0

I need a high precision interrupt for my STM32F7. The task is to increase a counter at every tick. The frequency of the CPU is up to 216 MHz (from datasheet) which means an tick duration of around 5 ns can be achieved right?

After some internet research I found out that sysTick can be used for this purpose. I should simply configure the SysTick as follows:

/** Configure the Systick interrupt time */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

/**Configure the Systick */
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

I'm toggling a GPIO pin inside the SysTick_Handler function to check the frequency of execution and it is 1 ms.

I want to achieve a tick duration of 1 microsecond so I replaced the 1000 (in the code) with 100, then I tried different numbers but nothing seems to affect the 1 ms duration.

Am I missing something here? Is there a better solution than the sysTick to achieve this goal?

Thanks.

Kalkhouri
  • 341
  • 1
  • 6
  • 16
  • 1
    "The task is to increase a counter at every tick. " What do you mean by "counter" and by "tick"? At 500Mhz/5ns, increasing a variable at each tick is not possible. – Yunnosch Aug 18 '18 at 13:00
  • by a counter I mean a uint32_t variable. by tick I mean every time an interrupt is called (period between two ticks should be 1 microsecond if not possible to get better). sysTick interrupt is already being called every 1 millisecond and I want to achieve at least 1000 times this rate. – Kalkhouri Aug 18 '18 at 13:20
  • 1
    Well, be sure to not call an OS scheduler at that frequency! If you are in that place, inc your integer and call the existing scheduler every 1000 interrupts. – Martin James Aug 18 '18 at 13:47
  • 2
    Precision is not the same as resolution. Is resolution what you need? Hardware timers already have an internal counter that can be incremented every tick. Why interrupt and increment a software counter when you can just read the hardware counter at any time without an interrupt? – kkrambo Aug 18 '18 at 14:23
  • 2
    ^^also that, or if you need the best interrupt timing, use the timer with the highest-priority for you needs, and relegate the OS systick to a lower-priority timer. – Martin James Aug 18 '18 at 15:49
  • 1
    What is your real goal? "Increase a counter" is not a goal, it is a means to an end. With interrupts at 1µs your system won't do much else, so better use a slower interrupt rate (1ms is OK) and read out the Systick counter for precise timing. – starblue Aug 18 '18 at 17:52
  • 1
    my real goal is simply to do_something() at a specific time and periodically. I'm very new to the field of microcontrollers so I'm not aware of the common solutions in this case so I thought to use a tick interrupt to increase a counter which helps me calculate the period of time at which my function do_something() should trigger. This period is supposed to be in the range of microsecond. According to the comments here, my idea doesn't seem to be the best solution so I will check how to do this with a hardware timer as recommended. do you mean by hardware timers TIM1, TIM2, etc? – Kalkhouri Aug 18 '18 at 21:34

1 Answers1

1

You can't (and shouldn't!) increase some variable each clock cycle. Instead, you should use a hardware timer (TIMx) for such a precision measurement.

In general, there are few suitable approaches:

  1. Use a scheduler. Set up a hardware timer to generate an interruption on overflow and configure it to overflow once in 20us–20ms depending on necessary time granularity. In the interruption routine check if you should do_something() in current scheduling cycle and do, if so. It's extremely important to keep the interruption routine short and surely finite (without long software cycles etc.), especially when the timer period is short.

  2. Use one-shot timers. If you need to execute only one routine or the order is strictly defined, you can use following approach. In the end of your do_something(), configure and start a hardware timer which will launch do_something() again after the necessary amount of time. So in the interruption routine you just launch do_something(), then in the beginning of do_something() you reset the timer, do your job and set up the timer again. This way you can control the delay up to single clock cycle. However, this solution is much more difficult to maintain and expand.

  3. Combine. You can use a scheduler that spins a one-shot timer to control the execution start time precisely.

Scheduling is heavily researched area of MCU software development. There are lots of articles on it as well as mature real-time operating systems for MCUs capable of this and much more such as FreeRTOS or ChibiOS. If it's commercial project you usually should stick with common tools like FreeRTOS instead of writing your own scheduler. However, of course, it's very educational — and it's fun!

Ankor
  • 694
  • 1
  • 6
  • 13