Newbie to freeRTOS, so please be gentle with me?
I am using freeRTOS on an embedded project using NXP IMXRT microcontrollers (~ 550MHz Cortex M7) and I had a question about the recommended method for handling “fast” events - and by fast I mean anything in the range say 1 us to 100 us (us = microseconds).
So far, I am not using any freeRTOS kernel services but instead am using the MCU’s hardware timers to generate an interrupt every, say, 1 us. Then in the ISR all I do is modify a global variable (typically decrement it) and in the main code, write a new value to that global variable and then sit in a while() loop waiting for it to reach zero. However whilst this system seems to work OK, I am running into occasional issues where the code sometimes hangs in the while() loops (currently there is no timeout in the while() loops, in the future there will be). I suspect this might be due to atomicity issues when updating the global variable, but this is not yet proved.
So my broader questions is, what is the recommended method for doing this kind of thing in a freeRTOS environment? How do others typically do this?
thanks in advance!
This kind of device driver / interrupt processing is usually done in modern FreeRTOS by using task notifications (supported since version 10.x.y) set by an ISR waking up a corresponding deferred processing task.
Depending on MCU clock and speed 1 us event rate might be pretty high, because there is a certain (small) overhead using a multitasking OS. But if you just need the event when the counter reaches 0 it‘s obviously better to notify the task only about this transition…
However, this depends on your actual device driver and what you have to do in your application.
To add to hs2’s comments - make sure the priority of the interrupt is above configMAX_SYSCALL_INTERRUPT_PRIORITY so nothing the kernel does will disable that interrupt - see https://www.freertos.org/RTOS-Cortex-M3-M4.html (same holds for M7, even though the URL says M3 and M4).
Can’t comment on the atomicity question without seeing the code.
Thanks both. I’ve not used task notifications yet but I’ll take a look into that.
I’m using the NXP mcuxpresso SDK and in that, configMAX_SYSCALL_INTERRUPT_PRIORITY is setup by default to be 32 decimal. In my system configMAX_PRIORITIES is set to 18, and my application has so far 5 or so tasks with their priorities set between 1 and 5. This is all new to me and so I am not completely sure if this meets your requirement or not?
In case of confusion. configMAX_SYSCALL_INTERRUPT_PRIORITY is related to interrupt priorities. Interrupts are controlled by hardware, and you can only call FreeRTOS API functions from interrupts at or below configMAX_SYSCALL_INTERRUPT_PRIORITY. That is unrelated to task priorities as configMAX_PRIORITIES relates to task priorities only.
thanks very much for the explanation - that is clear now, but it wasn’t before!
I’ll check but I am pretty sure the priority for the interrupt in question is higher than 32 decimal (i.e. a lower number) - it’s a one microsecond timer interrupt, with a higher priority in order to minimise jitter.