Loading...
Searching...
No Matches

Peripheral GPIO Low-Level API. More...

Detailed Description

Peripheral GPIO Low-Level API.

Warning
This API is not stable yet and intended for internal use only as of now.

Design Goals

This API aims to provide low-level access to GPIOs with as little abstraction and overhead in place as possible for the hot code paths, while providing a relatively high-level and feature complete API for the configuration of GPIO pins. The former is to enable sophisticated use cases such at bit-banging parallel protocols, bit-banging at high data rates, bit-banging with strict timing requirements, or any combination of these. The latter is to expose as much of the features the (arguably) most important peripheral of the MCU as possible.

It is possible to implement the high level pin-based GPIO API of RIOT, GPIO, on top of this API. It is expected that for many use cases the high level API will still remain the API of choice, since it is more concise an easier to use.

Note that this API is likely to be faster moving than the high level GPIO API, as it intents to match the hardware features more closely. Hence, new support for new MCUs are more likely to result in API changes here. This is another reason why only users interested in the low level access to GPIOs should be using the this low level API, while the high level API will cater all the LED blinking and button sensing use cases with a more convenient and more very stable interface.

Thread Safety

All functions provided by this API have to be implemented in a thread-safe manner, except for gpio_ll_prepare_write and gpio_ll_prepare_write_all_outputs. If the read-modify-write operations gpio_ll_set, gpio_ll_clear, and gpio_ll_toggle can be done atomically in hardware with predictable timing, this must be used in the implementation. Otherwise IRQs have to be disabled during read-modify-write sequences. Calls to gpio_ll_write are inherently thread-safe and lock-less, but sharing pins on the same port between threads is still requires a lock between the calls to gpio_ll_prepare_write and gpio_ll_write in the general case.

Under no circumstances two threads may call gpio_ll_init on the same port / pin combination concurrently.

Modules

 IRQ Support in Peripheral GPIO Low-Level API
 IRQ Support in Peripheral GPIO Low-Level API.
 

Files

file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll_arch.h
 GPIO Low-level API implementation for the GD32V GPIO peripheral.
 
file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll_arch.h
 CPU specific part of the Peripheral GPIO Low-Level API.
 
file  gpio_ll.h
 Peripheral GPIO Low-Level API.
 

Data Structures

union  gpio_conf_esp32
 GPIO pin configuration for ESP32/ESP32Cx/ESP32Sx MCUs. More...
 
union  gpio_conf_gd32v
 GPIO pin configuration for GD32V MCUs. More...
 
union  gpio_conf_nrf5x
 GPIO pin configuration for nRF5x MCUs. More...
 
union  gpio_conf_sam0
 GPIO pin configuration for SAM0 MCUs. More...
 
union  gpio_conf_stm32
 GPIO pin configuration for STM32 MCUs. More...
 
union  gpio_conf_minimal
 Public members of gpio_conf_t More...
 

Macros

#define GPIO_PORT_UNDEF   UINTPTR_MAX
 Magic "undefined GPIO port" value.
 
#define GPIO_PORT_NUMBERING_ALPHABETIC   implementation_specific
 Indicates whether GPIO ports are enumerated alphabetically (1) or numerically (0).
 
#define GPIO_PORT_0   implementation_specific
 Get the gpio_port_t value of the port labeled 0.
 
#define GPIO_PULL_NUMOF
 The number of distinct supported pull resistor strengths.
 
#define GPIO_DRIVE_NUMOF
 The number of distinct supported drive strengths.
 
#define GPIO_SLEW_NUMOF
 The number of distinct supported slew rates.
 

Typedefs

typedef uintptr_t gpio_port_t
 GPIO port type.
 

Enumerations

enum  gpio_state_t {
  GPIO_OUTPUT_PUSH_PULL , GPIO_OUTPUT_OPEN_DRAIN , GPIO_OUTPUT_OPEN_SOURCE , GPIO_INPUT ,
  GPIO_USED_BY_PERIPHERAL , GPIO_DISCONNECT
}
 Enumeration of GPIO states (direction) More...
 
enum  gpio_pull_t { GPIO_FLOATING , GPIO_PULL_UP , GPIO_PULL_DOWN , GPIO_PULL_KEEP }
 Enumeration of pull resistor configurations. More...
 
enum  gpio_pull_strength_t { GPIO_PULL_WEAKEST , GPIO_PULL_WEAK , GPIO_PULL_STRONG , GPIO_PULL_STRONGEST }
 Enumeration of pull resistor values. More...
 
enum  gpio_drive_strength_t { GPIO_DRIVE_WEAKEST , GPIO_DRIVE_WEAK , GPIO_DRIVE_STRONG , GPIO_DRIVE_STRONGEST }
 Enumeration of drive strength options. More...
 
enum  gpio_slew_t { GPIO_SLEW_SLOWEST , GPIO_SLEW_SLOW , GPIO_SLEW_FAST , GPIO_SLEW_FASTEST }
 Enumeration of slew rate settings. More...
 

Functions

gpio_port_t gpio_port (uword_t num)
 Get the gpio_port_t value of the port number num.
 
