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_timer: add periph_timer_capture API #20519

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

Conversation

maribu
Copy link
Member

@maribu maribu commented Mar 28, 2024

Contribution description

This adds an API to use timers in capture mode.

A brief look in a number of data sheets has revealed that even primitive timers such as ATmega or MSP430 timers allow using both capture and compare mode to be used in parallel. Most use the channel compare target register as capture register, when a channel is in capture mode. Some (e.g. ATmega) have a dedicated capture register that is not shared with compare channels.

The API intents to reflect this by allowing capture channels to overlap with compare channels, or to have distinct numbers. The number of the first and the last capture channel for each timer can be
queried by the API. A default (weak symbol) implementation can be used when all compare channels can be used as capture channels, which seems to be the case for most timer peripherals.

An implementation is expected to rely on a board or MCU level configuration that maps channels to event sources (such as internal triggers or GPIO pins). A function to query which GPIO pin a specific channel on a given timer refers to is provided, which will return GPIO_UNDEF for internal triggers. Managing internal triggers are out of scope for a hardware abstracting peripheral API, as those can widely vary between MCUs. However, managing the capture channels linked to internal triggers will work with this API in the same way as capture channels linked to external triggers.

The internal triggers will be particularly useful to implement a mechanism to synchronize timer peripherals, e.g. to convert timestamps captured on peripheral A to timestamps on timer peripheral B that is used in compare mode.

Testing procedure

A test application was provided.

Note

The test app requires a jumper wire connecting a GPIO used as output to a GPIO used as trigger input and the corresponding configuration. See the test doc for details.


$ make BOARD=nucleo-f429zi flash test-with-config -C tests/periph/timer_capture
[...]
TEST SUCCEEDED
Click here for full test output
$ make BOARD=nucleo-f429zi flash test-with-config -C tests/periph/timer_capture
make: Entering directory '/home/maribu/Repos/software/RIOT/timer_capture/tests/periph/timer_capture'
Building application "tests_timer_capture" for "nucleo-f429zi" with CPU "stm32".

"make" -C /home/maribu/Repos/software/RIOT/timer_capture/pkg/cmsis/ 
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/boards/common/init
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/boards/nucleo-f429zi
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/boards/common/nucleo
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/core
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/core/lib
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/cpu/stm32
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/cpu/cortexm_common
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/cpu/cortexm_common/periph
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/cpu/stm32/periph
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/cpu/stm32/stmclk
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/cpu/stm32/vectors
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/drivers
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/drivers/periph_common
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/auto_init
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/div
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/isrpipe
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/libc
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/malloc_thread_safe
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/newlib_syscalls_default
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/pm_layered
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/preprocessor
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/stdio
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/stdio_uart
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/test_utils/interactive_sync
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/test_utils/print_stack_usage
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/tiny_strerror
"make" -C /home/maribu/Repos/software/RIOT/timer_capture/sys/tsrb
   text	  data	   bss	   dec	   hex	filename
  16156	   136	  2748	 19040	  4a60	/home/maribu/Repos/software/RIOT/timer_capture/tests/periph/timer_capture/bin/nucleo-f429zi/tests_timer_capture.elf
/home/maribu/Repos/software/RIOT/timer_capture/dist/tools/openocd/openocd.sh flash /home/maribu/Repos/software/RIOT/timer_capture/tests/periph/timer_capture/bin/nucleo-f429zi/tests_timer_capture.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.249012
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 37367 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: 0x08000cfc 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 16384 bytes from file /home/maribu/Repos/software/RIOT/timer_capture/tests/periph/timer_capture/bin/nucleo-f429zi/tests_timer_capture.elf in 0.659514s (24.260 KiB/s)
verified 16292 bytes in 0.176828s (89.975 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/timer_capture/dist/tools/pyterm/pyterm -p "/dev/ttyACM1" -b "115200" --no-reconnect --noprefix --no-repeat-command-on-empty-line 
Connect to serial port /dev/ttyACM1
Welcome to pyterm!
Type '/exit' to exit.
READY
s
START
main(): This is RIOT! (Version: 2024.04-devel-529-g1c3a48-drivers/periph_timer_capture)
testing periph_timer_capture on nucleo-f429zi
GPIO (Output)    GPIO(Input)   Timer
P1.0/PB0 ---> P0.0/PA0 TIMER_DEV(0) @ chan 0
Running @ 90000000 Hz, offset 180000 ticks
timer_init(0, 90000000, compare_cb, &sync_compare): OK
gpio_ll_init(): OK
# capture on rising edge
- one shot mode: [OK]
- regular mode: [OK]
- interaction with disabling/enabling IRQs: [OK]
- capture channel still works in compare mode: [OK]
# capture on falling edge
- one shot mode: [OK]
- regular mode: [OK]
- interaction with disabling/enabling IRQs: [OK]
- capture channel still works in compare mode: [OK]
# capture on both edges
- one shot mode: [OK]
- regular mode: [OK]
- interaction with disabling/enabling IRQs: [OK]
- capture channel still works in compare mode: [OK]
TEST SUCCEEDED

make: Leaving directory '/home/maribu/Repos/software/RIOT/timer_capture/tests/periph/timer_capture'

Issues/PRs references

This adds an API to use timers in capture mode.

A brief look in a number of data sheets has revealed that even primitive
timers such as ATmega or MSP430 timers allow using both capture and
compare mode to be used in parallel. Most use the channel compare
target register as capture register, when a channel is in capture
mode. Some (e.g. ATmega) have a dedicated capture register that
is not shared with compare channels.

The API intents to reflect this by allowing capture channels to
overlap with compare channels, or to have distinct numbers. The number
of the first and the last capture channel for each timer can be
queried by the API. A default (weak symbol) implementation can
be used when all compare channels can be used as capture channels,
which seems to be the case for most timer peripherals.

An implementation is expected to rely on a board or MCU level
configuration that maps channels to event sources (such as internal
triggers or GPIO pins). A function to query which GPIO pin a specific
channel on a given timer refers to is provided, which will return
`GPIO_UNDEF` for internal triggers. Managing internal triggers are out
of scope for a hardware abstracting peripheral API, as those can widely
vary between MCUs. However, managing the capture channels linked to
internal triggers will work with this API in the same way as capture
channels linked to external triggers.

The internal triggers will be particularly useful to implement a
mechanism to synchronize timer peripherals, e.g. to convert timestamps
captured on peripheral A to timestamps on timer peripheral B that is
used in compare mode.
Add capture config when TIM2 or TIM5 and TIM2 are used as timers and
add the feature to the effected boards.
@github-actions github-actions bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: doc Area: Documentation Area: tests Area: tests and testing framework Area: build system Area: Build system Area: drivers Area: Device drivers Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports labels Mar 28, 2024
@maribu maribu added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Mar 28, 2024
@riot-ci
Copy link

riot-ci commented Mar 28, 2024

Murdock results

✔️ PASSED

7fc66c3 fixup! drivers/periph_timer: add periph_timer_capture API

Success Failures Total Runtime
10026 0 10027 10m:59s

Artifacts

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: build system Area: Build system Area: cpu Area: CPU/MCU ports Area: doc Area: Documentation 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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants