Cortex-A9 IRQ with priority over configMAX_API_CALL_INTERRUPT_PRIORITY

Hi guys, I’m using FreeRTOS on a Cortex A9 device (Xilinx ZYNQ). The final application will be used in the context of electric motor control so, in order to reduce control-law interrupt latency, I’ve register the related handler with a priority that exceeds configMAXAPICALLINTERRUPTPRIORITY. Given the previous setting the interrupt is properly triggered also under FreeRTOS critical sections – exactly as it’s expected to. I now intend to share data between application tasks and the aforementioned interrupt handler. To avoid race condition I intend to mask core interrupt, write the data, and then re-enable core interrupts. Something like the example reported below. Is this possible /is there a better way to do it? Does it interfere with FreeRTOS itself leading to system failure? ~~~ static uint32t EMPositionReferece = 0u; /* run in the context of the task / void EM_SetPositionReference(UINT32 user) { / mask CPU interrupt */ __asm volatile ( “CPSID i”); __asm volatile ( “DSB” ); __asm volatile ( “ISB” );
/* set motor-control position reference to be used in interrupt */
EM_PositionReferece = user;

/* 
 * NO FreeRTOS API usage here! 
 */

/* un-mask CPU interrupt */
__asm volatile ( "CPSIE i");
__asm volatile ( "DSB" );
__asm volatile ( "ISB" );
} void EMIRQHandler(void) { ControlLawExec(EM_PositionReferece );
/* 
 * NO FreeRTOS API usage here! 
 */
} ~~~ As last thing, in the previous example the interrupt are fully masked and then unmasked. Is there a way (e.g. a dedicated CPU instruction) to get interrupt masking status and simultaneously disabling them? What I want to achieve is something like the line below ~~~ /* mask interrupt and get previous masking status */ irqMask = _MaskIRQ(); /* * set motor-control variable shared with IRQ */ /* restore interrupt masking status read at _MaskIRQ */ _RestoreIRQ(irqMask); ~~~ Thanks in advance, Bucky

Cortex-A9 IRQ with priority over configMAX_API_CALL_INTERRUPT_PRIORITY

I’m afraid I don’t know if there is a single asm instruction that will do what you want (return the previous interrupt mask and disable as a single atomic operation) – but there could well be. As to whether the code you posted will interfere with the kernel – I don’t think it will. Globally disabling and re-enabling interrupts the way the first code you posted is doing is fine PROVIDED THAT you can always guarantee that interrupts were already enabled – otherwise you need to restore the previous interrupt state rather than just blindly re-enabled (as you know, because that is what the second part of your post is doing). The kernel only globally disables interrupt momentarily when it is updating the interrupt mask (that is a requirement of the interrupt controller), and your code cannot execute between the kernel’s own disable/re-enable sequence. Therefore the kernel will not have disabled interrupts when your code executes and only you know if anything else in your code will have done. If in doubt then you can keep a count of the disable nesting yourself, and only re-enable when the nesting returns to 0. As an example look at the implementation of vPortEnterCritical() and vPortExitCritical() in the kernel’s port.c file that you are using. That keeps its own nesting count for the interrupt priority mask level, you would need to do the same but for the global interrupt enable instead of the interrupt mask level.

Cortex-A9 IRQ with priority over configMAX_API_CALL_INTERRUPT_PRIORITY

Another option for updating the parameters ‘atomically’ (especially if you tend to possibly adjust most of them) is to have two copies of these with a flag to indicate which set is ‘active’, and your program then can update the inactive set, and when they are all updated switch the flag to make the ISR use the now updated set.