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

cpu/esp32/gpio_ll: fix & cleanup #20635

Merged
merged 1 commit into from Apr 30, 2024
Merged

Conversation

maribu
Copy link
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

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

@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
- `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
Copy link
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
25 checks passed
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.

None yet

3 participants