I'm attempting to setup and use the TIM2
peripheral in one pulse mode (OPM) on the STM32F303 Discovery
board.
The issue I'm encountering is that the timer instantly completes after enabling it.
I'm not using interrupt
's at this point and I'm just polling the TIM2_SR
(status register) UIF
bit to determine if the timer has completed.
This only happens the first time I enable the timer, if I use the timer again it works correctly (does not complete instantly).
I've tried resetting the TIM2_CNT
register prior to enabling the timer but the result is the same.
use cortex_m_rt::entry;
use stm32f3xx_hal::pac;
#[entry]
fn main( ) -> ! {
let p = pac::Peripherals::take( ).unwrap( );
p.RCC.apb1enr.modify( | _, w | w.tim2en( ).set_bit( ) );
p.TIM2.cr1.write( | w | w
.urs( ).set_bit( )
.opm( ).set_bit( )
.cen( ).clear_bit( ) );
// I've tried resetting the CNT register at this point
// in the application but the result was the same.
// Set the prescaler based on an 8MHz clock.
p.TIM2.psc.write( | w | w.psc( ).bits( 7999 ) );
// Here I initialize an LED (GPIOE). I've removed this code to
// keep the example as clean as possible.
let delay = | duration | {
p.TIM2.arr.write( | w | w.arr( ).bits( duration ) );
// I've also tried resetting the CNT register here
// but the result was the same.
p.TIM2.cr1.modify( | _, w | w.cen( ).set_bit( ) );
while p.TIM2.sr.read( ).uif( ).bit_is_clear( ) { }
p.TIM2.sr.write( | w | w.uif( ).clear_bit( ) );
};
// Enable LED.
// This call instantly returns.
delay( 3999 );
// Disable LED.
loop { }
}
The example above gets the LED to flicker on and off with little to no delay.
If I instead use an endless loop the timer works as intended after the initial call to delay
.
loop {
// Enable LED.
// The first call in the first loop iteration
// returns instantly.
delay( 3999 );
// Disable LED.
// This call, and every call here after correctly
// returns after 4 seconds.
delay( 3999 );
}
I've examined the registers while the application is running and everything appears to be set up correctly.
- The
TIM2_CNT
register reads0x0000_0000
prior to enabling the timer - The
UIF
bit in theTIM2_SR
register is not set prior to enabling the timer - The
TIM2_PSC
register reads the correct pre-scale7999
- The
TIM2_ARR
register contains the correct auto reload value3999
- The
OPM
bit in theTIM_CR1
register is set correctly
After reading a similar issue on a different forum it was suggested in that answer to enable the URS
bit in the TIM2_CR1
register, which causes an update interrupt/DMA request to only be issued on counter overflow/underflow. This of course did not work.
I get the sense that there is a bit
somewhere that I need to reset/set in order to get the timer to function as expected the first time I enable it.