i have just returned from an odyssey into timers on STM32. my goal was to write a sketch that uses a periodic interrupt to drive a DAC at an audio rate ( 20KHz – 48KHz ). i want to share some of my findings and also ask a question.
first i did the obvious and used the mbed Ticker
class to configure a callback at 40 μsec. the following snippet illustrates what i want to achieve ( i replaced the DAC with an LED and reduced the update rate for illustration purposes ):
mbed_ticker_approach
#include "mbed.h"
DigitalOut myled(LED2);
Ticker mTicker;
void ticker_callback() {
myled = !myled;
}
int main() {
mTicker.attach(ticker_callback, 0.5f);
while(1) {}
}
it worked ok-ish but i experienced some weird timing inconsistencies as soon as computations became more demanding. i found out that mbed uses just a single interrupt to drive all kinds of timing tasks. based on this understanding, i decided to investigate if a dedicated interrupt might work more reliably. after a lot of research i found an STM32-specfic solution that makes use of the underlying HAL:
nvic_and_HAL_approach
#include "mbed.h"
#define TIM_USR TIM3
#define TIM_USR_IRQ TIM3_IRQn
DigitalOut myled(LED2);
TIM_HandleTypeDef mTimUserHandle;
extern "C"
void M_TIM_USR_Handler(void) {
if (__HAL_TIM_GET_FLAG(&mTimUserHandle, TIM_FLAG_UPDATE) == SET) {
__HAL_TIM_CLEAR_FLAG(&mTimUserHandle, TIM_FLAG_UPDATE);
myled = !myled;
}
}
int main() {
__HAL_RCC_TIM3_CLK_ENABLE();
mTimUserHandle.Instance = TIM_USR;
mTimUserHandle.Init.Prescaler = 47999;
mTimUserHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
mTimUserHandle.Init.Period = 500; // 0.5 sec interval at 48 MHz MCU speed
mTimUserHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&mTimUserHandle);
HAL_TIM_Base_Start_IT(&mTimUserHandle);
NVIC_SetVector(TIM_USR_IRQ, (uint32_t)M_TIM_USR_Handler);
NVIC_EnableIRQ(TIM_USR_IRQ);
while(1) {}
}
// see also this thread: https://developer.mbed.org/users/AjK/notebook/getting-closer-to-the-hardware/
// and this thread: https://developer.mbed.org/forum/mbed/topic/16541/
the code above works fine for my setup. however, when i choose a different timer than timer 3 ( TIM3 ), the callback never happens ( although the application runs ). on my nucleo_f072rb board mbed is using timer 2 for its timing task but the others ( e.g TIM6, TIM7, or TIM15 ) should be available according to what i found out about mbed.
i am puzzled to what causes this behavior: is there something i am missing about the internals of mbed or am i just doing something plain wrong in my code?
on a side note: i get the timers to work when i do it in plain HAL with STM32CubeMX + SW4STM32, though using a different callback mechanic ( via HAL_TIM_PeriodElapsedCallback
).
i have just returned from an odyssey into timers on STM32. my goal was to write a sketch that uses a periodic interrupt to drive a DAC at an audio rate ( 20KHz – 48KHz ). i want to share some of my findings and also ask a question.
first i did the obvious and used the mbed
Ticker
class to configure a callback at 40 μsec. the following snippet illustrates what i want to achieve ( i replaced the DAC with an LED and reduced the update rate for illustration purposes ):mbed_ticker_approach
it worked ok-ish but i experienced some weird timing inconsistencies as soon as computations became more demanding. i found out that mbed uses just a single interrupt to drive all kinds of timing tasks. based on this understanding, i decided to investigate if a dedicated interrupt might work more reliably. after a lot of research i found an STM32-specfic solution that makes use of the underlying HAL:
nvic_and_HAL_approach
the code above works fine for my setup. however, when i choose a different timer than timer 3 ( TIM3 ), the callback never happens ( although the application runs ). on my nucleo_f072rb board mbed is using timer 2 for its timing task but the others ( e.g TIM6, TIM7, or TIM15 ) should be available according to what i found out about mbed.
i am puzzled to what causes this behavior: is there something i am missing about the internals of mbed or am i just doing something plain wrong in my code?
on a side note: i get the timers to work when i do it in plain HAL with STM32CubeMX + SW4STM32, though using a different callback mechanic ( via
HAL_TIM_PeriodElapsedCallback
).