uword_t gpio_port_num (gpio_port_t port)
 Get the number of the GPIO port port refers to.
 
static bool is_gpio_port_num_valid (uint_fast8_t num)
 Check if the given number is a valid argument for gpio_port.
 
int gpio_ll_init (gpio_port_t port, uint8_t pin, gpio_conf_t conf)
 Initialize the given GPIO pin as specified.
 
gpio_conf_t gpio_ll_query_conf (gpio_port_t port, uint8_t pin)
 Retrieve the current configuration of a GPIO pin.
 
void gpio_ll_print_conf_common (const gpio_conf_t conf)
 INTERNAL, use gpio_ll_print_conf instead.
 
void gpio_ll_print_conf (const gpio_conf_t conf)
 Utility function to print a given GPIO configuration to stdio.
 
static uword_t gpio_ll_read (gpio_port_t port)
 Get the current input value of all GPIO pins of the given port as bitmask.
 
static uword_t gpio_ll_read_output (gpio_port_t port)
 Get the current output value of all GPIO pins of the given port as bitmask.
 
static void gpio_ll_set (gpio_port_t port, uword_t mask)
 Perform an reg |= mask operation on the I/O register of the port.
 
static void gpio_ll_clear (gpio_port_t port, uword_t mask)
 Perform an reg &= ~mask operation on the I/O register of the port.
 
static void gpio_ll_toggle (gpio_port_t port, uword_t mask)
 Perform an reg ^= mask operation on the I/O register of the port.
 
static uword_t gpio_ll_prepare_write_all_outputs (gpio_port_t port, uword_t value)
 Same as gpio_ll_prepare_write(port, UWORD_MAX, value), but faster.
 
static uword_t gpio_ll_prepare_write (gpio_port_t port, uword_t mask, uword_t value)
 Helper to use gpio_ll_write side-effect free.
 
static uword_t gpio_ll_prepare_switch_dir (uword_t mask)
 Prepare bitmask for use with gpio_ll_switch_dir_output and gpio_ll_switch_dir_input.
 
static void gpio_ll_switch_dir_output (gpio_port_t port, uword_t pins)
 Turn GPIO pins specified by pins (obtained from gpio_ll_prepare_switch_dir) to outputs.
 
static void gpio_ll_switch_dir_input (gpio_port_t port, uword_t pins)
 Turn GPIO pins specified by pins (obtained from gpio_ll_prepare_switch_dir) to inputs.
 
static void gpio_ll_write (gpio_port_t port, uword_t state)
 Perform a masked write operation on the I/O register of the port.
 
static gpio_port_t gpio_get_port (gpio_t pin)
 Extract the gpio_port_t from a gpio_t
 
static uint8_t gpio_get_pin_num (gpio_t pin)
 Extract the pin number from a gpio_t
 
static gpio_port_t gpio_port_pack_addr (void *addr)
 Pack a pointer into a gpio_port_t.
 
static void * gpio_port_unpack_addr (gpio_port_t port)
 Extract a data pointer that was packed by gpio_port_pack_addr.
 

Variables

typedef gpio_conf_t
 GPIO pin configuration.
 

Commonly used GPIO LL configuration presets

Warning
These are not available in C++

C++ requires initializers to be provided in declaration order and contain explicit initialization for each and every field. However, the actual layout and the number of members of gpio_conf_t depends on the implementation, so that implementations can expose advanced features such as pull strength, driver strength, skew rate, mux settings, etc. The API mandates that those extra fields will have a sane default value when implicitly initialized with 0, as done here in C.

This doesn't work in C++, unless multiplying the maintenance burden by the number of implementations by having each implementation provide this by hand. This is not acceptable.

static const gpio_conf_t gpio_ll_in
 A standard configuration for a generic floating input pin.
 
static const gpio_conf_t gpio_ll_in_pd
 A standard configuration for a generic input pin with pull down resistor.
 
static const gpio_conf_t gpio_ll_in_pu
 A standard configuration for a generic input pin with pull up resistor.
 
static const gpio_conf_t gpio_ll_in_pk
 A standard configuration for a generic input pin with pull resistor to keep signal at bus level.
 
static const gpio_conf_t gpio_ll_out
 A standard configuration for a generic push-pull output pin.
 
static const gpio_conf_t gpio_ll_od
 A standard configuration for a generic floating open drain output.
 
static const gpio_conf_t gpio_ll_od_pu
 A standard configuration for a generic open drain output with pull up.
 

GPIO port aliases for alphabetic enumeration

#define GPIO_PORT_A   GPIO_PORT_0
 Alias of ref GPIO_PORT_0
 
#define GPIO_PORT_B   GPIO_PORT_1
 Alias of ref GPIO_PORT_1
 
#define GPIO_PORT_C   GPIO_PORT_2
 Alias of ref GPIO_PORT_2
 
#define GPIO_PORT_D   GPIO_PORT_3
 Alias of ref GPIO_PORT_3
 
#define GPIO_PORT_E   GPIO_PORT_4
 Alias of ref GPIO_PORT_4
 
