Calling a FromISR API in ISR causing kernel freeze or crash in Cortex-A9 port

Hi All,

I suspect that portable code for Cortex-A9 has an issue after calling a FromISR API in ISR.

Looking at xQueueGenericSendFromISR() API, it enters critical section at the beginning of the func by the following code:

uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();

Interrupt status is saved in uxSavedInterruptStatus.

Before leaving the function, it calls portCLEAR_INTERRUPT_MASK_FROM_ISR macro to exit the critical section:

portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );

Actual code of the macro on Cortex-A9 platform is vPortClearInterruptMask function, defined in FreeRTOS/Source/portable/GCC/ARM_CA9/port.c like the following:

void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{
    if( ulNewMaskValue == pdFALSE )
    {
        portCLEAR_INTERRUPT_MASK();
    }
}

This code resets interrupt priority mask register to the lowest priority, 0xFF, rather than the original one which was set to the register at the beginning of ISR.
I guess that this code results in allowing an another ISR at any level of priority to be called even if the first ISR is still running. SysTick ISR can be called under the situation, causing undesired task switching during ISR.
Isn’t this causing a serious problem?

I also think that some posts in this forum on Cortex-A9 platform may be related to this issue.

Correct me if I am misreading the code.
Thanks in advance,
Morizzo

Thanks for pointing this out. I will need to re-familiarise myself with the workings of the GIC before knowing for sure if this is an issue. On the Cortex-M (to be determined on the Cortex-A) the mask is always set back to zero and in that case it is safe as
the hardware itself will prevent the effective priority mask value (rather than the value in the register) from ever being below the priority of the currently executing interrupt. In other words the hardware will prevent a lower priority interrupt from interrupting
a higher priority interrupt no matter what value you write into the interrupt mask vale from within the interrupt itself.

Reading the manual now, but in the mean time, can you confirm that your issue is resolved if you restore the original mask value rather than clearing the mask to 0xFF? You would need to alter the function that sets the mask to return the original value rather than just pdTRUE or pdFALSE.

Sorry - one other note reading the code - even if the GIC does allow lower priority interrupts to interrupt higher priority interrupts if the mask is set to 0 I think the interrupt entry code should still handle that as a nested interrupt (even if it inverts priority)…still reading though.

Thanks for your effort to look into this.

I was digging into my issue for days and found that reverting interrupt priority back to original value didn’t solve the issue.
In my application using Cortex-A8 instead of A9, I should be careful of using nested interrupts. SysTick interrupt might be potentially called once right after entering FreeRTOS critical section and re-enabling ARM interrupt by CPSIE and then SysTick service reverted priority threshold to FFh in Cortex-A port while the task was still running in the critical section.

Thanks for your support,