EVE 1.0
gpio-ext.h
Go to the documentation of this file.
1 #ifndef DRIVER_GPIO_EXT_H
2 #define DRIVER_GPIO_EXT_H
3 /**********************************************************************/
4 /*
5  * Copyright (c) 2015, Jetro AS
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without modification,
9  * are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  * derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONRIBUTORS ``AS IS'' AND ANY EXPRESS
20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
22  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
28  * OF SUCH DAMAGE.
29  *
30  * This file is part of the EVE platform.
31  */
32 
33 /**
34  * \file
35  * @brief Abstract IO extender driver.
36  *
37  * @author SE, Jetro AS
38  */ /******************************************************************/
39 
40 #include <stdint.h>
41 #include <stddef.h>
42 #include <stdbool.h>
43 #include <lib/assert.h>
44 #include <dev/gpio.h>
45 #include <core/atomic.h>
46 #include <app_util_platform.h>
47 #include <dev/irq.h>
48 
49 /**
50  * \defgroup gpio_ext Extended GPIO driver
51  * \ingroup abstract
52  * \{
53  */
54 
55 /***********************************************************************
56  * Global defines
57  **********************************************************************/
58 #define GPIO_EXT_MAXPINS 16
59 
60 #ifndef DRIVER_PORT_EXT_INIT_TABLE
61  #error DRIVER_PORT_EXT_INIT_TABLE must point to a header file with pin init values
62 #endif
63 #define PINDEF(name, pin, mode, value, drive) name = pin,
64 enum pins_ext_t {
65  #include DRIVER_PORT_EXT_INIT_TABLE
66 };
67 #undef PINDEF
68 
69 /**
70  * GPIO driver SPI/I2C bus operation statuse
71  */
73 {
74  GPIO_EXT_STATUS_OK = 0, //!< Operation completed successfully
75  GPIO_EXT_STATUS_COMM_ERROR = 1, //!< SPI/I2C bus error
76 };
77 
78 /**
79  * Pin direction setting
80  */
82 {
83  DIR_UNCHANGED = 0, //!< Do not touch pin direction setting (leave as is)
84  DIR_IN = 1, //!< Set pin as input
85  DIR_OUT = 2, //!< Set pin as output
86 };
87 
88 /**
89  * Pin pullup / pulldown setting
90  */
92 {
93  PULL_UNCHANGED = 0, //!< Do not touch pin pullup / pulldown setting (leave as is)
94  PULL_NONE = 1, //!< Disconnect pin pullup / pulldown
95  PULL_UP = 2, //!< Pullup the pin
96  PULL_DOWN = 3, //!< Pulldown the pin
97 };
98 
99 struct gpio_ext_t;
100 
101 /**
102  * GPIO driver run-time state
103  */
105 {
106  uint16_t OutputValues; ///< Last values set for output
107  uint16_t InputValues; ///< Last read input values
108  uint16_t Direction; ///< Current direction state (0 = in, 1 = out)
109  uint16_t PullSelect; ///< Current pullup/pulldown state (0 = pulldown, 1 = pullup)
110  uint16_t PullEnable; ///< Current pull resistor enabled state (0 = off, 1 = on)
111  uint16_t InterruptStatus; ///< Pending interrupt status
112  uint16_t InterruptMask; ///< Internal interrupt bit mask (0 = disabled, 1 = enabled)
113  enum gpio_ext_status_t Status;
114 };
115 
116 /**
117  * PIN initial state configuration
118  */
120 {
121  uint8_t Value; //!< Initial pin value
122  enum gpio_mode_t Mode; //!< Initial pin direction / pullup / pulldown configuration
123  uint8_t Drive; //!< Pin drive force in %%
124 };
125 
126 /**********************************************************************/
127 /**
128  * @brief Virtual function initializes pins of an gpio expander to
129  * default values based on DRIVER_PORT_EXT_INIT_TABLE
130  **********************************************************************/
131 typedef void (*gpio_ext_init_t) (const struct gpio_ext_t* GpioExt);
132 
133 /**********************************************************************/
134 /**
135  * @brief Virtual function reads from gpio expander port
136  **********************************************************************/
137 typedef uint16_t (*gpio_ext_inport_t) (const struct gpio_ext_t* GpioExt);
138 
139 /**********************************************************************/
140 /**
141  * @brief Virtual function writes to gpio expander port / pin direction
142  * register / pull select register / pull enable register /
143  * interrupt enable register / latch enable register
144  **********************************************************************/
145 typedef void (*gpio_ext_outport_t)(const struct gpio_ext_t* GpioExt, uint16_t Value);
146 
147 /**********************************************************************/
148 /**
149  * @brief Virtual function sets drive force to gpio expander pins
150  **********************************************************************/
151 typedef void (*gpio_ext_setdrive_t)(const struct gpio_ext_t* GpioExt, uint8_t Values[]);
152 
153 /**
154  * GPIO driver virtual function table
155  */
157 {
158  gpio_ext_init_t GpioExtInit; //!< Function to initialize GPIO expander chip
159  gpio_ext_init_t GpioExtDisable; //!< Function to deinitialize GPIO expander chip
160  gpio_ext_inport_t GpioExtInPort; //!< Function to read from GPIO expander port
161  gpio_ext_outport_t GpioExtOutPort; //!< Function to write to GPIO expander port
162  gpio_ext_outport_t GpioExtSetDirection; //!< Function to set GPIO expander pins direction
163  gpio_ext_outport_t GpioExtSetPullSelect; //!< Function to set GPIO expander pullup/pulldown
164  gpio_ext_outport_t GpioExtSetPullEnable; //!< Function to enable/disable GPIO expander pullup/pulldowen
165  gpio_ext_outport_t GpioExtSetInterrupts; //!< Function to enable/disable GPIO expander interrupts
166  gpio_ext_setdrive_t GpioExtSetDrive; //!< Function to set GPIO expander drive force
167  gpio_ext_outport_t GpioExtSetLatch; //!< Function to enable/disable GPIO expander interrupt latch
168 };
169 
170 /**
171  * GPIO driver configuration data
172  */
174 {
175  const void* Impl; //!< Device specific configuration data
176  struct gpio_ext_state_t* State; //!< Address to struct with RAM variables used by the driver
177  uint8_t PinsNum; //!< Total number of pins on the port
178  uint16_t PortMask; //!< Bitmask of all the pins on the port (f.ex. 0xFF for 8-bit port, 0xFFFF for 16-bit)
179  const struct gpio_ext_init_pin_t PortsInit[16]; //!< Init values for each pin
180  const struct gpio_ext_api_t* Func; //!< Virtual functions table
181 };
182 
183 #define GPIO_EXT_VCALL(GpioExt, Fn) (GpioExt)->Func->Fn
184 
185 extern void GpioExtPortWriteImpl(const struct gpio_ext_t* GpioExt,
186  uint16_t* StoredValue, uint16_t DesiredValue,
187  uint16_t Mask, gpio_ext_outport_t Func);
188 
189 extern uint16_t GpioExtPortReadImpl(const struct gpio_ext_t* GpioExt,
190  bool TriggerInterrupt);
191 
192 extern void IrqTriggerExternal(void);
193 
194 /**
195  * @name Functions called from application programs
196  * @{
197  */
198 
199 /**
200  * @brief Initialize IO expander driver and chip.
201  *
202  * @param GpioExt Parameters for the IO port expander to be used
203  */
204 extern void GpioExtInit(const struct gpio_ext_t* GpioExt);
205 
206 /**
207  * @brief Write 16-bits data to the GPIO port.
208  *
209  * @param GpioExt Parameters for the IO port expander to be used
210  * @param Value Data to be written to IO expander ports
211  * @param Mask Mask of pins in the port to be written
212  */
213 static inline void GpioExtPortWrite(const struct gpio_ext_t* GpioExt,
214  uint16_t Value, uint16_t Mask)
215 {
216  uint16_t DesiredValue = Value & Mask;
217  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->OutputValues, DesiredValue,
218  Mask, GpioExt->Func->GpioExtOutPort);
219 }
220 
221 /**
222  * @brief Set bits by mask in the GPIO port.
223  *
224  * @param GpioExt Parameters for the IO port expander to be used
225  * @param Mask Mask of pins in the port to be written
226  */
227 static inline void GpioExtPortSet(const struct gpio_ext_t* GpioExt, uint16_t Mask)
228 {
229  GpioExtPortWrite(GpioExt, 0xFFFF, Mask);
230 }
231 
232 /**
233  * @brief Clear bits by mask in the GPIO port.
234  *
235  * @param GpioExt Parameters for the IO port expander to be used
236  * @param Mask Mask of pins in the port to be written
237  */
238 static inline void GpioExtPortClear(const struct gpio_ext_t* GpioExt, uint16_t Mask)
239 {
240  GpioExtPortWrite(GpioExt, 0x0000, Mask);
241 }
242 
243 /**
244  * @brief Invert bits by mask in the GPIO port.
245  *
246  * @param GpioExt Parameters for the IO port expander to be used
247  * @param Mask Mask of pins in the port to be written
248  */
249 static inline void GpioExtPortToggle(const struct gpio_ext_t* GpioExt, uint16_t Mask)
250 {
251  uint16_t DesiredValue = atomic_xor16(&GpioExt->State->OutputValues, Mask) & Mask;
252  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->OutputValues, DesiredValue,
253  Mask, GpioExt->Func->GpioExtOutPort);
254 }
255 
256 /**
257  * @brief Set/clear 1 pin in the GPIO port.
258  *
259  * @param GpioExt Parameters for the IO port expander to be used
260  * @param Pin Pin number to set/clear
261  * @param Value 0 clears the pin, any other value sets it to 1
262  */
263 static inline void GpioExtPinWrite(const struct gpio_ext_t* GpioExt, uint16_t Pin, uint16_t Value)
264 {
265  uint16_t Mask = (1 << Pin);
266  Value = Value ? Mask : 0;
267  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->OutputValues, Value,
268  Mask, GpioExt->Func->GpioExtOutPort);
269 }
270 
271 /**
272  * @brief Set 1 pin in the GPIO port.
273  *
274  * @param GpioExt Parameters for the IO port expander to be used
275  * @param Pin Pin number to set
276  */
277 static inline void GpioExtPinSet(const struct gpio_ext_t* GpioExt, uint16_t Pin)
278 {
279  uint16_t Mask = (1 << Pin);
280  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->OutputValues, Mask, Mask,
281  GpioExt->Func->GpioExtOutPort);
282 }
283 
284 /**
285  * @brief Clear 1 pin in the GPIO port.
286  *
287  * @param GpioExt Parameters for the IO port expander to be used
288  * @param Pin Pin number to clear
289  */
290 static inline void GpioExtPinClear(const struct gpio_ext_t* GpioExt, uint16_t Pin)
291 {
292  uint16_t Mask = (1 << Pin);
293  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->OutputValues, 0, Mask,
294  GpioExt->Func->GpioExtOutPort);
295 }
296 
297 /**
298  * @brief Invert 1 pin in the GPIO port.
299  *
300  * @param GpioExt Parameters for the IO port expander to be used
301  * @param Pin Pin number to toggle
302  */
303 static inline void GpioExtPinToggle(const struct gpio_ext_t* GpioExt, uint16_t Pin)
304 {
305  uint16_t Mask = (1 << Pin);
306  uint16_t Value = atomic_xor16(&GpioExt->State->OutputValues, Mask) & Mask;
307  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->OutputValues, Value, Mask,
308  GpioExt->Func->GpioExtOutPort);
309 }
310 
311 /**
312  * @brief Read all the pins from the GPIO port.
313  *
314  * @param GpioExt Parameters for the IO port expander to be used
315  * @return Port value
316  */
317 static inline uint16_t GpioExtPortRead(const struct gpio_ext_t* GpioExt)
318 {
319  return GpioExtPortReadImpl(GpioExt, true);
320 }
321 
322 /**
323  * @brief Read a pin value from the GPIO port.
324  *
325  * @param GpioExt Parameters for the IO port expander to be used
326  * @param Pin Global pin number to be read
327  * @return Pin value
328  */
329 static inline uint8_t GpioExtPinRead(const struct gpio_ext_t* GpioExt, uint16_t Pin)
330 {
331  uint16_t Port = GpioExtPortRead(GpioExt);
332  return (Port & (1 << Pin)) ? 1 : 0;
333 }
334 
335 /**
336  * @brief Set IO expander ports to input or output.
337  *
338  * @param GpioExt Parameters for the IO port expander to be used
339  * @param Direction 0 = input, 1 = output
340  * @param PullSelect 0 = pulldown, 1 = pullup
341  * @param PullEnable 0 = no pull, 1 = pullup/pulldown
342  * @param Mask Mask of pins in the port to be changed
343  */
344 extern void GpioExtPortSetup(const struct gpio_ext_t* GpioExt,
345  uint16_t Direction, uint16_t PullSelect,
346  uint16_t PullEnable, uint16_t Mask);
347 
348 
349 static inline uint16_t GpioExtInterruptsClear(const struct gpio_ext_t* GpioExt, uint16_t Mask)
350 {
351  /* Just set GpioExt->State->InterruptStatus, not interesting in port values */
352  GpioExtPortReadImpl(GpioExt, false);
353  uint16_t InterruptStatus = (GpioExt->State->InterruptStatus &
354  GpioExt->State->InterruptMask) &
355  ~(GpioExt->State->Direction);
356  GpioExt->State->InterruptStatus = InterruptStatus & ~Mask;
357  return (InterruptStatus);
358 }
359 
360 static inline uint16_t GpioExtInterruptsRead(const struct gpio_ext_t* GpioExt)
361 {
362  uint16_t InterruptStatus = GpioExtInterruptsClear(GpioExt, 0xFFFF);
363  GpioExt->State->InterruptStatus &= ~InterruptStatus;
364  return (InterruptStatus);
365 }
366 
367 static inline void GpioExtInterruptsEnable(const struct gpio_ext_t* GpioExt, uint16_t Mask)
368 {
369  uint16_t InterruptMask = GpioExt->State->InterruptMask | Mask;
370  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->InterruptMask, InterruptMask,
371  Mask, GpioExt->Func->GpioExtSetInterrupts);
372  if ((GpioExt->State->InterruptMask & GpioExt->State->InterruptStatus) &
373  ~GpioExt->State->Direction)
375 }
376 
377 static inline void GpioExtInterruptsDisable(const struct gpio_ext_t* GpioExt, uint16_t Mask)
378 {
379  uint16_t InterruptMask = GpioExt->State->InterruptMask & ~Mask;
380  GpioExtPortWriteImpl(GpioExt, &GpioExt->State->InterruptMask, InterruptMask,
381  Mask, GpioExt->Func->GpioExtSetInterrupts);
382 }
383 
384 static inline void GpioExtSetDrive(const struct gpio_ext_t* GpioExt, uint8_t Values[])
385 {
386  GPIO_EXT_VCALL(GpioExt, GpioExtSetDrive)(GpioExt, Values);
387 }
388 
389 static inline void GpioExtSetLatch(const struct gpio_ext_t* GpioExt, uint16_t Mask)
390 {
391  GPIO_EXT_VCALL(GpioExt, GpioExtSetLatch)(GpioExt, Mask);
392 }
393 
394 /**
395  * @brief Check status of GpioExt operations and reset status to GPIO_EXT_STATUS_OK.
396  *
397  * @param GpioExt Parameters for the IO port expander to be used
398  * @return GPIO_EXT_STATUS_OK if there were no errors since the last check,
399  * errorcode otherwise.
400  */
401 static inline uint8_t GpioExtCheckStatus(const struct gpio_ext_t* GpioExt)
402 {
403  uint8_t ret = GpioExt->State->Status;
404  GpioExt->State->Status = GPIO_EXT_STATUS_OK;
405  return ret;
406 }
407 
408 /** @} */
409 
410 /** \} gpio_ext */
411 
412 #endif //DRIVER_GPIO_EXT_H
static void GpioExtPortWrite(const struct gpio_ext_t *GpioExt, uint16_t Value, uint16_t Mask)
Write 16-bits data to the GPIO port.
Definition: gpio-ext.h:213
gpio_ext_outport_t GpioExtOutPort
Function to write to GPIO expander port.
Definition: gpio-ext.h:161
gpio_ext_pin_pull_t
Definition: gpio-ext.h:91
Operation completed successfully.
Definition: gpio-ext.h:74
static void GpioExtPortToggle(const struct gpio_ext_t *GpioExt, uint16_t Mask)
Invert bits by mask in the GPIO port.
Definition: gpio-ext.h:249
uint16_t InterruptMask
Internal interrupt bit mask (0 = disabled, 1 = enabled)
Definition: gpio-ext.h:112
uint16_t InterruptStatus
Pending interrupt status.
Definition: gpio-ext.h:111
Do not touch pin pullup / pulldown setting (leave as is)
Definition: gpio-ext.h:93
gpio_ext_outport_t GpioExtSetPullSelect
Function to set GPIO expander pullup/pulldown.
Definition: gpio-ext.h:163
gpio_ext_inport_t GpioExtInPort
Function to read from GPIO expander port.
Definition: gpio-ext.h:160
Driver for port initialisazion and IO functions for nRF52 uC.
gpio_ext_outport_t GpioExtSetInterrupts
Function to enable/disable GPIO expander interrupts.
Definition: gpio-ext.h:165
Do not touch pin direction setting (leave as is)
Definition: gpio-ext.h:83
static uint8_t GpioExtCheckStatus(const struct gpio_ext_t *GpioExt)
Check status of GpioExt operations and reset status to GPIO_EXT_STATUS_OK.
Definition: gpio-ext.h:401
uint8_t Drive
Pin drive force in %%.
Definition: gpio-ext.h:123
void(* gpio_ext_init_t)(const struct gpio_ext_t *GpioExt)
Virtual function initializes pins of an gpio expander to default values based on DRIVER_PORT_EXT_INIT...
Definition: gpio-ext.h:131
const struct gpio_ext_api_t * Func
Virtual functions table.
Definition: gpio-ext.h:180
gpio_ext_setdrive_t GpioExtSetDrive
Function to set GPIO expander drive force.
Definition: gpio-ext.h:166
gpio_mode_t
Definition: gpio.h:97
uint16_t PullSelect
Current pullup/pulldown state (0 = pulldown, 1 = pullup)
Definition: gpio-ext.h:109
Pulldown the pin.
Definition: gpio-ext.h:96
static void GpioExtPinWrite(const struct gpio_ext_t *GpioExt, uint16_t Pin, uint16_t Value)
Set/clear 1 pin in the GPIO port.
Definition: gpio-ext.h:263
static void GpioExtPortClear(const struct gpio_ext_t *GpioExt, uint16_t Mask)
Clear bits by mask in the GPIO port.
Definition: gpio-ext.h:238
void IrqTriggerExternal(void)
uint16_t(* gpio_ext_inport_t)(const struct gpio_ext_t *GpioExt)
Virtual function reads from gpio expander port.
Definition: gpio-ext.h:137
uint16_t InputValues
Last read input values.
Definition: gpio-ext.h:107
gpio_ext_outport_t GpioExtSetPullEnable
Function to enable/disable GPIO expander pullup/pulldowen.
Definition: gpio-ext.h:164
uint16_t Direction
Current direction state (0 = in, 1 = out)
Definition: gpio-ext.h:108
Pullup the pin.
Definition: gpio-ext.h:95
uint8_t Value
Initial pin value.
Definition: gpio-ext.h:121
uint16_t PortMask
Bitmask of all the pins on the port (f.ex. 0xFF for 8-bit port, 0xFFFF for 16-bit) ...
Definition: gpio-ext.h:178
uint8_t PinsNum
Total number of pins on the port.
Definition: gpio-ext.h:177
uint16_t atomic_xor16(volatile uint16_t *p, uint16_t value)
static void GpioExtPinSet(const struct gpio_ext_t *GpioExt, uint16_t Pin)
Set 1 pin in the GPIO port.
Definition: gpio-ext.h:277
Header file for the EVE atomic primitives set.
const void * Impl
Device specific configuration data.
Definition: gpio-ext.h:175
static void GpioExtPortSet(const struct gpio_ext_t *GpioExt, uint16_t Mask)
Set bits by mask in the GPIO port.
Definition: gpio-ext.h:227
uint16_t OutputValues
Last values set for output.
Definition: gpio-ext.h:106
static void GpioExtPinClear(const struct gpio_ext_t *GpioExt, uint16_t Pin)
Clear 1 pin in the GPIO port.
Definition: gpio-ext.h:290
gpio_ext_status_t
Definition: gpio-ext.h:72
static uint16_t GpioExtPortRead(const struct gpio_ext_t *GpioExt)
Read all the pins from the GPIO port.
Definition: gpio-ext.h:317
static void GpioExtPinToggle(const struct gpio_ext_t *GpioExt, uint16_t Pin)
Invert 1 pin in the GPIO port.
Definition: gpio-ext.h:303
gpio_ext_outport_t GpioExtSetDirection
Function to set GPIO expander pins direction.
Definition: gpio-ext.h:162
gpio_ext_pin_dir_t
Definition: gpio-ext.h:81
struct gpio_ext_state_t * State
Address to struct with RAM variables used by the driver.
Definition: gpio-ext.h:176
SPI/I2C bus error.
Definition: gpio-ext.h:75
gpio_ext_init_t GpioExtInit
Function to initialize GPIO expander chip.
Definition: gpio-ext.h:158
void GpioExtInit(const struct gpio_ext_t *GpioExt)
Initialize IO expander driver and chip.
void(* gpio_ext_outport_t)(const struct gpio_ext_t *GpioExt, uint16_t Value)
Virtual function writes to gpio expander port / pin direction register / pull select register / pull ...
Definition: gpio-ext.h:145
Disconnect pin pullup / pulldown.
Definition: gpio-ext.h:94
gpio_ext_outport_t GpioExtSetLatch
Function to enable/disable GPIO expander interrupt latch.
Definition: gpio-ext.h:167
External IRQ abstraction.
void(* gpio_ext_setdrive_t)(const struct gpio_ext_t *GpioExt, uint8_t Values[])
Virtual function sets drive force to gpio expander pins.
Definition: gpio-ext.h:151
void GpioExtPortSetup(const struct gpio_ext_t *GpioExt, uint16_t Direction, uint16_t PullSelect, uint16_t PullEnable, uint16_t Mask)
Set IO expander ports to input or output.
Set pin as input.
Definition: gpio-ext.h:84
Set pin as output.
Definition: gpio-ext.h:85
gpio_ext_init_t GpioExtDisable
Function to deinitialize GPIO expander chip.
Definition: gpio-ext.h:159
static uint8_t GpioExtPinRead(const struct gpio_ext_t *GpioExt, uint16_t Pin)
Read a pin value from the GPIO port.
Definition: gpio-ext.h:329
uint16_t PullEnable
Current pull resistor enabled state (0 = off, 1 = on)
Definition: gpio-ext.h:110