#define GPIO_PORT_F   GPIO_PORT_5
 Alias of ref GPIO_PORT_5
 
#define GPIO_PORT_G   GPIO_PORT_6
 Alias of ref GPIO_PORT_6
 
#define GPIO_PORT_H   GPIO_PORT_7
 Alias of ref GPIO_PORT_7
 
#define GPIO_PORT_I   GPIO_PORT_8
 Alias of ref GPIO_PORT_8
 
#define GPIO_PORT_J   GPIO_PORT_9
 Alias of ref GPIO_PORT_9
 
#define GPIO_PORT_K   GPIO_PORT_10
 Alias of ref GPIO_PORT_10
 
#define GPIO_PORT_L   GPIO_PORT_11
 Alias of ref GPIO_PORT_11
 
#define GPIO_PORT_M   GPIO_PORT_12
 Alias of ref GPIO_PORT_12
 
#define GPIO_PORT_N   GPIO_PORT_13
 Alias of ref GPIO_PORT_13
 
#define GPIO_PORT_O   GPIO_PORT_14
 Alias of ref GPIO_PORT_14
 
#define GPIO_PORT_P   GPIO_PORT_15
 Alias of ref GPIO_PORT_15
 

Macro Definition Documentation

◆ GPIO_DRIVE_NUMOF

#define GPIO_DRIVE_NUMOF
Value:
@ GPIO_DRIVE_STRONG
Use a strong drive strength.
Definition gpio_ll.h:302
@ GPIO_DRIVE_WEAK
Use a weak drive strength.
Definition gpio_ll.h:301
@ GPIO_DRIVE_STRONGEST
Use the strongest drive strength.
Definition gpio_ll.h:303
@ GPIO_DRIVE_WEAKEST
Use the weakest drive strength.
Definition gpio_ll.h:300

The number of distinct supported drive strengths.

This equals the number of drive strengths actually supported and can be less than four, if one or more enumeration values in gpio_drive_strength_t have the same numeric value. Note that some pins might have more options than others.

Definition at line 315 of file gpio_ll.h.

◆ GPIO_PORT_0

#define GPIO_PORT_0   implementation_specific

Get the gpio_port_t value of the port labeled 0.

Note
For MCUs that use letters instead of numbers, this will be an alias for GPIO_PORT_A
Some MCUs will not start with Port 0 / Port A, but rather with Port 1 (e.g. MSP430) or Port B (e.g. ATmega328P). It will be undefined when unavailable
There will also be GPIO_PORT_1, GPIO_PORT_2, etc. when there are corresponding GPIO ports in hardware.

Definition at line 122 of file gpio_ll.h.

◆ GPIO_PORT_A

#define GPIO_PORT_A   GPIO_PORT_0

Alias of ref GPIO_PORT_0

Definition at line 914 of file gpio_ll.h.

◆ GPIO_PORT_B

#define GPIO_PORT_B   GPIO_PORT_1

Alias of ref GPIO_PORT_1

Definition at line 920 of file gpio_ll.h.

◆ GPIO_PORT_C

#define GPIO_PORT_C   GPIO_PORT_2

Alias of ref GPIO_PORT_2

Definition at line 926 of file gpio_ll.h.

◆ GPIO_PORT_D

#define GPIO_PORT_D   GPIO_PORT_3

Alias of ref GPIO_PORT_3

Definition at line 932 of file gpio_ll.h.

◆ GPIO_PORT_E

#define GPIO_PORT_E   GPIO_PORT_4

Alias of ref GPIO_PORT_4

Definition at line 938 of file gpio_ll.h.

◆ GPIO_PORT_F

#define GPIO_PORT_F   GPIO_PORT_5

Alias of ref GPIO_PORT_5

Definition at line 944 of file gpio_ll.h.

◆ GPIO_PORT_G

#define GPIO_PORT_G   GPIO_PORT_6

Alias of ref GPIO_PORT_6

Definition at line 950 of file gpio_ll.h.

◆ GPIO_PORT_H

#define GPIO_PORT_H   GPIO_PORT_7

Alias of ref GPIO_PORT_7

Definition at line 956 of file gpio_ll.h.

◆ GPIO_PORT_I

#define GPIO_PORT_I   GPIO_PORT_8

Alias of ref GPIO_PORT_8

Definition at line 962 of file gpio_ll.h.

◆ GPIO_PORT_J

#define GPIO_PORT_J   GPIO_PORT_9

Alias of ref GPIO_PORT_9

Definition at line 968 of file gpio_ll.h.

◆ GPIO_PORT_K

#define GPIO_PORT_K   GPIO_PORT_10

Alias of ref GPIO_PORT_10

Definition at line 974 of file gpio_ll.h.

◆ GPIO_PORT_L

#define GPIO_PORT_L   GPIO_PORT_11

Alias of ref GPIO_PORT_11

Definition at line 980 of file gpio_ll.h.

◆ GPIO_PORT_M

#define GPIO_PORT_M   GPIO_PORT_12

Alias of ref GPIO_PORT_12

Definition at line 986 of file gpio_ll.h.

