I just discovered a horrible truth. We have ported our application to RTX RTOS v5. Our environment requires leaving one high priority interrupt running while disabling all others, including any kernel interrupts, like task switching. To accomplish this on ARM, I set the BASEPRI to allow only this one interrupt. In at lease one instance, our code disable interrupts and makes a kernel call (osNewMutex in this case) to create a global mutex on the fly that will be used by multiple threads. The OSs that our code was ported from allowed this. RTX does not. It returns NULL in this case.
So how do I make this work? Modifying existing code to prevent this will be difficult and may break existing products. I see that I will have to modify the existing RTOS5 library to allow for BASEPRI to be non-zero. Is it possible to temporarily boost the SVC interrupt priority to below the needed interrupt and exclude it from BASEPRI?
Hello. I have moved your query to the Keil specific forum, which will hopefully get a more targeted audience.
Hi Robert,
you can read more about RTX and ISR here: https://arm-software.github.io/CMSIS-RTX/latest/theory_of_operation.html
System IRQs used by the RTX (SysTick, PendSV and SVC) and should be configured with the lowest priorities and that is done by the RTX itself, as described here: https://arm-software.github.io/CMSIS-RTX/latest/theory_of_operation.html#cre_UsingIRQs
So, by default all other (user) interrupts should have higher priorities that system ones thus will preempt them and allow handling of those interrupts without the necessity of disabling system interrupts.
I am aware of this. Perhaps I should clarify my situation some. I'm working with legacy code, some which is 15+ years old. We have two hardware-specific functions DisableInterrupts() and RestoreInterrupts(). On all systems, they disable all interrupts except for the highest priority interrupt which must fire every 10 mS. Their function was meant to protect memory used by both threads and interrupts, somewhat the same function a critical section would do between threads. These two functions were used quite liberally in code, even where a critical section could have been used, especially where the processing time between the two functions is very short.
In many places we have code that does this:
static bool initialized = false;
DisableInterrupts
if (!initialized) {
CreateCriticalSection
initialized = true;
}
RestoreInterrupts
EnterCriticalSection
For RTX, DisableInterrupts sets BASEPRI to only allow the high priority interrupt. CreateCriticalSection calls osNewMutex(), which specifically looks at BASEPRI and returns NULL if it is not zero. The call to EnterCriticalSection does nothing.
Is there a way to work around this within DisableInterrupts and RestoreInterrupts without wholesale modification of our code?
from my view, DisableInterrupts and RestoreInterrupts should not do anything since higher-priority interrupts will happen anyways and preempt the current execution (either system interrupt of lower-priority interrupt or any application code (thread)).
Of course higher priority will happen in any moment of code execution thus if you are accessing the same memory that your higher-priority interrupt is also accessing that might be a problem.
Maybe, you can consider using producer-consumer concept, in which ISR just produces messages and application code just consumes them (meaning using mechanism called Message Queue).
RTX Mutex functions can't be used from ISRs, Semaphores however can, so maybe that would help if you don't want to change the concept of a whole application.
Best regards, Milorad