cancel
Showing results for 
Search instead for 
Did you mean: 

Read Systick Timer Value Directly for 1ms Timebase

EPala.2
Associate III

Hi, I am working on a project on the STM32H730 that runs a high priority audio interrupt thread as well as a lower priority asynchronous loop for user interface processing and a 1ms SysTick interrupt for user interface processes that need some accuracy in the timing.

I'm running into an issue where if my audio processing interrupt takes longer than 1ms (as is the case doing intensive processing at a 32kHz sample rate with a 128 sample buffer size) to execute SysTick interrupts no longer happen reliably once per ms. 

I imagine I can recreate this functionality by setting a timer to increment once per millisecond independent of the CPU and referencing this value whenever I need an accurate time reference. 

 

What function can I call to get the value of SysTick directly to compare to a global timer variable? Does this sound like the right approach? 

17 REPLIES 17

Is there a SysTick->CNT that could be accessed without additional configuration?

Pavel A.
Evangelist III

If there's a 16-bit timer available, you can make a free running 1 ms counter without any interrupts. Just read the timer counter, from any context. Intervals will be limited to 16 bit ( ~ 65 seconds). With a 32-bit timer intervals will be much longer, if anyone ever needs this.

 

Are you able to share what the MX configuration for setting up a 1ms timer looks like? 

As I stated in my last post, the MX UI is unfortunately not very intuitive for how to achieve this. It does not display a clear period or frequency value for the clock source or for the timer post prescaler.

Could the 16-bit timer be reset after reading in order to get an elapsed millisecond value?

Would this syntax work? Or is there a function I need to call to reset the timer counter?

static uint32_t global_ms = 0;

uint32_t elapsed_ms = TIMx->CNT; 
TIMx->CNT = 0;

global_ms += elapsed_ms;

 

 

No, the whole idea is that you don't keep any global_ms (or use a different clock for "wall time").

If you want also to use the well known function HAL_GetTick, the timer must be 32-bit. 

I think there is some misunderstanding: the whole idea is that I don't set global_ms with an interrupt, but by checking a timer value which is incrementing independent of the CPU, whether I store global_ms as a variable or look directly at the timer value is more flexible.

Are you able to please address my question of what the MX setup for a 1ms timer looks like?

>  the whole idea is that I don't set global_ms with an interrupt, but by checking a timer value which is incrementing independent of the CPU

"Independent of the CPU" means free-running. If you have a "main loop" or background task that  spins much faster than 1 cycle per ms, you can disable the systick interrupt and check the systick overrun event in this background code, and increment the counter when you see the overflow flag.

Are you able to please address my question of what the MX setup for a 1ms timer looks like?

Sorry but no. First, find a free timer. If there's a 32-bit timer, you're golden. Just set a prescaler so that one bit of the timer counter is 1ms, and you can use HAL_GetTick() for delays and timeouts. If only 16-bit timers are available, things will be more complicated.

 


@EPala.2 wrote:

Are you able to share what the MX configuration for setting up a 1ms timer looks like? 

As I stated in my last post, the MX UI is unfortunately not very intuitive for how to achieve this. It does not display a clear period or frequency value for the clock source or for the timer post prescaler.


Your screen shot shows the APBx as 275MHz. Simple math.

0.001(second) * 275MHz = 275000 (counter period).

 

275000 is within 4294967295 (32bit counter) so prescaler can stay at zero.

Auto-reload enabled, count down, NVIC enable, Update event.  

If you want to count up, then that's simple math too.

 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.