◆ GPIO_PORT_N

#define GPIO_PORT_N   GPIO_PORT_13

Alias of ref GPIO_PORT_13

Definition at line 992 of file gpio_ll.h.

◆ GPIO_PORT_NUMBERING_ALPHABETIC

#define GPIO_PORT_NUMBERING_ALPHABETIC   implementation_specific

Indicates whether GPIO ports are enumerated alphabetically (1) or numerically (0).

Note
You can use both GPIO_PORT_A and GPIO_PORT_0 to refer to the first GPIO port in RIOT, regardless of the naming scheme used by the MCU the app is compiled for. This macro is useful e.g. for pretty-printing.

Definition at line 106 of file gpio_ll.h.

◆ GPIO_PORT_O

#define GPIO_PORT_O   GPIO_PORT_14

Alias of ref GPIO_PORT_14

Definition at line 998 of file gpio_ll.h.

◆ GPIO_PORT_P

#define GPIO_PORT_P   GPIO_PORT_15

Alias of ref GPIO_PORT_15

Definition at line 1004 of file gpio_ll.h.

◆ GPIO_PORT_UNDEF

#define GPIO_PORT_UNDEF   UINTPTR_MAX

Magic "undefined GPIO port" value.

Definition at line 93 of file gpio_ll.h.

◆ GPIO_PULL_NUMOF

#define GPIO_PULL_NUMOF
Value:
@ GPIO_PULL_WEAKEST
Use the weakest (highest Ohm value) resistor.
Definition gpio_ll.h:269
@ GPIO_PULL_WEAK
Use a weak pull resistor.
Definition gpio_ll.h:270
@ GPIO_PULL_STRONG
Use a strong pull resistor.
Definition gpio_ll.h:271
@ GPIO_PULL_STRONGEST
Use the strongest pull resistor.
Definition gpio_ll.h:272

The number of distinct supported pull resistor strengths.

This equals the number of pull resistor strengths actually supported and can be less than four, if one or more enumeration values in gpio_pull_strength_t have the same numeric value. Note that: a) some pins might have more options than others and b) it could be possible that there are e.g. two pull up resistors to pick from, but only one pull down resistor.

Definition at line 286 of file gpio_ll.h.

◆ GPIO_SLEW_NUMOF

#define GPIO_SLEW_NUMOF
Value:
@ GPIO_SLEW_SLOWEST
let the output voltage level rise/fall as slow as possible
Definition gpio_ll.h:333
@ GPIO_SLEW_FAST
let the output voltage level rise/fall fast
Definition gpio_ll.h:336
@ GPIO_SLEW_SLOW
let the output voltage level rise/fall slowly
Definition gpio_ll.h:335
@ GPIO_SLEW_FASTEST
let the output voltage level rise/fall as fast as possible
Definition gpio_ll.h:337

The number of distinct supported slew rates.

This equals the number of slew rates actually supported and can be less than four, if one or more enumeration values in gpio_drive_strength_t have the same numeric value. Note that some pins might have more options than others.

Definition at line 350 of file gpio_ll.h.

Typedef Documentation

◆ gpio_port_t

typedef uintptr_t gpio_port_t

GPIO port type.

Definition at line 87 of file gpio_ll.h.

Enumeration Type Documentation

◆ gpio_drive_strength_t

Enumeration of drive strength options.

Note
Depending on the implementation, some (or even all!) constants can have the same numeric value if less than four drive strength options to pick from. For obvious reasons, only neighboring values are allowed to have the same numeric value.
Enumerator
GPIO_DRIVE_WEAKEST 

Use the weakest drive strength.

GPIO_DRIVE_WEAK 

Use a weak drive strength.

GPIO_DRIVE_STRONG 

Use a strong drive strength.

GPIO_DRIVE_STRONGEST 

Use the strongest drive strength.

Definition at line 299 of file gpio_ll.h.

◆ gpio_pull_strength_t

Enumeration of pull resistor values.

Note
Depending on the implementation, some (or even all!) constants can have the same numeric value if less than four pull resistors per direction are provided. For obvious reasons, only neighboring values are allowed to have the same numeric value.
Enumerator
GPIO_PULL_WEAKEST 

Use the weakest (highest Ohm value) resistor.

GPIO_PULL_WEAK 

Use a weak pull resistor.

GPIO_PULL_STRONG 

Use a strong pull resistor.

GPIO_PULL_STRONGEST 

Use the strongest pull resistor.

Definition at line 268 of file gpio_ll.h.

◆ gpio_pull_t

Enumeration of pull resistor configurations.

Enumerator
GPIO_FLOATING 

No pull ups nor pull downs enabled.

GPIO_PULL_UP 

Pull up resistor enabled.

GPIO_PULL_DOWN 

Pull down resistor enabled.

GPIO_PULL_KEEP 

Keep the signal at current logic level with pull up/down resistors.

Definition at line 250 of file gpio_ll.h.

◆ gpio_slew_t

Enumeration of slew rate settings.

Reducing the slew rate can be useful to limit the high frequency noise emitted by a GPIO pin. On the other hand, a high frequency signal cannot be generated if the slew rate is too slow.

Warning
The numeric values are implementation defined and multiple constants can have the same numeric value, if an implementation supports fewer slew rates. An implementation only supporting a single slew rate can have all constants set to a value of zero.
Enumerator
GPIO_SLEW_SLOWEST 

let the output voltage level rise/fall as slow as possible

GPIO_SLEW_SLOW 

let the output voltage level rise/fall slowly

GPIO_SLEW_FAST 

let the output voltage level rise/fall fast

GPIO_SLEW_FASTEST 

let the output voltage level rise/fall as fast as possible

Definition at line 332 of file gpio_ll.h.

◆ gpio_state_t

Enumeration of GPIO states (direction)

Enumerator
GPIO_OUTPUT_PUSH_PULL 

Use pin as output in push-pull configuration.

Note
This is supported and implemented on all MCUs.
Logical Value Electrical Behavior
0 Low
1 High
GPIO_OUTPUT_OPEN_DRAIN 

Use pin as output in open collector configuration.

Note
The feature periph_gpio_ll_open_drain is used to indicate support for this GPIO mode. However, it may not be available on all pins.
Logical Value Electrical Behavior
0 Low
1 High Impedance (Disconnected)
GPIO_OUTPUT_OPEN_SOURCE 

Use pin as output in open emitter configuration.

Note
The feature periph_gpio_ll_open_source is used to indicate support for this GPIO mode. However, it may not be available on all pins.
Logical Value Electrical Behavior
0 High Impedance (Disconnected)
1 High
GPIO_INPUT 

Use pin as input.

Note
This is supported and implemented on all MCUs.
GPIO_USED_BY_PERIPHERAL 

The GPIO pin is used by a peripheral.

Note that calling gpio_ll_init with this state is implementation defined behavior, as implementation specific additional details (such as which peripheral to connect the pin to) are needed. An implementation may choose to not support this at all.

However, it is strongly encouraged that gpio_ll_query_conf uses this state to indicate a GPIO pin is currently used by a peripheral (e.g. as ADC input, I2C data/clock pin, etc.).

GPIO_DISCONNECT 

Disconnect pin from all peripherals.

Note
This may be an alias for GPIO_INPUT when the MCU does not support support disconnecting GPIO pins from the GPIO peripheral. The feature periph_gpio_ll_disconnect indicates that disconnecting pins from all peripherals (including the GPIO peripheral) is supported.

The implementation should aim to reduce power consumption of the pin when this state is entered, if this is feasible. For pins where it is possible and sensible, this should electrically disconnect them (high impedance).

Warning
If a given pin will not only be disconnected from peripherals but also enter an high impedance state is implementation defined and may differ from pin to pin.
Note
Pull resistors can still be requested in this mode. This can be useful e.g. for keeping an UART TXD pin from emitting noise while the UART peripheral is powered off. But not every implementation will support this.

Once all GPIOs of a GPIO port are disconnected, the implementation is allowed to power off the whole GPIO port again to conserve power.

Definition at line 158 of file gpio_ll.h.

Function Documentation

◆ gpio_ll_clear()

static void gpio_ll_clear ( gpio_port_t  port,
uword_t  mask 
)
inlinestatic

Perform an reg &= ~mask operation on the I/O register of the port.

Note
The behavior regarding pins not configured as GPIO_OUTPUT_PUSH_PULL or as GPIO_OUTPUT_OPEN_DRAIN is implementation defined.
Warning
Portable code must set the bits in mask that do not correspond to pins configured as output to zero.

On hardware that supports implementing this as a single write instruction, this must be implemented as such. Otherwise this read-modify-write will disable IRQs to still behave atomically.

Parameters
[in]portport to modify
[in]maskbitmask containing the pins to clear

◆ gpio_ll_init()

int gpio_ll_init ( gpio_port_t  port,
uint8_t  pin,
gpio_conf_t  conf 
)

Initialize the given GPIO pin as specified.

Parameters
[in]portport the pin to initialize belongs to
[in]pinnumber of the pin to initialize
[in]confconfiguration to apply
Return values
0success
-ENOTSUPGPIO state or pull resistor configuration not supported
Warning
If the configuration of the Schmitt trigger, the drive strength, or the pull resistor strength are not supported, the closest supported value will be chosen instead and 0 is returned.
Note that hardware GPIO peripherals may have shared building blocks. Those SHOULD be handed out by the implementation in first-come-first-served fashion. (E.g. if there is only one pull up resistor per port that can be connected to any pin of that port, typically the first pin on the port configured as pull up will succeed and subsequent configuration as pull ups for other pins on that port will get an -ENOTSUP.) For that reason, an application might need to optimize the order in which it configures GPIO pins to get the most suitable overall configuration supported by the hardware.
Note
An application having strict requirements can use gpio_ll_query_conf afterwards to verify that the used configuration is indeed within spec. It is often sensible to omit these checks if DEVELHELP is disabled. An application can rely on that the configuration of pin pin at port port will not be changed as side-effect of operations performed on other pins. That is, once gpio_ll_init returns the configuration details are settled and may only change due to subsequent calls to gpio_ll_init with the same values for port and pin.
Precondition
No concurrent context is calling this function for the same combination of port and pin - concurrent initialization of different pins on the same port is supported. The underlying implementation might perform locking where needed.

◆ gpio_ll_prepare_switch_dir()

static uword_t gpio_ll_prepare_switch_dir ( uword_t  mask)
inlinestatic

Prepare bitmask for use with gpio_ll_switch_dir_output and gpio_ll_switch_dir_input.

Parameters
[in]maskbitmask specifying the pins to switch the direction of
Returns
Value to use in gpio_ll_switch_dir_output or gpio_ll_switch_dir_input

Definition at line 743 of file gpio_ll.h.

◆ gpio_ll_prepare_write()

static uword_t gpio_ll_prepare_write ( gpio_port_t  port,
uword_t  mask,
uword_t  value 
)
inlinestatic

Helper to use gpio_ll_write side-effect free.

Parameters
[in]portport that should be written to
[in]maskbitmask of the pins to write to
[in]valuevalue to write to port
Returns
Value to call gpio_ll_write with

The caller needs to make sure that no concurrent changes (this includes configuration changes, writing, clearing, setting or toggling GPIO pins) are performed.

See gpio_ll_write on how to use this function

Definition at line 727 of file gpio_ll.h.

◆ gpio_ll_prepare_write_all_outputs()

static uword_t gpio_ll_prepare_write_all_outputs ( gpio_port_t  port,
uword_t  value 
)
inlinestatic

Same as gpio_ll_prepare_write(port, UWORD_MAX, value), but faster.

Parameters
[in]portport that should be written to
[in]valuevalue to write to port
Returns
Value to call gpio_ll_write with

On most platforms this function will just pass value through unmodified, becoming a no-op (and costing neither CPU cycles, nor RAM, nor ROM). Hence, this function will only cost you if your platform really requires preparation of any sorts.

Note
If all pins on port are known to be configured as output, calls to this functions can be omitted.

The caller needs to make sure that no concurrent changes (this includes configuration changes, writing, clearing, setting or toggling GPIO pins) are performed.

This function can be used to prevent side-effects on non-output pins of a port when writing to it, e.g. when the output buffer is multiplexed with the pull configuration for input pins (such as on ATmega MCUs).

Definition at line 705 of file gpio_ll.h.

◆ gpio_ll_print_conf()

void gpio_ll_print_conf ( const gpio_conf_t  conf)

Utility function to print a given GPIO configuration to stdio.

Parameters
[in]confConfiguration to print

◆ gpio_ll_print_conf_common()

void gpio_ll_print_conf_common ( const gpio_conf_t  conf)

INTERNAL, use gpio_ll_print_conf instead.

This function prints the public API part of gpio_conf_t to stdio. The intention is that implementations that extend gpio_conf_t to contain more members overwrite gpio_ll_print_conf and call this function to print the common members

◆ gpio_ll_query_conf()

gpio_conf_t gpio_ll_query_conf ( gpio_port_t  port,
uint8_t  pin 
)

Retrieve the current configuration of a GPIO pin.

Parameters
[in]portGPIO port the pin to query is located at
[in]pinNumber of the pin to query within port
Returns
The current config of the given GPIO here
Precondition
port and pin refer to an existing GPIO pin and dest can be written to. Expect blowing assertions otherwise.
Note
gpio_conf_minimal::initial_value should be set to the current value of the pin, so that no shadow log of the initial value is needed to consult.

◆ gpio_ll_read()

static uword_t gpio_ll_read ( gpio_port_t  port)
inlinestatic

Get the current input value of all GPIO pins of the given port as bitmask.

Parameters
[in]portport to read
Returns
The current value of the input register of the given GPIO port
Note
The value of unconfigured pins and pins configured as GPIO_DISCONNECT or GPIO_OUTPUT_PUSH_PULL is implementation defined.

Unless technically impossible, this must be implemented as a single read instruction.

◆ gpio_ll_read_output()

static uword_t gpio_ll_read_output ( gpio_port_t  port)
inlinestatic

Get the current output value of all GPIO pins of the given port as bitmask.

Parameters
[in]portport to read
Returns
The current value of the output register of the given GPIO port
Note
The value of unconfigured pins and pins configured as GPIO_INPUT or GPIO_OUTPUT_PUSH_PULL is implementation defined.

Unless technically impossible, this must be implemented as a single read instruction.

◆ gpio_ll_set()

static void gpio_ll_set ( gpio_port_t  port,
uword_t  mask 
)
inlinestatic

Perform an reg |= mask operation on the I/O register of the port.

Note
The behavior regarding pins not configured as GPIO_OUTPUT_PUSH_PULL or as GPIO_OUTPUT_OPEN_DRAIN is implementation defined.
Warning
Portable code must set the bits in mask that do not correspond to pins configured as output to zero.

On hardware that supports implementing this as a single write instruction, this must be implemented as such. Otherwise this read-modify-write will disable IRQs to still behave atomically.

Parameters
[in]portport to modify
[in]maskbitmask containing the pins to set

