This changes the API of xfa from
XFA(array_name, prio) type element_name = INITIALIZER;
to
XFA(type, array_name, prio) element_name = INITIALIZER;
this allows forcing natural alignment of the type, fixing failing tests
on `native64`.
Since https://github.com/RIOT-OS/RIOT/pull/20935 gpio_write()
uses a `bool` instead of an `int`. This does the same treatment for
`gpio_read()`.
This does indeed add an instruction to `gpio_read()` implementations.
However, users caring about an instruction more are better served with
`gpio_ll_read()` anyway. And `gpio_read() == 1` is often seen in
newcomer's code, which would now work as expected.
It turns out that the feature to switch the GPIO direction quickly
is not only a way to emulate open drain / open source mode for less
sophisticated GPIO peripherals that do not natively support it.
It also enables tri-state output (push-pull high, push-pull low,
high impedance), which is useful e.g. for driven charlieplexed LEDs
quickly.
This changes the API by introducing a `gpio_ll_prepare_switch_dir()`
function that prepares the value used to identify which pins should
be switched to input or to output mode. This is useful for GPIO
peripherals in which the GPIO mode register does not allocate one bit
per pin (so that only the direction is given there), such as the one
for STM32. This allows an STM32 implementation in which preparing the
bitmask needed to modify the direction of pins is not trivial.
The assumption that every MCU has this feature turned out wrong. Hence,
add a feature to allow testing for support of edge triggered IRQs on
both flanks.
The API was based on the assumption that GPIO ports are mapped in memory
sanely, so that a `GPIO_PORT(num)` macro would work allow for constant
folding when `num` is known and still be efficient when it is not.
Some MCUs, however, will need a look up tables to efficiently translate
GPIO port numbers to the port's base address. This will prevent the use
of such a `GPIO_PORT(num)` macro in constant initializers.
As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros
for each GPIO port present (regardless of MCU naming scheme), as well as
`GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port
naming scheme uses letters rather than numbers.
These can be defined as macros to the peripheral base address even when
those are randomly mapped into the address space. In addition, a C
function `gpio_port()` replaces the role of the `GPIO_PORT()` and
`gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will
still be implemented as efficient as possible and will allow constant
folding where it was formerly possible. Hence, there is no downside for
MCUs with sane peripheral memory mapping, but it is highly beneficial
for the crazy ones.
There are also two benefits for the non-crazy MCUs:
1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>`
- This directly benefits the test in `tests/periph/gpio_ll`, which
can now provide a valid GPIO port for each and every board
- Writing to invalid memory mapped I/O addresses was treated as
triggering undefined behavior by the compiler and used as a
optimization opportunity
2. We can now detect at compile time if the naming scheme of the MCU
uses letters or numbers, and produce more user friendly output.
- This is directly applied in the test app
We occasionally have some public `foo.h` header that includes a private
`foo_arch.h` header. Users are expected to include the `foo.h` header
and not the `foo_arch.h`. However, clangd will claim that the `#include`
of `foo.h` is unused if only functions / macros/ types / ... from
`foor_arch.h` is used and nothing from `foo.h`.
This adds the `IWYU pragma: export` comment to the include of
`foo_arch.h` in `foo.h`, so that clangd treats functions / macros /
types provided by `foo_arch.h` as if they were instead provided by
`foo.h`, which fixes the false positives.
If not included before, IS_USED macro from modules.h is undefined,
leading to such errors:
error: missing binary operator before token "("
Signed-off-by: Gilles DOFFE <g.doffe@gmail.com>
This adds two functions:
void gpio_ll_switch_dir_output(gpio_port_t port, uword_t outputs);
void gpio_ll_switch_dir_input(gpio_port_t port, uword_t inputs);
The first configures GPIO pins specified by a bitmask as output, the
second configures the specified pins as input.
The main use case is to allow bit-banging bidirectional protocols using
more basic GPIO peripherals that do not implement open drain mode, such
as found e.g. on MSP430, ATmega, or SAM0.
It is not intended to implement this feature on modern MCUs with
sophisticated GPIO peripherals.
This adds the features
- periph_gpio_ll_input_pull_down:
To indicate support for input mode with internal pull down
- periph_gpio_ll_input_pull_keep:
To indicate support for input mode with internal resistor
pulling towards current level
- periph_gpio_ll_input_pull_up:
To indicate support for input mode with internal pull up
- periph_gpio_ll_disconnect:
To indicate a GPIO can be disconnected
- periph_gpio_ll_open_drain:
To indicate support for open drain mode
- periph_gpio_ll_open_drain_pull_up:
To indicate support for open drain mode with internal pull up
- periph_gpio_ll_open_source:
To indicate support for open source mode
- periph_gpio_ll_open_source_pull_down:
To indicate support for open source mode with internal pull down
The documentation on the state `GPIO_DISCONNECT` was a bit vague. The
API doc said it should disconnect the GPIO from all peripherals, the
test also tested them for being electrically disconnected.
The documentation in both the test and the API is extended to point out
that a GPIO indeed SHOULD be in high impedance state, but that user
MUST NOT expect that this requested is honored by every implementation
and for every GPIO pin.
In the test it is also pointed out that failing the test for a GPIO
in the `GPIO_DISCONNECT` state being electrically disconnected is for
some pins expected, and that the test should be just run again with
different GPIOs. The test intentionally tests for a feature not provided
by every GPIO pin rather than warning on a failure: The effort to just
flash and run the test again with different GPIOs is relatively low, but
it does confirm correct behavior of the API.
This commit optimizes the `gpio_conf_t` type in the following
regards:
- The "base" `gpio_conf_t` is stripped from members that only some
platforms support, e.g. drive strength, slew rate, and disabling of
the Schmitt Trigger are no longer universally available but
platform-specific extensions
- The `gpio_conf_t` is now crammed into a bit-field that is 8 bit or
16 bit wide. This allows for storing lots of them e.g. in
`driver_foo_params_t` or `uart_conf_t` etc.
- A `union` of the `struct` with bit-field members and a `bits` is used
to allow accessing all bits in a simple C statement and to ensure
alignment for efficient handling of the type
Co-authored-by: Gunar Schorcht <gunar@schorcht.net>