Peripheral GPIO Low-Level API. More...
Peripheral GPIO Low-Level API.
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.
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.h |
Peripheral GPIO Low-Level API. | |
Data Structures | |
struct | gpio_conf_t |
GPIO pin configuration. More... | |
Macros | |
#define | GPIO_PORT_UNDEF UINTPTR_MAX |
Magic "undefined GPIO port" value. | |
#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. | |
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, const gpio_conf_t *conf) |
Initialize the given GPIO pin as specified. More... | |
void | gpio_ll_query_conf (gpio_conf_t *dest, 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_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 | |
const gpio_conf_t | gpio_ll_in |
A standard configuration for a generic floating input pin. | |
const gpio_conf_t | gpio_ll_in_pd |
A standard configuration for a generic input pin with pull down resistor. | |
const gpio_conf_t | gpio_ll_in_pu |
A standard configuration for a generic input pin with pull up resistor. | |
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... | |
const gpio_conf_t | gpio_ll_out |
A standard configuration for a generic push-pull output pin. More... | |
const gpio_conf_t | gpio_ll_od |
A standard configuration for a generic floating open drain output. More... | |
const gpio_conf_t | gpio_ll_od_pu |
A standard configuration for a generic open drain output with pull up. More... | |
#define GPIO_DRIVE_NUMOF |
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.
#define GPIO_PORT | ( | num | ) | implementation_specific |
Get the gpio_port_t value of the port identified by num
.
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))
#define GPIO_PORT_NUM | ( | port | ) | implementation_specific |
Get the number of the GPIO port belonging to the given gpio_port_t value.
port
is a compile time constant, this is guaranteed to be suitable for a constant initializer.port
is the return value of GPIO_PORTFor every supported port number n the following assert()
must not blow up:
#define GPIO_PULL_NUMOF |
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.
#define GPIO_SLEW_NUMOF |
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.
Enumeration of drive strength options.
enum gpio_pull_strength_t |
Enumeration of pull resistor values.
enum gpio_pull_t |
enum 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.
enum gpio_state_t |
Enumeration of GPIO states (direction)
Enumerator | |||||||
---|---|---|---|---|---|---|---|
GPIO_OUTPUT_PUSH_PULL | Use pin as output in push-pull configuration.
| ||||||
GPIO_OUTPUT_OPEN_DRAIN | Use pin as output in open collector configuration.
| ||||||
GPIO_OUTPUT_OPEN_SOURCE | Use pin as output in open emitter configuration.
| ||||||
GPIO_INPUT | Use pin as input. | ||||||
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. The implementation should aim to reduce power consumption of the pin when this state is entered, if this is feasible.
Once all GPIOs of a GPIO port are disconnected, the implementation is allowed to power off the whole GPIO port again to conserve power. |
|
inlinestatic |
Perform an reg &= ~mask
operation on the I/O register of the port.
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.
[in] | port | port to modify |
[in] | mask | bitmask containing the pins to clear |
int gpio_ll_init | ( | gpio_port_t | port, |
uint8_t | pin, | ||
const gpio_conf_t * | conf | ||
) |
Initialize the given GPIO pin as specified.
[in] | port | port the pin to initialize belongs to |
[in] | pin | number of the pin to initialize |
[in] | conf | configuration to apply |
0 | success |
-ENOTSUP | GPIO state or pull resistor configuration not supported |
0
is returned. -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. 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
. port
and pin
- concurrent initialization of different pins on the same port is supported. The underlying implementation might perform locking where needed.
|
inlinestatic |
Helper to use gpio_ll_write side-effect free.
[in] | port | port that should be written to |
[in] | mask | bitmask of the pins to write to |
[in] | value | value to write to port |
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
|
inlinestatic |
Same as gpio_ll_prepare_write(port, UWORD_MAX, value)
, but faster.
[in] | port | port that should be written to |
[in] | value | value to write to port |
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.
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).
void gpio_ll_print_conf | ( | const gpio_conf_t * | conf | ) |
Utility function to print a given GPIO configuration to stdio.
[in] | conf | Configuration to print |
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
void gpio_ll_query_conf | ( | gpio_conf_t * | dest, |
gpio_port_t | port, | ||
uint8_t | pin | ||
) |
Retrieve the current configuration of a GPIO pin.
[out] | dest | Write the current config of the given GPIO here |
[in] | port | GPIO port the pin to query is located at |
[in] | pin | Number of the pin to query within port |
port
and pin
refer to an existing GPIO pin and dest
can be written to. Expect blowing assertions otherwise.
|
inlinestatic |
Get the current input value of all GPIO pins of the given port as bitmask.
[in] | port | port to read |
Unless technically impossible, this must be implemented as a single read instruction.
|
inlinestatic |
Get the current output value of all GPIO pins of the given port as bitmask.
[in] | port | port to read |
Unless technically impossible, this must be implemented as a single read instruction.
|
inlinestatic |
Perform an reg |= mask
operation on the I/O register of the port.
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.
[in] | port | port to modify |
[in] | mask | bitmask containing the pins to set |
|
inlinestatic |
Perform an reg ^= mask
operation on the I/O register of the port.
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.
[in] | port | port to modify |
[in] | mask | bitmask containing the pins to toggle |
|
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 .
[in] | port | port to modify |
[in] | state | Opaque value produced by gpio_ll_prepare_write |
Usage:
Unless technically impossible, this must be implemented as a single write instruction.
|
inlinestatic |
Pack a pointer into a gpio_port_t.
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)addr
can be reconstructed by calling gpio_port_unpack_addr
|
inlinestatic |
Extract a data pointer that was packed by gpio_port_pack_addr.
NULL | port 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.
|
inlinestatic |
Check if the given number is a valid argument for GPIO_PORT.
[in] | num | port number to check |
true | the MCU used has a GPIO port with that number |
false | the MCU used has NO GPIO port with that number |
|
extern |
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.
|
extern |
A standard configuration for a generic floating open drain output.
|
extern |
A standard configuration for a generic open drain output with pull up.
|
extern |
A standard configuration for a generic push-pull output pin.