◆ gpio_ll_switch_dir_input()

static void gpio_ll_switch_dir_input ( gpio_port_t  port,
uword_t  pins 
)
inlinestatic

Turn GPIO pins specified by pins (obtained from gpio_ll_prepare_switch_dir) to inputs.

Parameters
[in]portGPIO port to modify
[in]pinsOutput of gpio_ll_prepare_switch_dir
Precondition
The feature gpio_ll_switch_dir is available
Each affected GPIO pin is either configured as input or as push-pull output.
Warning
The state of the output register may be intermixed with the input configuration. Specifically, on AVR the output register enables/disables the internal pull up, on SAM0 MCUs the output register controls the pull resistor direction (if the pull resistor is enabled). Hence, the bits in the output register of the pins switched to input should be restored just after this call.

◆ gpio_ll_switch_dir_output()

static void gpio_ll_switch_dir_output ( gpio_port_t  port,
uword_t  pins 
)
inlinestatic

Turn GPIO pins specified by pins (obtained from gpio_ll_prepare_switch_dir) to outputs.

Parameters
[in]portGPIO port to modify
[in]pinsOutput of gpio_ll_prepare_switch_dir
Precondition
The feature gpio_ll_switch_dir is available
Each affected GPIO pin is either configured as input or as push-pull output.

◆ gpio_ll_toggle()

static void gpio_ll_toggle ( gpio_port_t  port,
uword_t  mask 
)
inlinestatic

Perform an reg ^= mask operation on the I/O register of the port.

Note
The behavior regarding pins not configured as GPIO_OUTPUT_PUSH_PULL or as GPIO_OUTPUT_OPEN_DRAIN is implementation defined.
Warning
Portable code must set the bits in mask that do not correspond to pins configured as output to zero.

On hardware that supports implementing this as a single write instruction, this must be implemented as such. Otherwise this read-modify-write will disable IRQs to still behave atomically.

Parameters
[in]portport to modify
[in]maskbitmask containing the pins to toggle

◆ gpio_ll_write()

static void gpio_ll_write ( gpio_port_t  port,
uword_t  state 
)
inlinestatic

Perform a masked write operation on the I/O register of the port.

Some platforms multiplex the "write" I/O register with additional functions e.g. for input pin configuration. To prevent unintentional side effects prepare a value using gpio_ll_prepare_write that will set the bits of non-output pins as needed to not have side effects on the state the GPIO port had when calling gpio_ll_prepare_write .

Parameters
[in]portport to modify
[in]stateOpaque value produced by gpio_ll_prepare_write

Usage:

// emit a square wave from two pins with a phase shift of pi between the
// waves, e.g.:
// pin1: _⎍_⎍_⎍_⎍_⎍_⎍_⎍_⎍_⎍
// pin2: ⎍_⎍_⎍_⎍_⎍_⎍_⎍_⎍_⎍_
void square_wave(gpio_port_t port, uint8_t pin1, uint8_t pin2)
{
uword_t mask = (1U << pin1) | (1U << pin2);
uword_t state1 = gpio_ll_prepare_write(port, mask, 1U << pin1);
uword_t state2 = gpio_ll_prepare_write(port, mask, 1U << pin2);
while (1) {
gpio_ll_write(port, state1);
gpio_ll_write(port, state2);
}
}
static uword_t gpio_ll_prepare_write(gpio_port_t port, uword_t mask, uword_t value)
Helper to use gpio_ll_write side-effect free.
Definition gpio_ll.h:727
static void gpio_ll_write(gpio_port_t port, uword_t state)
Perform a masked write operation on the I/O register of the port.
uintptr_t gpio_port_t
GPIO port type.
Definition gpio_ll.h:87
uint< NUM > _t uword_t
Word sized unsigned integer.
Note
If the configuration of the used port changes between the calls of gpio_ll_prepare_write and gpio_ll_write the write will still have undesired side effects on the configuration of input pins if the platform multiplexes the write register with configuration for input pins. It is expected that the user of the API either exclusively uses a GPIO port or synchronizes with other users to update the prepared value on configuration changes.

Unless technically impossible, this must be implemented as a single write instruction.

◆ gpio_port()

gpio_port_t gpio_port ( uword_t  num)

Get the gpio_port_t value of the port number num.

Parameters
[in]numThe number of the port to get
Precondition
num is a valid GPIO port number. An implementation may follow the "garbage in, garbage out" philosophy.
Note
If the MCU uses an alphabetic naming scheme, number 0 refers to port A.
Warning
This may involve accessing a lookup table, prefer e.g. using GPIO_PORT_0 over gpio_port(0) if the port number is known at compile time.

◆ gpio_port_num()

uword_t gpio_port_num ( gpio_port_t  port)

Get the number of the GPIO port port refers to.

Parameters
[in]portThe port to get the number of
Precondition
port is a valid GPIO port. An implementation may follow the "garbage in, garbage out" philosophy.
Warning
This may involve iterating over a lookup table, prefer using e.g. 0 instead of gpio_port_num(GPIO_PORT_0) if the port number is known at compile time.

