Skip to content

cpu/esp32/gpio_ll: fix & cleanup#20635

Merged
maribu merged 1 commit intoRIOT-OS:masterfrom
maribu:cpu/esp32/gpio_ll
Apr 30, 2024
Merged

cpu/esp32/gpio_ll: fix & cleanup#20635
maribu merged 1 commit intoRIOT-OS:masterfrom
maribu:cpu/esp32/gpio_ll

Conversation

@maribu
Copy link
Copy Markdown
Member

@maribu maribu commented Apr 29, 2024

Contribution description

  • gpio_ll_toggle() now is race-free
  • avoid using a look up table but branch to the two different registers
    in the gpio_ll*() functions
    • in most cases the GPIO port is a compile time constant and the dead branch is eliminated by the optimizer, making this vastly more efficient
    • some MCUs do only have a single port, in which case GPIO_PORT_NUM(port) is known to return 0 even if port is not known, resulting in one of the branch being eliminated as dead branch no matter what
    • in case it really is unknown at compile time which port to work on, the branch can still be implemented efficiently by the compiler e.g. using a conditional move; likely more efficient than fetching a value from the look up table.

Testing procedure

Selftest with the PR

$ cd tests/periph/gpio_ll
$ 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
  69557	 14372	  6774	 90703	 1624f	/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.7 seconds (effective 212.8 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 85...
Wrote 3072 bytes (85 compressed) at 0x00008000 in 0.0 seconds (effective 579.7 kbit/s)...
Hash of data verified.
Compressed 113536 bytes to 52923...
Wrote 113536 bytes (52923 compressed) at 0x00010000 in 1.8 seconds (effective 502.4 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-109-gc2bd8)
Test / Hardware Details:
========================
Cabling:
(INPUT -- OUTPUT)
  P0.2 (PA2) -- P0.23 (PA23)
  P0.4 (PA4) -- P0.19 (PA19)
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
testin 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

Benchmark (tests/bench/gpio_ll) with PR

Benchmarking GPIO APIs
======================

estimating loop overhead for compensation
-----------------------------------------
3131 us for 50000 iterations

periph/gpio: Using 2x gpio_set() and 2x gpio_clear()
---------------------------------------------------
50000 iterations took 70004 us (73135 us uncompensated)
Two square waves pins at       714244 Hz (      683667 Hz uncompensated)
~112 CPU cycles per square wave period (~117 cycles uncompensated)
:'-(

periph/gpio_ll: Using gpio_ll_set() and gpio_ll_clear()
-------------------------------------------------------
50000 iterations took 4374 us (7505 us uncompensated)
Two square waves pins at     11431184 Hz (     6662225 Hz uncompensated)
~7 CPU cycles per square wave period (~12 cycles uncompensated)
:-|

pe-----
50000 iterations took 92504 us (95635 us uncompensated)
Two square waves pins at       540517 Hz (      522821 Hz uncompensated)
~148 CPU cycles per square wave period (~153 cycles uncompensated)
:'-(

periph/gpio_ll: Using 2x gpio_ll_toggle()
-----------------------------------------
50000 iterations took 78754 us (81885 us uncompensated)
Two square waves pins at       634888 Hz (      610612 Hz uncompensated)
~126 CPU cycles per square wave period (~131 cycles uncompensated)
:'-(

periph/gpio: Using 4x gpio_write()
----------------------------------
50000 iterations took 81254 us (84385 us uncompensated)
Two square waves pins at       615354 Hz (      592522 Hz uncompensated)
~130 CPU cycles per square wave period (~135 cycles uncompensated)
:'-(

periph/gpio_ll: Using 2x gpio_ll_write()
----------------------------------------
50000 iterations took 4375 us (7506 us uncompensated)
Two square waves pins at     11428571 Hz (     6661337 Hz uncompensated)
~7 CPU cycles per square wave period (~12 cycles uncompensated)
:-|

Benchmark (tests/bench/gpio_ll) with master

Benchmarking GPIO APIs
======================

estimating loop overhead for compensation
-----------------------------------------
3126 us for 50000 iterations

periph/gpio: Using 2x gpio_set() and 2x gpio_clear()
---------------------------------------------------
50000 iterations took 70009 us (73135 us uncompensated)
Two square waves pins at       714193 Hz (      683667 Hz uncompensated)
~112 CPU cycles per square wave period (~117 cycles uncompensated)
:'-(

periph/gpio_ll: Using gpio_ll_set() and gpio_ll_clear()
-------------------------------------------------------
50000 iterations took 4379 us (7505 us uncompensated)
Two square waves pins at     11418131 Hz (     6662225 Hz uncompensated)
~7 CPU cycles per square wave period (~12 cycles uncompensated)
:-|

periph/gpio: Using 4x gpio_toggle()
-----------------------------------
50000 iterations took 92509 us (95635 us uncompensated)
Two square waves pins at       540487 Hz (      522821 Hz uncompensated)
~148 CPU cycles per square wave period (~153 cycles uncompensated)
:'-(

periph/gpio_ll: Using 2x gpio_ll_toggle()
-----------------------------------------
50000 iterations took 19379 us (22505 us uncompensated)
Two square waves pins at      2580112 Hz (     2221728 Hz uncompensated)
~31 CPU cycles per square wave period (~36 cycles uncompensated)
:'-(

periph/gpio: Using 4x gpio_write()
----------------------------------
50000 iterations took 81259 us (84385 us uncompensated)
Two square waves pins at       615316 Hz (      592522 Hz uncompensated)
~130 CPU cycles per square wave period (~135 cycles uncompensated)
:'-(

periph/gpio_ll: Using 2x gpio_ll_write()
----------------------------------------
50000 iterations took 5000 us (8126 us uncompensated)
Two square waves pins at     10000000 Hz (     6153088 Hz uncompensated)
~8 CPU cycles per square wave period (~13 cycles uncompensated)
:-|


TEST SUCCEEDED

Conclusion

  • No functional regression
  • +36 B .text, -64 B .data, +/-0 B .bss in tests/benchmark/gpio_ll
    • More RAM saved than flash lost, and RAM is more expensive --> slight win
  • gpio_ll_toggle() got a lot more expensive (but now lives out to the thread-safety guarantees of the API)
  • no change in the benchmark of the other APIs
    • But: The test is designed so that loading the register address from the look up table could be moved out of the loop body and cached in a register by the optimizer, which is not generally possible in real world uses
    • I expect the new API to be faster in real world uses

Issues/PRs references

None

@maribu maribu requested a review from gschorcht as a code owner April 29, 2024 11:57
@github-actions github-actions bot added Platform: ESP Platform: This PR/issue effects ESP-based platforms Area: cpu Area: CPU/MCU ports labels Apr 29, 2024
@maribu maribu added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Apr 29, 2024
@riot-ci
Copy link
Copy Markdown

riot-ci commented Apr 29, 2024

Murdock results

✔️ PASSED

dd585f9 cpu/esp32/gpio_ll: fix & cleanup

Success Failures Total Runtime
10065 0 10066 13m:22s

Artifacts

@maribu maribu force-pushed the cpu/esp32/gpio_ll branch from 06edfa8 to ae1deb2 Compare April 30, 2024 07:57
@benpicco benpicco enabled auto-merge April 30, 2024 09:05
@benpicco benpicco added this pull request to the merge queue Apr 30, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Apr 30, 2024
@maribu maribu force-pushed the cpu/esp32/gpio_ll branch from ae1deb2 to f36695e Compare April 30, 2024 12:08
- `gpio_ll_toggle()` now is race-free
- avoid using a look up table but branch to the two different registers
  in the `gpio_ll*()` functions
    - in most cases the GPIO port is a compile time constant and the
      dead branch is eliminated by the optimizer, making this vastly
      more efficient
    - some MCUs do only have a single port, in which case
      `GPIO_PORT_NUM(port)` is known to return `0` even if `port` is
      not known, resulting in one of the branch being eliminated as
      dead branch no matter what
    - in case it really is unknown at compile time which port to work
      on, the branch can still be implemented efficiently by the
      compiler e.g. using a conditional move; likely more efficient
      than fetching a value from the look up table.
@maribu maribu force-pushed the cpu/esp32/gpio_ll branch from f36695e to dd585f9 Compare April 30, 2024 12:16
@maribu
Copy link
Copy Markdown
Member Author

maribu commented Apr 30, 2024

OK, it compiles now for both ESP32 with one and two GPIO ports. Tests are still passing:

main(): This is RIOT! (Version: 2024.07-devel-110-gdd585-cpu/esp32/gpio_ll)
Test / Hardware Details:
========================
Cabling:
(INPUT -- OUTPUT)
  P0.2 (PA2) -- P0.23 (PA23)
  P0.4 (PA4) -- P0.19 (PA19)
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

The benchmark for gpio_toggle() interestingly got faster. Likely the memory barrier in irq_disable() caused GCC to not do constant folding on the GPIO port, as it assumed the variable holding the GPIO port may have been changed by irq_disable()? Anyway, I'm not complaining about faster code :)

main(): This is RIOT! (Version: 2024.07-devel-110-gdd585-cpu/esp32/gpio_ll)

Benchmarking GPIO APIs
======================

estimating loop overhead for compensation
-----------------------------------------
3126 us for 50000 iterations

periph/gpio: Using 2x gpio_set() and 2x gpio_clear()
---------------------------------------------------
50000 iterations took 70013 us (73139 us uncompensated)
Two square waves pins at       714153 Hz (      683629 Hz uncompensated)
~112 CPU cycles per square wave period (~117 cycles uncompensated)
:'-(

periph/gpio_ll: Using gpio_ll_set() and gpio_ll_clear()
-------------------------------------------------------
50000 iterations took 4380 us (7506 us uncompensated)
Two square waves pins at     11415525 Hz (     6661337 Hz uncompensated)
~7 CPU cycles per square wave period (~12 cycles uncompensated)
:-|

periph/gpio: Using 4x gpio_toggle()
-----------------------------------
50000 iterations took 92509 us (95635 us uncompensated)
Two square waves pins at       540487 Hz (      522821 Hz uncompensated)
~148 CPU cycles per square wave period (~153 cycles uncompensated)
:'-(

periph/gpio_ll: Using 2x gpio_ll_toggle()
-----------------------------------------
50000 iterations took 56884 us (60010 us uncompensated)
Two square waves pins at       878981 Hz (      833194 Hz uncompensated)
~91 CPU cycles per square wave period (~96 cycles uncompensated)
:'-(

periph/gpio: Using 4x gpio_write()
----------------------------------
50000 iterations took 81258 us (84384 us uncompensated)
Two square waves pins at       615324 Hz (      592529 Hz uncompensated)
~130 CPU cycles per square wave period (~135 cycles uncompensated)
:'-(

periph/gpio_ll: Using 2x gpio_ll_write()
----------------------------------------
50000 iterations took 4375 us (7501 us uncompensated)
Two square waves pins at     11428571 Hz (     6665777 Hz uncompensated)
~7 CPU cycles per square wave period (~12 cycles uncompensated)
:-|


TEST SUCCEEDED

@maribu maribu enabled auto-merge April 30, 2024 12:21
@maribu maribu added this pull request to the merge queue Apr 30, 2024
Merged via the queue into RIOT-OS:master with commit 91dd1ff Apr 30, 2024
@mguetschow mguetschow added this to the Release 2024.07 milestone Jul 5, 2024
@maribu maribu deleted the cpu/esp32/gpio_ll branch October 10, 2024 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ESP Platform: This PR/issue effects ESP-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants