I need to implement foreground/background system where foreground processing is done in timed interrupts which cannot be disabled by FreeRTOS. Foreground never calls any of the FreeRTOS APIs. Eventually, foreground will trigger an interrupt which will tick FreeRTOS timer and that interrupt and other with deffered “background” processing can be under RTOS critical section control.
When looking at CM0 port I see portSET_INTERRUPT_MASK_FROM_ISR(),portCLEAR_INTERRUPT_MASK_FROM_ISR(), portDISABLE_INTERRUPTS() and portENABLE_INTERRUPTS() which all disable all interrupts. They also seems to be called freely from different spots in FreeRTOS code. There seems to be no obvious way of modifying these for what I need to do.
Could someone suggest how to approach separation of interrupt control in FreeRTOS between interrupts that OS doesn’t know about and the ones that it does?
From CM0 port file, it uses cpsid i to disable all interrupts while entering critical section. Even thought it can disable/enable specific interrupt by NVIC, it might cause some race condition during process.
Is CM0 mandatory? It might be easier to achieve that by using different core which support selective interrupt masking.
Yes, CM0 is the MCU core because selected part has all that is needed for application for acceptable price.
The question here is really if NVIC mask can be used reliably with FreeRTOS to control critical sections and not to intefere with FreeRTOS behavior?
The problem with NVIC enabling/disabling of interrupts is that you need to know which interrupts to enable/disable, and doing a list of them tends to be slow.
If your processor has a level mask in the NVIC, then that can be used, and you just don’t disable the levels that don’t use FreeRTOS and they won’t be block by the critical section.
This is the method that higher Cortex M series use, as that level control is part of the core, so available on all parts of that level. The supplied ports tending to be a lowest common denominator design to avoid needing thousands of ports.
AFAIK, ARMv6-M doesn’t have BASEPRI register an thus level masking is not possible. That leaves only one option NVIC mask. Since that is 32b value and interupt selection is static using NVIC mask shouldn’t be big deal.
Are mentioned above port APIs the only ones that need to be updated or there are other spots in CM0 FreeRTOS port where global interrupt control is done outside of those APIs?
The kernel doesn’t know how to enter a critical section other than the API provided by the port.
Thus, defining a new version of the API that turns off and on the set of interrupts that you define are needed to be masked to keep the system stable (all the ones that might interact with the kernel) is sufficient.
Note, this means you REPLACING the whole “port” layer, which is just a couple of files with a new one. (or editing the existing files, but I don’t suggest doing that).
Note, EVERYTHING that begins with “port” will be defined in the port layer, so is changable by providiing a new port.
FreeRTOS was built on this kernel/port layer just to allow for such things. Now, perhaps a revised CM0 port that used this method might be a reasonable submission to be added to the collection of ports.