We cannot use the D0/D1 UART if it is also used for STDIO. However,
the logic did not take into account whether `stdio_uart` was used at
all. This fixes the issue.
Calling `uart_poweroff()` when done with the UART test allows sharing
the underlying hardware e.g. to provide other peripheral interfaces.
One example of this would be the SERCOM3 on the Adafruit Metro M4
Express that is used to provide UART on D1/D0 and SPI on D11/D12/D13.
The GPIO IRQ tests had a side-effect that IRQs remained configured after
the test case was complete. This caused stray IRQs to trigger on
SAM0 MCUs and they consequently (and incorrectly) failed the test.
Calling `timer_init()` with unsupported frequencies on some MCUs just
selects the closest possible frequency. But e.g. on SAM0, using an
unsupported frequency will cause `timer_init()` to fail; which probably
is the better option.
However, a failing calling to `timer_init()` results in a test failure.
This is now worked around by using timer_query_freq() to select a
suitable timer frequency that is supported.
Use `test_utils_interactive_sync` for the following tests explicitly:
- tests/periph/timer_periodic
- tests/sys/posix_sleep
This is needed for accurate timestamping of the stdio received. The
tests will not pass without on `native` / `native64`.
In all other tests we added a delay after writing to the output buffer
of GPIO A before expected the input buffer of GPIO B (connected to A)
to reflect the change, but not in test_switch_dir().
This adds the delay here as well to make the test more robust in regard
to GPIO peripherals that react not as fast as the CPU can query them.
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.
A test intended to ensure that a configuration toggling the direction
of a GPIO two times restores the original configuration not only
compared the configuration at the two points in time, but also the
value of the input buffer. Since a floating input reads back random
values when not externally driven, the test was actually randomly
failing. Apparently I got lucky before consistently and this never
triggered until now.
This now clears the input value from both the configuration reported
before and after toggling the direction twice and should now indeed
succeed consistently.
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
This updates the test app to use the XFA shell interface and ztimer.
In addition, a shell command to power off the UART interface is added
to e.g. confirm that power consumption indeed goes down.
The `Makefile.ci` was intended to be read and generated by command
line utilities and the contents should look exactly like this:
```
BOARD_INSUFFICIENT_MEMORY += \
board_a \
board_b \
... \
#
```
No fancy schmancy, no `include`, no nothing. This fixes the format.
When it is difficult to navigate a function, it is overdue to split
it up :D
Also, no need to test for feature `gpio_ll_irq` in `test_irq()` *and*
before calling `test_irq()`.
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.
When using level triggered IRQs, a new IRQ flag may already have been
set while the IRQ callback is executed. Hence, we cannot just toggle
the output, but rather should drive it low/high for a level trigger on
high/low.
Also test `gpio_ll_query_conf()` for the disconnected state as well.
The default pin config is only a place holder anyway. But if it is
invalid at least on AVR most of the firmware is considered unreachable.
This updates the default GPIO config to something that should look
plausible to the compiler for all MCUs supporting GPIO LL, so that
ROM and RAM size in the CI start making sense.
Printing the newline after the state was printed is not optional.
This also moves the call to `gpio_ll_print_conf()` and `puts("")` to
a static function to safe enough ROM so that this still can be flashed
on `nucleo-l011k4`.
Also the LF is display inside the [...].
Now it is more obvious what characters came in on the RX port of the UART.
Here is an example:
2024-01-20 20:57:41,368 # send 1 ati
2024-01-20 20:57:41,368 # UART_DEV(1) TX: ati
> 2024-01-20 20:57:41,393 # Success: UART_DEV(1) RX: [ati\r\r\n]
2024-01-20 20:57:41,398 # Success: UART_DEV(1) RX: [SARA-N310-00X-00\r\n]
2024-01-20 20:57:41,399 # Success: UART_DEV(1) RX: [\r\n]
2024-01-20 20:57:41,399 # Success: UART_DEV(1) RX: [OK\r\n]
This application uses `soft_uart` to bit-bang the name of a number of
configured GPIO pins via said pins at 9600 Bd. This way attaching an
USB UART bridge to one pin at a time easily reveals which MCU GPIO
pin a given pin on a board corresponds to. This is useful when no
schematic and no silkscreen labeling is available, or when the
information is misleading or outright incorrect (looking at the
E180-ZG120B-TB).