Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers/periph_gpio_ll: change API to access GPIO ports #20639

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

maribu
Copy link
Member

@maribu maribu commented Apr 29, 2024

Contribution description

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

Testing procedure

The test app in tests/periph/gpio_ll should still work.

Issues/PRs references

@maribu maribu added Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care. CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Apr 29, 2024
@github-actions github-actions bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: tests Area: tests and testing framework Platform: AVR Platform: This PR/issue effects AVR-based platforms Area: drivers Area: Device drivers Area: boards Area: Board ports Platform: ESP Platform: This PR/issue effects ESP-based platforms Area: cpu Area: CPU/MCU ports labels Apr 29, 2024
@maribu maribu changed the title Drivers/periph gpio ll/api change drivers/periph_gpio_ll: change API to access GPIO ports Apr 29, 2024
@riot-ci
Copy link

riot-ci commented Apr 29, 2024

Murdock results

✔️ PASSED

09e8d9e boards/stm32: use GPIO LL for LEDs

Success Failures Total Runtime
10066 0 10066 11m:26s

Artifacts

@maribu
Copy link
Member Author

maribu commented Apr 29, 2024

ESP32

make BOARD=esp32-mh-et-live-minikit BUILD_IN_DOCKER=1 flash test-with-config
Launching build container using image "docker.io/riot/riotbuild:latest".
podman run --rm --tty --userns keep-id -v '/etc/zoneinfo/Europe/Berlin:/etc/localtime:ro' -v '/home/maribu/Repos/software/RIOT/master:/data/riotbuild/riotbase:delegated' -v '/home/maribu/.cargo/registry:/data/riotbuild/.cargo/registry:delegated' -v '/home/maribu/.cargo/git:/data/riotbuild/.cargo/git:delegated' -e 'RIOTBASE=/data/riotbuild/riotbase' -e 'CCACHE_BASEDIR=/data/riotbuild/riotbase' -v '/home/maribu/.cache/RIOT:/data/riotbuild/build:delegated' -e 'BUILD_DIR=/data/riotbuild/build' -e 'RIOTPROJECT=/data/riotbuild/riotbase' -e 'RIOTCPU=/data/riotbuild/riotbase/cpu' -e 'RIOTBOARD=/data/riotbuild/riotbase/boards' -e 'RIOTMAKE=/data/riotbuild/riotbase/makefiles'    -v '/home/maribu/Repos/software/boards/riot:/data/riotbuild/external/riot:delegated' -v '/home/maribu/Repos/software/miot-pcbs/RIOT/boards:/data/riotbuild/external/boards:delegated'  -e 'BOARD=esp32-mh-et-live-minikit' -e 'DISABLE_MODULE=' -e 'DEFAULT_MODULE=test_utils_interactive_sync test_utils_print_stack_usage' -e 'FEATURES_REQUIRED=periph_gpio_ll' -e 'FEATURES_BLACKLIST=' -e 'FEATURES_OPTIONAL=periph_gpio_ll_irq periph_gpio_ll_irq_level_triggered_high periph_gpio_ll_irq_level_triggered_low' -e 'USEMODULE=ztimer_usec' -e 'USEPKG='  -w '/data/riotbuild/riotbase/tests/periph/gpio_ll/' 'docker.io/riot/riotbuild:latest' make 'BOARD=esp32-mh-et-live-minikit'  'EXTERNAL_BOARD_DIRS=/data/riotbuild/external/riot /data/riotbuild/external/boards'  
Building application "tests_gpio_ll" for "esp32-mh-et-live-minikit" with CPU "esp32".

"make" -C /data/riotbuild/riotbase/pkg/esp32_sdk/ 
"make" -C /data/riotbuild/riotbase/boards/common/init
"make" -C /data/riotbuild/riotbase/boards/esp32-mh-et-live-minikit
"make" -C /data/riotbuild/riotbase/boards/common/esp32
"make" -C /data/riotbuild/riotbase/boards/common/esp32x
"make" -C /data/riotbuild/riotbase/core
"make" -C /data/riotbuild/riotbase/core/lib
"make" -C /data/riotbuild/riotbase/cpu/esp32
"make" -C /data/riotbuild/riotbase/cpu/esp32/bootloader
esptool.py v3.2-dev
Merged 1 ELF section
"make" -C /data/riotbuild/riotbase/cpu/esp32/esp-idf
"make" -C /data/riotbuild/riotbase/cpu/esp32/esp-idf/common
"make" -C /data/riotbuild/riotbase/cpu/esp32/esp-idf/efuse
"make" -C /data/riotbuild/riotbase/cpu/esp32/esp-idf/gpio
"make" -C /data/riotbuild/riotbase/cpu/esp32/esp-idf-api
"make" -C /data/riotbuild/riotbase/cpu/esp32/freertos
"make" -C /data/riotbuild/riotbase/cpu/esp32/periph
"make" -C /data/riotbuild/riotbase/cpu/esp_common
"make" -C /data/riotbuild/riotbase/cpu/esp_common/esp-xtensa
"make" -C /data/riotbuild/riotbase/cpu/esp_common/freertos
"make" -C /data/riotbuild/riotbase/cpu/esp_common/periph
"make" -C /data/riotbuild/riotbase/cpu/esp_common/vendor
"make" -C /data/riotbuild/riotbase/cpu/esp_common/vendor/xtensa
"make" -C /data/riotbuild/riotbase/drivers
"make" -C /data/riotbuild/riotbase/drivers/periph_common
"make" -C /data/riotbuild/riotbase/sys
"make" -C /data/riotbuild/riotbase/sys/auto_init
"make" -C /data/riotbuild/riotbase/sys/div
"make" -C /data/riotbuild/riotbase/sys/frac
"make" -C /data/riotbuild/riotbase/sys/isrpipe
"make" -C /data/riotbuild/riotbase/sys/libc
"make" -C /data/riotbuild/riotbase/sys/luid
"make" -C /data/riotbuild/riotbase/sys/newlib_syscalls_default
"make" -C /data/riotbuild/riotbase/sys/pm_layered
"make" -C /data/riotbuild/riotbase/sys/preprocessor
"make" -C /data/riotbuild/riotbase/sys/random
"make" -C /data/riotbuild/riotbase/sys/stdio
"make" -C /data/riotbuild/riotbase/sys/stdio_uart
"make" -C /data/riotbuild/riotbase/sys/test_utils/interactive_sync
"make" -C /data/riotbuild/riotbase/sys/test_utils/print_stack_usage
"make" -C /data/riotbuild/riotbase/sys/tsrb
"make" -C /data/riotbuild/riotbase/sys/ztimer
esptool.py v3.2-dev
Merged 1 ELF section
Parsing CSV input...
   text	  data	   bss	   dec	   hex	filename
  69481	 14388	  6774	 90643	 16213	/data/riotbuild/riotbase/tests/periph/gpio_ll/bin/esp32-mh-et-live-minikit/tests_gpio_ll.elf
esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 --before default_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 /home/maribu/Repos/software/RIOT/master/tests/periph/gpio_ll/bin/esp32-mh-et-live-minikit/esp_bootloader/bootloader.bin 0x8000 /home/maribu/Repos/software/RIOT/master/tests/periph/gpio_ll/bin/esp32-mh-et-live-minikit/partitions.bin 0x10000 /home/maribu/Repos/software/RIOT/master/tests/periph/gpio_ll/bin/esp32-mh-et-live-minikit/tests_gpio_ll.elf.bin
esptool.py v4.7.0
Serial port /dev/ttyUSB0
Connecting.....
Chip is ESP32-D0WDQ6 (revision v1.0)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 24:62:ab:de:6d:74
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Auto-detected Flash size: 4MB
Flash will be erased from 0x00001000 to 0x00005fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x00010000 to 0x0002bfff...
Warning: Image file at 0x1000 is protected with a hash checksum, so not changing the flash size setting. Use the --flash_size=keep option instead of --flash_size=4MB in order to remove this warning, or use the --dont-append-digest option for the elf2image command in order to generate an image file without a hash checksum
Compressed 17488 bytes to 11680...
Wrote 17488 bytes (11680 compressed) at 0x00001000 in 0.6 seconds (effective 240.7 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 85...
Wrote 3072 bytes (85 compressed) at 0x00008000 in 0.0 seconds (effective 581.6 kbit/s)...
Hash of data verified.
Compressed 113456 bytes to 52854...
Wrote 113456 bytes (52854 compressed) at 0x00010000 in 1.9 seconds (effective 483.0 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
r
/home/maribu/Repos/software/RIOT/master/dist/tools/pyterm/pyterm -p "/dev/ttyUSB0" -b "115200" --no-reconnect --noprefix --no-repeat-command-on-empty-line 
Twisted not available, please install it if you want to use pyterm's JSON capabilities
Connect to serial port /dev/ttyUSB0
Welcome to pyterm!
Type '/exit' to exit.
READY
s
START
main(): This is RIOT! (Version: 2024.07-devel-111-g9dc93-drivers/periph_gpio_ll/api-change)
Test / Hardware Details:
========================
Cabling:
(INPUT -- OUTPUT)
  P0.2 -- P0.23
  P0.4 -- P0.19
Number of pull resistor values supported: 1
Number of drive strengths supported: 4
Number of slew rates supported: 1
Valid GPIO ports:
- PORT 0 (PORT A)
- PORT 1 (PORT B)

Testing gpio_port_pack_addr()
=============================

All OK

Testing gpip_ng_init()
======================

Testing is_gpio_port_num_valid() is true for PORT_OUT and PORT_IN:

Testing input configurations for PIN_IN_0:
Support for input with pull up: yes
state: in, pull: up, value: on, drive: weakest
Support for input with pull down: yes
state: in, pull: down, value: off, drive: weakest
Support for input with pull to bus level: no
Support for floating input (no pull resistors): yes
state: in, pull: none, value: off, drive: weakest

Testing output configurations for PIN_OUT_0:
Support for output (push-pull) with initial value of LOW: yes
state: out-pp, value: off, drive: weakest
Output is indeed LOW: yes
state: out-pp, value: on, drive: weakest
Output can be pushed HIGH: yes
Support for output (push-pull) with initial value of HIGH: yes
state: out-pp, value: on, drive: weakest
Output is indeed HIGH: yes
Support for output (open drain with pull up) with initial value of LOW: yes
state: out-od, pull: up, value: off, drive: weakest
Output is indeed LOW: yes
Support for output (open drain with pull up) with initial value of HIGH: yes
state: out-od, pull: up, value: on, drive: weakest
Output is indeed HIGH: yes
Support for output (open drain) with initial value of LOW: yes
state: out-od, pull: none, value: off, drive: weakest
Output is indeed LOW: yes
Support for output (open drain) with initial value of HIGH: yes
state: out-od, pull: none, value: on, drive: weakest
state: in, pull: down, value: off, drive: weakest
Output can indeed be pulled LOW: yes
state: in, pull: up, value: on, drive: weakest
Output can indeed be pulled HIGH: yes
Support for output (open source) with initial value of LOW: no
Support for output (open source) with initial value of HIGH: no
Support for output (open source with pull down) with initial value of HIGH: no
Support for output (open source with pull down) with initial value of LOW: no

Support for disconnecting GPIO: yes
state: off, pull: none, value: off, drive: weakest
Output can indeed be pulled LOW: yes
Output can indeed be pulled HIGH: yes

Testing Reading/Writing GPIO Ports
==================================

testing initial value of 0 after init
...OK
testing setting both outputs_optional simultaneously
...OK
testing clearing both outputs_optional simultaneously
...OK
testing toggling first output (0 --> 1)
...OK
testing toggling first output (1 --> 0)
...OK
testing toggling second output (0 --> 1)
...OK
testing toggling second output (1 --> 0)
...OK
testing setting first output and clearing second with write
...OK
testing setting second output and clearing first with write
...OK
All input/output operations worked as expected

Testing External IRQs
=====================

Testing rising edge on PIN_IN_0
... OK
Testing falling edge on PIN_IN_0
... OK
Testing both edges on PIN_IN_0
... OK
Testing masking of IRQs (still both edges on PIN_IN_0)
... OK
Testing level-triggered on HIGH on PIN_IN_0 (when input is LOW when setting up IRQ)
... OK
Testing level-triggered on HIGH on PIN_IN_0 (when input is HIGH when setting up IRQ)
... OK
Testing level-triggered on LOW on PIN_IN_0 (when input is HIGH when setting up IRQ)
... OK
Testing level-triggered on LOW on PIN_IN_0 (when input is LOW when setting up IRQ)
... OK


TEST SUCCEEDED

@maribu maribu force-pushed the drivers/periph_gpio_ll/api-change branch from 9dc939a to cc1b7a1 Compare April 29, 2024 19:43
@maribu
Copy link
Member Author

maribu commented Apr 29, 2024

STM32

make BOARD=nucleo-f429zi flash test-with-config                              
Building application "tests_gpio_ll" for "nucleo-f429zi" with CPU "stm32".

"make" -C /home/maribu/Repos/software/RIOT/master/pkg/cmsis/ 
"make" -C /home/maribu/Repos/software/RIOT/master/boards/common/init
"make" -C /home/maribu/Repos/software/RIOT/master/boards/nucleo-f429zi
"make" -C /home/maribu/Repos/software/RIOT/master/boards/common/nucleo
"make" -C /home/maribu/Repos/software/RIOT/master/core
"make" -C /home/maribu/Repos/software/RIOT/master/core/lib
"make" -C /home/maribu/Repos/software/RIOT/master/cpu/stm32
"make" -C /home/maribu/Repos/software/RIOT/master/cpu/cortexm_common
"make" -C /home/maribu/Repos/software/RIOT/master/cpu/cortexm_common/periph
"make" -C /home/maribu/Repos/software/RIOT/master/cpu/stm32/periph
"make" -C /home/maribu/Repos/software/RIOT/master/cpu/stm32/stmclk
"make" -C /home/maribu/Repos/software/RIOT/master/cpu/stm32/vectors
"make" -C /home/maribu/Repos/software/RIOT/master/drivers
"make" -C /home/maribu/Repos/software/RIOT/master/drivers/periph_common
"make" -C /home/maribu/Repos/software/RIOT/master/sys
"make" -C /home/maribu/Repos/software/RIOT/master/sys/auto_init
"make" -C /home/maribu/Repos/software/RIOT/master/sys/div
"make" -C /home/maribu/Repos/software/RIOT/master/sys/frac
"make" -C /home/maribu/Repos/software/RIOT/master/sys/isrpipe
"make" -C /home/maribu/Repos/software/RIOT/master/sys/libc
"make" -C /home/maribu/Repos/software/RIOT/master/sys/malloc_thread_safe
"make" -C /home/maribu/Repos/software/RIOT/master/sys/newlib_syscalls_default
"make" -C /home/maribu/Repos/software/RIOT/master/sys/pm_layered
"make" -C /home/maribu/Repos/software/RIOT/master/sys/preprocessor
"make" -C /home/maribu/Repos/software/RIOT/master/sys/stdio
"make" -C /home/maribu/Repos/software/RIOT/master/sys/stdio_uart
"make" -C /home/maribu/Repos/software/RIOT/master/sys/test_utils/interactive_sync
"make" -C /home/maribu/Repos/software/RIOT/master/sys/test_utils/print_stack_usage
"make" -C /home/maribu/Repos/software/RIOT/master/sys/tsrb
"make" -C /home/maribu/Repos/software/RIOT/master/sys/ztimer
   text	  data	   bss	   dec	   hex	filename
  21440	   180	  2728	 24348	  5f1c	/home/maribu/Repos/software/RIOT/master/tests/periph/gpio_ll/bin/nucleo-f429zi/tests_gpio_ll.elf
/home/maribu/Repos/software/RIOT/master/dist/tools/openocd/openocd.sh flash /home/maribu/Repos/software/RIOT/master/tests/periph/gpio_ll/bin/nucleo-f429zi/tests_gpio_ll.elf
### Flashing Target ###
Open On-Chip Debugger 0.12.0+dev-snapshot (2024-01-17-08:38)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
DEPRECATED! use 'adapter serial' not 'hla_serial'
hla_swd
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
srst_only separate srst_nogate srst_open_drain connect_assert_srst
Info : clock speed 2000 kHz
Info : STLINK V2J29M18 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.255790
Info : [stm32f4x.cpu] Cortex-M4 r0p1 processor detected
Info : [stm32f4x.cpu] target has 6 breakpoints, 4 watchpoints
Info : [stm32f4x.cpu] Examination succeed
Info : starting gdb server for stm32f4x.cpu on 0
Info : Listening on port 34307 for gdb connections
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32f4x.cpu       hla_target little stm32f4x.cpu       unknown
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
[stm32f4x.cpu] halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0800138c msp: 0x20000200
Info : device id = 0x20016419
Info : flash size = 2048 KiB
Info : Dual Bank 2048 kiB STM32F42x/43x/469/479 found
auto erase enabled
wrote 32768 bytes from file /home/maribu/Repos/software/RIOT/master/tests/periph/gpio_ll/bin/nucleo-f429zi/tests_gpio_ll.elf in 1.097200s (29.165 KiB/s)
verified 21620 bytes in 0.214806s (98.290 KiB/s)
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
shutdown command invoked
Done flashing
r
/home/maribu/Repos/software/RIOT/master/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "115200" --no-reconnect --noprefix --no-repeat-command-on-empty-line 
Twisted not available, please install it if you want to use pyterm's JSON capabilities
Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
��сtest, r to print it is ready
Help: Press s to start test, r to print it is ready
READY
s
START
main(): This is RIOT! (Version: 2024.07-devel-111-gcc1b7a1-drivers/periph_gpio_ll/api-change)
Test / Hardware Details:
========================
Cabling:
(INPUT -- OUTPUT)
  PPD0 -- PC0
  PPD1 -- PC3
Number of pull resistor values supported: 1
Number of drive strengths supported: 1
Number of slew rates supported: 4
Valid GPIO ports:
- PORT 0 (PORT A)
- PORT 1 (PORT B)
- PORT 2 (PORT C)
- PORT 3 (PORT D)
- PORT 4 (PORT E)
- PORT 5 (PORT F)
- PORT 6 (PORT G)
- PORT 7 (PORT H)
- PORT 8 (PORT I)
- PORT 9 (PORT J)
- PORT 10 (PORT K)

Testing gpio_port_pack_addr()
=============================

All OK

Testing gpip_ng_init()
======================

Testing is_gpio_port_num_valid() is true for PORT_OUT and PORT_IN:

Testing input configurations for PIN_IN_0:
Support for input with pull up: yes
state: in, pull: up, value: on, slew: slowest
Support for input with pull down: yes
state: in, pull: down, value: off, slew: slowest
Support for input with pull to bus level: no
Support for floating input (no pull resistors): yes
state: in, pull: none, value: off, slew: slowest

Testing output configurations for PIN_OUT_0:
Support for output (push-pull) with initial value of LOW: yes
state: out-pp, value: off, slew: slowest
Output is indeed LOW: yes
state: out-pp, value: on, slew: slowest
Output can be pushed HIGH: yes
Support for output (push-pull) with initial value of HIGH: yes
state: out-pp, value: on, slew: slowest
Output is indeed HIGH: yes
Support for output (open drain with pull up) with initial value of LOW: yes
state: out-od, pull: up, value: off, slew: slowest
Output is indeed LOW: yes
Support for output (open drain with pull up) with initial value of HIGH: yes
state: out-od, pull: up, value: on, slew: slowest
Output is indeed HIGH: yes
Support for output (open drain) with initial value of LOW: yes
state: out-od, pull: none, value: off, slew: slowest
Output is indeed LOW: yes
Support for output (open drain) with initial value of HIGH: yes
state: out-od, pull: none, value: on, slew: slowest
state: in, pull: down, value: off, slew: slowest
Output can indeed be pulled LOW: yes
state: in, pull: up, value: off, slew: slowest
Output can indeed be pulled HIGH: yes
Support for output (open source) with initial value of LOW: no
Support for output (open source) with initial value of HIGH: no
Support for output (open source with pull down) with initial value of HIGH: no
Support for output (open source with pull down) with initial value of LOW: no

Support for disconnecting GPIO: yes
state: off, pull: none, value: off, slew: slowest
Output can indeed be pulled LOW: yes
Output can indeed be pulled HIGH: yes

Testing Reading/Writing GPIO Ports
==================================

testing initial value of 0 after init
...OK
testing setting both outputs_optional simultaneously
...OK
testing clearing both outputs_optional simultaneously
...OK
testing toggling first output (0 --> 1)
...OK
testing toggling first output (1 --> 0)
...OK
testing toggling second output (0 --> 1)
...OK
testing toggling second output (1 --> 0)
...OK
testing setting first output and clearing second with write
...OK
testing setting second output and clearing first with write
...OK
All input/output operations worked as expected

Testing External IRQs
=====================

Testing rising edge on PIN_IN_0
... OK
Testing falling edge on PIN_IN_0
... OK
Testing both edges on PIN_IN_0
... OK
Testing masking of IRQs (still both edges on PIN_IN_0)
... OK
Testing level-triggered on HIGH on PIN_IN_0 (when input is LOW when setting up IRQ)
... OK
Testing level-triggered on HIGH on PIN_IN_0 (when input is HIGH when setting up IRQ)
... OK
Testing level-triggered on LOW on PIN_IN_0 (when input is HIGH when setting up IRQ)
... OK
Testing level-triggered on LOW on PIN_IN_0 (when input is LOW when setting up IRQ)
... OK


TEST SUCCEEDED

@maribu maribu force-pushed the drivers/periph_gpio_ll/api-change branch 3 times, most recently from e5956fd to ae64e85 Compare April 30, 2024 17:16
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 fixes a race in `LED<NUM>_TOGGLE`, which is a read-copy-write
operation. Any access to a GPIO pin on the same GPIO port that
happens concurrently could result in data corruption. Using the
GPIO LL API, which is thread-safe, fixes the issue.

Note: The used GPIO LL functions will work even in when the GPIO LL
      module is not used.
@maribu maribu force-pushed the drivers/periph_gpio_ll/api-change branch from ae64e85 to 09e8d9e Compare April 30, 2024 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports Area: drivers Area: Device drivers Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Platform: AVR Platform: This PR/issue effects AVR-based platforms Platform: ESP Platform: This PR/issue effects ESP-based platforms Process: API change Integration Process: PR contains or issue proposes an API change. Should be handled with care.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants