Hello All.
I have a porting of FreeRTOS on Cortex-R52 and I have some doubts about the right priority assigned to the interrupts.
In my applications, typically all the ISR, registered by the peripherals, have a priority greater then the configMAX_API_CALL_INTERRUPT_PRIORITY.
I understand, these ISR never be delayed by anything the kernel is doing, can nest, but cannot use any safe API.
Note that the priority is directly used for programming the GIC registers.
Actually, these ISR (for all my IP) will never call “FromISR” functions in my applications but…
Q1) is there any example of a driver that needs to call safe API inside own ISR?
Q2) For ARM, the higher numeric interrupt priority values indicates the lower logical interrupt priorities. I have not clear if the meaning configMAX_API_CALL_INTERRUPT_PRIORITY remains the same. I mean, this is still the logic:
Q3) the System Timer should have the lowest priority as reported in the port.c. In my FreeRTOS, the configMAX_API_CALL_INTERRUPT_PRIORITY = 8, then peripheral registers the handler with prio > 8, but the FreeRTOS_Tick_Handler has 4. Is it correct?
Are you looking for a code example, or just asking under what conditions would a driver need to call an API inside an ISR?
When you are using a simple priority based preemptive scheduler, such the FreeRTOS scheduler, you don’t want a task to be polling for IO because by polling it is preventing any lower priority task from running. Instead you want the task to wait in the Blocked state until the IO is available - in which case the FreeRTOS API is used in the ISR to unblock the task when data is available. There are many ways of doing this, so let me know if I’m missing the point of your question.
The max system/api call interrupt priority always sets the highest LOGICAL interrupt priority from which an API can be called. As you say, on ARM systems the lower the numeric interrupt priority the higher its LOGICAL priority - so on ARM systems, if configMAX_API_CALL_INTERRUPT_PRIORITY is set to x, then interrupts with a NUMERICAL priority value greater or equal to x can call the ISR safe API, because interrupts with a NUMERICAL value greater or equal to x have a lower LOGICAL interrupt priority. Generally this is much easer to understand on non-ARM systems because then high numerical value means high logical value.
If the max API call priority is 8 the, on an ARM system, I would expect the tick hander to have a priority numerically greater than or equal to 8. In that case, and without re-reading all the docs, 4 would not see to be a good value because it has a logically higher priority than 8.
Hi Richard
many thx for your prompt feedback and you covered my questions. Really appreciated.
I have another question.
Experimenting with my Ethernet driver, I implemented the Tx/Rx inside the ISR w/o invoking any Task. I mean, for example the incoming frames are passed to the TCPIP stack from the ETH ISR.
So I implemented the xSendEventStructToIPTaskFromISR.
When I refill the RX resources I should invoke functions like: pxGetNetworkBufferWithDescriptor and pvPortMalloc (depending on ZERO copy) I guess they are not designed to be called at interrupt time. What do you think, maybe I should use queue? Or is it better and simpler to fallback to a task implementation based?
It is best for these things to be deferred to a task - you can look at other MAC drivers in the distribution to see how that is done. Generally (although it depends on the individual system), you would have the priority of the TCP/IP task above the priority of the application tasks, and the priority of the task that handles MAC events at a higher priority than the TCP/IP task.
If you have the task that handles MAC events at a very high priority then it can spend most of its time waiting for the MAC ISR to tell it there is something to do. The MAC ISR can do that by sending the task a direct to task notification, then yielding in the ISR, so the MAC ISR interrupts one task, but returns directly to the task that is handling the MAC ISR, so the MAC processing occurs immediately, just as if it were done in the ISR itself.
On ARM Cortex A the interrupt, which uses FreeRTOS API calls, has to have a priority setting lower than the configMAX_API_CALL_INTERTUPT_PRIORITY which means that the number has to be bigger than that value of this config paramater. Also, I had to use the portPRIORITY_SHIFT when setting the interrupt priority because I think there is some masking taking place and not all interrupt value bits are valid to use. SO after setting my priority setting code to following the interrupt fired nicely and there were no assertion errors: // set the priority of IRQ_F2P[0:0] to 0x04 (highest 0xF8, lowest 0x00) and a trigger for a rising edge 0x3.XScuGic_SetPriorityTriggerType(&xInterruptController, INT_ID, (configMAX_API_CALL_INTERRUPT_PRIORITY \+ 1) << portPRIORITY_SHIFT, 0x3);