In other words n == gpio_port_num(gpio_port(n)) for every n that is a valid port number.

◆ gpio_port_pack_addr()

static gpio_port_t gpio_port_pack_addr ( void *  addr)
inlinestatic

Pack a pointer into a gpio_port_t.

Precondition
The address in addr is not NULL and points to a regular memory region (e.g. anywhere in .data, .rodata, .bss or an address returned by malloc() and friends)
Returns
A value that is distinguishable from any valid port reference and from which addr can be reconstructed by calling gpio_port_unpack_addr

◆ gpio_port_unpack_addr()

static void * gpio_port_unpack_addr ( gpio_port_t  port)
inlinestatic

Extract a data pointer that was packed by gpio_port_pack_addr.

Returns
The exact address previously packed by gpio_port_pack_addr
Return values
NULLport is a valid GPIO port

The motivation is that a high level API can multiplex peripheral GPIOs and GPIOs provided by port extenders. That high level API could pack pointers to the device descriptors of port extenders into a gpio_port_t and use this function to check if the port is a peripheral port (the return value is NULL), or retrieve the device descriptor.

◆ is_gpio_port_num_valid()

static bool is_gpio_port_num_valid ( uint_fast8_t  num)
inlinestatic

Check if the given number is a valid argument for gpio_port.

Parameters
[in]numport number to check
Return values
truethe MCU used has a GPIO port with that number
falsethe MCU used has NO GPIO port with that number

Variable Documentation

◆ gpio_conf_t

typedef gpio_conf_t

GPIO pin configuration.

Warning
The layout of this structure is implementation dependent and additional implementation specific fields might be present. For this reason, this structure must be initialized using designated initializers or zeroing out the whole contents using `memset() before initializing the individual fields.

See gpio_conf_minimal for the minimal structure fields to expect.

Definition at line 416 of file gpio_ll.h.

◆ gpio_ll_in

const gpio_conf_t gpio_ll_in
static
Initial value:
= {
.state = GPIO_INPUT,
.pull = GPIO_FLOATING,
}
@ GPIO_FLOATING
No pull ups nor pull downs enabled.
Definition gpio_ll.h:251
@ GPIO_INPUT
Use pin as input.
Definition gpio_ll.h:201

A standard configuration for a generic floating input pin.

Definition at line 442 of file gpio_ll.h.

◆ gpio_ll_in_pd

const gpio_conf_t gpio_ll_in_pd
static
Initial value:
= {
.state = GPIO_INPUT,
.pull = GPIO_PULL_DOWN,
}
@ GPIO_PULL_DOWN
Pull down resistor enabled.
Definition gpio_ll.h:253

A standard configuration for a generic input pin with pull down resistor.

Definition at line 451 of file gpio_ll.h.

◆ gpio_ll_in_pk

const gpio_conf_t gpio_ll_in_pk
static
Initial value:
= {
.state = GPIO_INPUT,
.pull = GPIO_PULL_KEEP,
}
@ GPIO_PULL_KEEP
Keep the signal at current logic level with pull up/down resistors.
Definition gpio_ll.h:254

A standard configuration for a generic input pin with pull resistor to keep signal at bus level.

This means, when the input reaches a 0, a pull down resistor is applied. If input reaches 1, a pull up is applied instead.

Note
This is a rather uncommon feature. MCUs that support this are RP2040.

Definition at line 475 of file gpio_ll.h.

◆ gpio_ll_in_pu

const gpio_conf_t gpio_ll_in_pu
static
Initial value:
= {
.state = GPIO_INPUT,
.pull = GPIO_PULL_UP,
}
@ GPIO_PULL_UP
Pull up resistor enabled.
Definition gpio_ll.h:252

A standard configuration for a generic input pin with pull up resistor.

Definition at line 460 of file gpio_ll.h.

◆ gpio_ll_od

const gpio_conf_t gpio_ll_od
static
Initial value:
= {
.pull = GPIO_FLOATING,
.initial_value = true,
}
@ GPIO_OUTPUT_OPEN_DRAIN
Use pin as output in open collector configuration.
Definition gpio_ll.h:182

A standard configuration for a generic floating open drain output.

Note
The pin will have an initial value of 1 (which in absence of an external pull up resistor will be high impedance).

Definition at line 496 of file gpio_ll.h.

◆ gpio_ll_od_pu

const gpio_conf_t gpio_ll_od_pu
static
Initial value:
= {
.pull = GPIO_PULL_UP,
.initial_value = true,
}

A standard configuration for a generic open drain output with pull up.

Note
The pin will have an initial value of 1 (so that the pull up will pill the line high).

Definition at line 509 of file gpio_ll.h.

◆ gpio_ll_out

const gpio_conf_t gpio_ll_out
static
Initial value:
= {
.initial_value = false,
}
@ GPIO_OUTPUT_PUSH_PULL
Use pin as output in push-pull configuration.
Definition gpio_ll.h:169

A standard configuration for a generic push-pull output pin.

Note
The pin will have an initial value of 0.

Definition at line 485 of file gpio_ll.h.