0
votes

I want to blink a led (toggle a GPIO pin) synchronously with an hardware timer configured to rise an interrupt at 50KHz on an ARM Cortex M4.

In my current code, I toggle one GPIO pin into one specific ISR handler triggered on a 50KHz external clock signal. The result is that the GPIO pin is toggled very erratically at random frequencies from 1KHz to 96KHz.

The Operating System is not running any other task apart from the Timer Tick Interrupt (100Hz with the lowest priority) the IDLE Task and my specific ISR handler.

Otherwise, this "toggling solution" is working perfectly with a Bare Metal implementation on the same MCU. So, my problem seems to come from my lack of knowledge in the FreeRTOS environment.

  1. Is it feasible to toggle a LED into a FreeRTOS ISR at 50 KHz ?
  2. Do I need to do it into a task waiting for the 50KHz interrupt signal ?
  3. Should I create a timed toggling task at 50KHz and synchronize it periodically with the external clock signal ?
3
What do you mean by a "FreeRTOS ISR"? How did the ISR implementation change from your bare metal implementation to the FreeRTOS implementation? Why did it have to change at all?kkrambo
Hi @kkrambo, "FreeRTOS ISR" means Interrupt Service Routine, no matter if it is on FreeRTOS or not. Actually, both my ISR code on FreeRTOS and bare metal are exactly the same. The difference may resides in the FreeRTOS multitasking behavioral. It could come from the configuration of priorities, the nested interrupts management, the interrupt overhead. As the ISR priority is the highest in the FreeRTOS system, I though that my 50Khz interrupt would have run before everything else...fbourge
ARM Cortex M4 only specifies the core and that does not include hardware timers - you should specify the part itself. Most hardware timers on most microcontrollers can drive GPIO pins (via their PWM function) directly with zero software overhead; if you want an accurate 50 KHz signal you should use a PWM output. Bit-banging a 50KHz signal in an interrupt will present significant CPU load and will affect the determinism and real-time performance of other tasks and ISR's that this one preempts. And accuracy depends on the OS or application never disabling interrupts.Clifford

3 Answers

2
votes

If you want the 50K to be accurate (no jitter) the priority of the interrupt would have to be at or above configMAX_SYSCALL_INTERRUPT_PRIORITY: https://www.freertos.org/a00110.html#kernel_priority and https://www.freertos.org/RTOS-Cortex-M3-M4.html (assuming you are using a port that supports interrupt nesting).

2
votes

I finally find out that the instruction cache was not enabled in the FreeRTOS implementation of my 50KHz ISR unlike in the Bare Metal version. It's now almost working as expected (some jitter remains).

In reply to my questions I suggest the following :

  1. Is it feasible to toggle a LED into a FreeRTOS ISR at 50 KHz ?

Definitely yes. FreeRTOS can perform ISR at any frequencies. The feasibility only depends on the computational capablities of the MCU added to the instruction and data access performances. For sure FreeRTOS will add some delays compared to a Bare Metal implementation to process an ISR (ISR overhead and port efficiency) but once again, this will be more or less significant depending of the MCU's computational performances and the considerate frequency.

  1. Do I need to do it into a task waiting for the 50KHz interrupt signal ?

Not necessarily. Anyway, this is a good alternative if an irregular or a rather important processing is needed. However the FreeRTOS deferring instructions will cost time and may be too much to end the processing before the next ISR. More resilient but less efficient. In my case at 50KHz, this cost too much time regarding the average amount of processing per ISR.

  1. Should I create a timed toggling task at 50KHz and synchronize it periodically with the external clock signal ?

Not feasible unless reduce the system tick frequency significantly which will cause a severe loss of performance.

1
votes

You could not get 50 KHz by FreeRTOS mechanisms.

Оf course, you can try but this bad idea. So you should change system tick at least 10uS(1 / 50KHz / 2 ) in this case your task will have small latency(it allows react "immediately"), but context switch ISR will be called very often and this reduces performance.

The right way is using hardware timer to generate the interrupt (for toggle GPIO) or use timer with PWM output in this case frequency accuracy depends on clock source. In order to synchronize timer from external sources, you should use the external interrupt and additional timer with high accuracy (at least 10uS)