rtic icon indicating copy to clipboard operation
rtic copied to clipboard

Expose a `Delay` implementation on task contexts

Open antonok-edm opened this issue 3 years ago • 4 comments

Several peripheral HAL APIs require the use of a DelayUs or DelayMs trait implementor. I've seen this pattern a couple of times on reset/initialization methods, e.g. synopsys_usb_otg::bus::UsbBus::force_reset or ssd1306::Ssd1306::reset. The blocking nature of these APIs is not necessarily friendly to a real time framework like RTIC, but:

  • these are widely-used libraries
  • exposing a set of delay-free reset routines for some libraries may be particularly challenging
  • resets are ideally called only in edge cases where blocking may not be as much of an issue

On rtic 0.5/stm32f4xx_hal, it was possible to use stm32f4xx_hal::dwt::DwtExt to create a suitable delay implementation, and put it in LateResources. As of rtic 1.0 it looks like dwt_systick_monotonic::DwtSystick is the proper way to create a monotonic timer for RTIC on stm32 platforms, but this takes ownership of DWT and DCB so that it's no longer possible to make another timer as a resource.

I'm not sure what kind of magic allowed RTIC to work without exclusive access to DWT in the past, but since it should be ultimately responsible for scheduling/timekeeping, it makes sense to give it exclusive access to the timer hardware. Still, this prevents use of reset APIs like those mentioned above.

I've realized that a clean way to maintain compatibility with those APIs would be to give RTIC tasks access to a DelayMs/DelayUs implementor as a field of the context struct. The implementation would reuse the main monotonic counter behind the scenes. I'm not sure if it's feasible for RTIC to allow other tasks to continue running in the meantime, but a minimal implementation that blocks for the duration of the delay would still be really useful for interoperability with these peripheral crates.

antonok-edm avatar Feb 07 '22 05:02 antonok-edm

Hi, the dwt-systick-monotonic is really only for playing around with RTIC and getting a feel for what you can do. If you have collisions with the specific chosen monotonic, is e recommend you to use a different one that does not use Systick and DWT.

Else, if that is not possible, you can implement Delay based of the monotonic. I don't quite see why RTIC itself would perform this implementation.

korken89 avatar Feb 07 '22 06:02 korken89

Hi, the dwt-systick-monotonic is really only for playing around with RTIC and getting a feel for what you can do.

Ah, okay. This wasn't really clear from the book, and I guess it doesn't help that the links to the (presumably "real") STM32 and Nordic implementations are broken :sweat_smile:

Else, if that is not possible, you can implement Delay based of the monotonic.

If I were to use this approach, how would you suggest to access the monotonic from within a task?

antonok-edm avatar Feb 07 '22 06:02 antonok-edm

Hi, the dwt-systick-monotonic is really only for playing around with RTIC and getting a feel for what you can do.

Ah, okay. This wasn't really clear from the book, and I guess it doesn't help that the links to the (presumably "real") STM32 and Nordic implementations are broken sweat_smile

Should be fixed now also on stable (not only dev book)

Else, if that is not possible, you can implement Delay based of the monotonic.

If I were to use this approach, how would you suggest to access the monotonic from within a task?

The regular way to access it within a task is to refer to monotonics::now() (if default monotonic is set), see example over here. If you have suggestions how to help clarify docs we're all ears.

AfoHT avatar Feb 08 '22 22:02 AfoHT

The regular way to access it within a task is to refer to monotonics::now() (if default monotonic is set), see example over here. If you have suggestions how to help clarify docs we're all ears.

Ok, I guess what I'm asking is: how can I "implement Delay based of the monotonic" as @korken89 suggested, in order to be compatible with the APIs that require it. I don't see any obvious methods on rtic_monotonic::Monotonic that I could wrap with, say, a DelayMs impl, so I believe RTIC would have to expose something new to support it. Essentially a way to suspend control flow within a task for a given duration.

antonok-edm avatar Feb 09 '22 19:02 antonok-edm

This is now implemented using embedded-hal-async in the async support in rtic-monotonics

korken89 avatar Apr 15 '23 06:04 korken89