Hello,
I am developing an application on the following platform:
MCU: NXP S32K314
RTD 7.0.0 (AUTOSAR MCAL)
FreeRTOS 7.0.0
S32 Design Studio 3.6.4
During development, I encountered a deadlock related to high-priority interrupts and would like to ask whether my understanding is correct and whether there is a recommended solution.
FreeRTOS specifies that ISRs with a priority higher than configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY must not call FreeRTOS APIs.
However, I found that many RTD MCAL APIs internally execute FreeRTOS critical section APIs through the following call chain:
MCAL API
↓
SchM_Enter_xxx()
↓
OsIf_SuspendAllInterrupts()
↓
SuspendAllInterrupts()
↓
OsIf_Interrupts_SuspendAllInterrupts()
↓
taskENTER_CRITICAL_FROM_ISR()and
MCAL API
↓
SchM_Exit_xxx()
↓
OsIf_ResumeAllInterrupts()
↓
ResumeAllInterrupts()
↓
OsIf_Interrupts_ResumeAllInterrupts()
↓
taskEXIT_CRITICAL_FROM_ISR()This behavior exists even in APIs that only perform simple peripheral register accesses, such as DIO and GPT.
When a MCAL API is called from a high-priority ISR (priority higher than configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY), the internal call to taskENTER_CRITICAL_FROM_ISR() causes the FreeRTOS interrupt masking state to become inconsistent.
As a result, after taskEXIT_CRITICAL_FROM_ISR() returns, BASEPRI is not restored correctly, causing lower-priority interrupts such as SysTick and PendSV to remain masked.
The scheduler eventually stops because xPortSysTickHandler() is no longer executed.
I was able to reproduce this issue using APIs such as:
Dio_FlipChannel()
GPT (PIT) interrupt processing
Other MCAL APIs that use SchM exclusive areas
To avoid modifying RTD-generated source code directly, I used the GNU linker --wrap option to wrap the following functions:
OsIf_Interrupts_SuspendAllInterrupts() OsIf_Interrupts_ResumeAllInterrupts()
The wrapper checks the current interrupt priority.
Please refer to the attached WrapperExample.c.
If the current ISR priority is higher than configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY, it skips the original function.
Otherwise, it calls the original implementation.
This workaround appears to resolve the deadlock while leaving the generated RTD source unchanged.
Is this behavior expected by design in the RTD MCAL?
Is it recommended to call DIO, GPT, CAN, or other MCAL APIs from high-priority ISRs?
Does NXP recommend implementing dedicated drivers (Complex Device Drivers) for high-priority real-time functions such as watchdog servicing or GPIO toggling?
Is wrapping OsIf_Interrupts_SuspendAllInterrupts() and OsIf_Interrupts_ResumeAllInterrupts() using the GNU linker --wrap option an acceptable workaround?
Is there an official or recommended solution for this problem that does not require modifying generated RTD source code?
Any advice or recommendations would be greatly appreciated.
Thank you.