Struct esp_idf_hal::timer::TimerDriver
source · pub struct TimerDriver<'d> { /* private fields */ }
Implementations§
source§impl<'d> TimerDriver<'d>
impl<'d> TimerDriver<'d>
pub fn new<TIMER: Timer>( _timer: impl Peripheral<P = TIMER> + 'd, config: &Config, ) -> Result<Self, EspError>
sourcepub fn enable(&mut self, enable: bool) -> Result<(), EspError>
pub fn enable(&mut self, enable: bool) -> Result<(), EspError>
Enable or disable the timer.
Enabling the timer causes it to begin counting up from the current counter.
Disabling the timer effectively pauses the counter.
sourcepub fn set_counter(&mut self, value: u64) -> Result<(), EspError>
pub fn set_counter(&mut self, value: u64) -> Result<(), EspError>
Manually set the current counter value of the timer.
This does not enable or disable the timer.
sourcepub fn enable_alarm(&mut self, enable: bool) -> Result<(), EspError>
pub fn enable_alarm(&mut self, enable: bool) -> Result<(), EspError>
Enable or disable the alarm.
Enabling the alarm activates the following behaviors once it is triggered:
- The counter will reset to 0, if auto-reload is set
- An interrupt will be triggered, if configured
sourcepub fn set_alarm(&mut self, value: u64) -> Result<(), EspError>
pub fn set_alarm(&mut self, value: u64) -> Result<(), EspError>
Set the alarm value of the timer.
NOTE: The alarm must be activated with enable_alarm for this value to take effect
Once the counter exceeds this value:
- The counter will reset to 0, if auto-reload is set
- An interrupt will be triggered, if configured
pub fn enable_interrupt(&mut self) -> Result<(), EspError>
pub fn disable_interrupt(&mut self) -> Result<(), EspError>
sourcepub async fn delay(&mut self, counter: u64) -> Result<(), EspError>
pub async fn delay(&mut self, counter: u64) -> Result<(), EspError>
Delays for counter
ticks
NOTE: This function resets the counter
sourcepub fn reset_wait(&mut self)
pub fn reset_wait(&mut self)
Resets the internal wait notification
sourcepub async fn wait(&mut self) -> Result<(), EspError>
pub async fn wait(&mut self) -> Result<(), EspError>
Wait for an alarm interrupt to occur
NOTE: This requires interrupts to be enabled to work
sourcepub unsafe fn subscribe<F>(&mut self, callback: F) -> Result<(), EspError>where
F: FnMut() + Send + 'static,
pub unsafe fn subscribe<F>(&mut self, callback: F) -> Result<(), EspError>where
F: FnMut() + Send + 'static,
Subscribes the provided callback for ISR notifications.
As a side effect, interrupts will be disabled, so to receive a notification, one has
to also call TimerDriver::enable_interrupt
after calling this method.
§Safety
Care should be taken not to call STD, libc or FreeRTOS APIs (except for a few allowed ones) in the callback passed to this function, as it is executed in an ISR context.
sourcepub unsafe fn subscribe_nonstatic<F>(
&mut self,
callback: F,
) -> Result<(), EspError>where
F: FnMut() + Send + 'd,
pub unsafe fn subscribe_nonstatic<F>(
&mut self,
callback: F,
) -> Result<(), EspError>where
F: FnMut() + Send + 'd,
Subscribes the provided callback for ISR notifications.
As a side effect, interrupts will be disabled, so to receive a notification, one has
to also call TimerDriver::enable_interrupt
after calling this method.
§Safety
Care should be taken not to call STD, libc or FreeRTOS APIs (except for a few allowed ones) in the callback passed to this function, as it is executed in an ISR context.
Additionally, this method - in contrast to method subscribe
- allows
the passed-in callback/closure to be non-'static
. This enables users to borrow
- in the closure - variables that live on the stack - or more generally - in the same scope where the driver is created.
HOWEVER: care should be taken NOT to call core::mem::forget()
on the driver,
as that would immediately lead to an UB (crash).
Also note that forgetting the driver might happen with Rc
and Arc
when circular references are introduced: https://github.com/rust-lang/rust/issues/24456
The reason is that the closure is actually sent and owned by an ISR routine, which means that if the driver is forgotten, Rust is free to e.g. unwind the stack and the ISR routine will end up with references to variables that no longer exist.
The destructor of the driver takes care - prior to the driver being dropped and e.g. the stack being unwind - to unsubscribe the ISR routine. Unfortunately, when the driver is forgotten, the un-subscription does not happen and invalid references are left dangling.
This “local borrowing” will only be possible to express in a safe way once/if !Leak
types
are introduced to Rust (i.e. the impossibility to “forget” a type and thus not call its destructor).
pub fn unsubscribe(&mut self) -> Result<(), EspError>
pub fn group(&self) -> timer_group_t
pub fn index(&self) -> timer_idx_t
Trait Implementations§
source§impl<'d> DelayNs for TimerDriver<'d>
impl<'d> DelayNs for TimerDriver<'d>
source§async fn delay_ns(&mut self, ns: u32)
async fn delay_ns(&mut self, ns: u32)
ns
nanoseconds. Pause can be longer
if the implementation requires it due to precision/timing issues.