portDISABLE_INTERRUPTS() question on SMP

Hi,
I am porting smp on arm cortex-a7 using gic-v2 and the portable part is refered to portable/GCC/ARM_CA9.
I followed the SMP change description to porting. I continued to use portDISABLE_INTERRUPTS() and portSET_INTERRUPT_MASK_FROM_ISR()portDISABLE_INTERRUPT,because they match the description in the documentation.

portDISABLE_INTERRUPTS()
This must now also return the interrupt mask prior to disabling. It may still be called without
checking the return value.

portDISABLE_INTERRUPTS() sets GICC_ PMR and clears CPSR I bit to enable IRQ.

The FreeRTOS_SWI_Handler and FreeRTOS_IRQ_Handler is also implemented as same as ARM_CA9/portASM.S, but stack corruption happends. Because interrupt is re-enabled is vTaskSwitchContext( CoreID ) which will calls xTaskGetCurrentTaskHandle() and portDISABLE_INTERRUPTS, IRQ is re-enabled at this time and interrupt preempts vTaskSwitchContext().

Main branch has added new marcore portSET_INTERRUPT_MASK() which has return value. I want to know what is the difference between portSET_INTERRUPT_MASK() and portDISABLE_INTERRUPTS and how to implent them.

Thank you!

I do not see a call to xTaskGetCurrentTaskHandle in vTaskSwitchContext, Are you using the latest code in the main branch?

No, I am using old smp branch smp.
xTaskGetCurrentTaskHandle() in main branch uses portSET_INTERRUPT_MASK() instead of portDISABLE_INTERTUPT().

I’d suggest switching to main branch as smp branch is now deprecated.

Some platforms allow us to mask interrupts selectively. We divide interrupts into 2 parts on such platforms -

  1. High priority interrupts - these are not masked by FreeRTOS critical sections. You cannot call FreeRTOS APIs from the corresponding ISRs.
  2. Low priority interrupts - these are masked by FreeRTOS critical sections. You can call FreeRTOS APIs from the corresponding ISRs.

portSET_INTERRUPT_MASK is helpful when you want to mask interrupts selectively. The call sequence looks like:

            uxSavedInterruptStatus = portSET_INTERRUPT_MASK();
            {
                /* Critical section code. */
            }
            portCLEAR_INTERRUPT_MASK( uxSavedInterruptStatus );

If you want to disable all the interrupts always, you can choose to implement portSET_INTERRUPT_MASK using portDISABLE_INTERTUPT.

Got it! When using gic, mask interrupts selectively by setting GICC_PMR to configMAX_SYSCALL_INTERRUPT_PRIORITY, I will try main branch. Thanks for your reply.

BTW, is there any relevant implements that can be refered to?

1 Like