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.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. More...
 
#define GPIO_PORT(num)   implementation_specific
 Get the gpio_port_t value of the port identified by num. More...
 
#define GPIO_PORT_NUM(port)   implementation_specific
 Get the number of the GPIO port belonging to the given gpio_port_t value. More...
 
#define GPIO_PULL_NUMOF
 The number of distinct supported pull resistor strengths. More...
 
#define GPIO_DRIVE_NUMOF
 The number of distinct supported drive strengths. More...
 
#define GPIO_SLEW_NUMOF
 The number of distinct supported slew rates. More...
 

Typedefs

typedef uintptr_t gpio_port_t
 GPIO port type. More...
 

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

static bool is_gpio_port_num_valid (uint_fast8_t num)
 Check if the given number is a valid argument for GPIO_PORT. More...
 
int gpio_ll_init (gpio_port_t port, uint8_t pin, gpio_conf_t conf)
 Initialize the given GPIO pin as specified. More...
 
gpio_conf_t gpio_ll_query_conf (gpio_port_t port, uint8_t pin)
 Retrieve the current configuration of a GPIO pin. More...
 
void gpio_ll_print_conf_common (const gpio_conf_t conf)
 INTERNAL, use gpio_ll_print_conf instead. More...
 
void gpio_ll_print_conf (const gpio_conf_t conf)
 Utility function to print a given GPIO configuration to stdio. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
static void gpio_ll_switch_dir_output (gpio_port_t port, uword_t outputs)
 Turn GPIO pins specified by the bitmask outputs to outputs. More...
 
static void gpio_ll_switch_dir_input (gpio_port_t port, uword_t inputs)
 Turn GPIO pins specified by the bitmask inputs to inputs. More...
 
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. More...
 
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. More...
 
static void * gpio_port_unpack_addr (gpio_port_t port)
 Extract a data pointer that was packed by gpio_port_pack_addr. More...
 

Variables

typedef gpio_conf_t
 GPIO pin configuration. More...
 

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. More...
 
static const gpio_conf_t gpio_ll_in_pd
 A standard configuration for a generic input pin with pull down resistor. More...
 
static const gpio_conf_t gpio_ll_in_pu
 A standard configuration for a generic input pin with pull up resistor. More...
 
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. More...
 
static const gpio_conf_t gpio_ll_out
 A standard configuration for a generic push-pull output pin. More...
 
static const gpio_conf_t gpio_ll_od
 A standard configuration for a generic floating open drain output. More...
 
static const gpio_conf_t gpio_ll_od_pu
 A standard configuration for a generic open drain output with pull up. More...
 

Macro Definition Documentation

◆ GPIO_DRIVE_NUMOF

#define GPIO_DRIVE_NUMOF
Value:
@ GPIO_DRIVE_STRONG
Use a strong drive strength.
Definition: gpio_ll.h:277
@ GPIO_DRIVE_WEAK
Use a weak drive strength.
Definition: gpio_ll.h:276
@ GPIO_DRIVE_STRONGEST
Use the strongest drive strength.
Definition: gpio_ll.h:278
@ GPIO_DRIVE_WEAKEST
Use the weakest drive strength.
Definition: gpio_ll.h:275

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 290 of file gpio_ll.h.

◆ GPIO_PORT

#define GPIO_PORT (   num)    implementation_specific

Get the gpio_port_t value of the port identified by num.

Note
If num is a compile time constant, this is guaranteed to be suitable for a constant initializer.

Typically this will be something like (GPIO_BASE_ADDR + num * sizeof(struct vendor_gpio_reg))

Definition at line 106 of file gpio_ll.h.

◆ GPIO_PORT_NUM

#define GPIO_PORT_NUM (   port)    implementation_specific

Get the number of the GPIO port belonging to the given gpio_port_t value.

Note
If port is a compile time constant, this is guaranteed to be suitable for a constant initializer.
Precondition
port is the return value of GPIO_PORT

For every supported port number n the following assert() must not blow up:

#define assert(cond)
abort the program if assertion is false
Definition: assert.h:137
#define GPIO_PORT_NUM(port)
Get the number of the GPIO port belonging to the given gpio_port_t value.
Definition: gpio_ll.h:126
#define GPIO_PORT(num)
Get the gpio_port_t value of the port identified by num.
Definition: gpio_ll.h:106

Definition at line 126 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:244
@ GPIO_PULL_WEAK
Use a weak pull resistor.
Definition: gpio_ll.h:245
@ GPIO_PULL_STRONG
Use a strong pull resistor.
Definition: gpio_ll.h:246
@ GPIO_PULL_STRONGEST
Use the strongest pull resistor.
Definition: gpio_ll.h:247

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 261 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:308
@ GPIO_SLEW_FAST
let the output voltage level rise/fall fast
Definition: gpio_ll.h:311
@ GPIO_SLEW_SLOW
let the output voltage level rise/fall slowly
Definition: gpio_ll.h:310
@ GPIO_SLEW_FASTEST
let the output voltage level rise/fall as fast as possible
Definition: gpio_ll.h:312

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 325 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 274 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 243 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 225 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 307 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 133 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_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 702 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 680 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  inputs 
)
inlinestatic

Turn GPIO pins specified by the bitmask inputs to inputs.

Parameters
[in]portGPIO port to modify
[in]inputsBitmask specifying the GPIO pins to set in input mode
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.
Note
This is a makeshift solution to implement bit-banging of bidirectional protocols on less sophisticated GPIO peripherals that do not support open drain mode.
Warning
Use open drain mode instead, if supported.

◆ gpio_ll_switch_dir_output()

static void gpio_ll_switch_dir_output ( gpio_port_t  port,
uword_t  outputs 
)
inlinestatic

Turn GPIO pins specified by the bitmask outputs to outputs.

Parameters
[in]portGPIO port to modify
[in]outputsBitmask specifying the GPIO pins to set in output mode
Precondition
The feature gpio_ll_switch_dir is available
Each affected GPIO pin is either configured as input or as push-pull output.
Note
This is a makeshift solution to implement bit-banging of bidirectional protocols on less sophisticated GPIO peripherals that do not support open drain mode.
Warning
Use open drain mode instead, if supported.

◆ 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:702
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.
Definition: architecture.h:70
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_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 391 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:226
@ GPIO_INPUT
Use pin as input.
Definition: gpio_ll.h:176

A standard configuration for a generic floating input pin.

Definition at line 417 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:228

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

Definition at line 426 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:229

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 450 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:227

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

Definition at line 435 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:157

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 471 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 484 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:144

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

Note
The pin will have an initial value of 0.

Definition at line 460 of file gpio_ll.h.