GCC ARM CM3 port configuration issue

darrenjenkins wrote on Tuesday, May 22, 2012:

I have noticed that (due to the way that interrupt masking uses configMAX_SYSCALL_INTERRUPT_PRIORITY to set basepri) it is not valid to have an ISR containing freeRTOS interfaces at priority level 0 (highest).
This has bitten me, and may bite other users of this port.
Is the port maintainer likely to want to clean this up him/herself? or would it be more suitable for me to submit a change to clean this configuration dificulty up ? and if so how and where can I do this ?

Thanks for your attention.

rtel wrote on Tuesday, May 22, 2012:

As you elude to in your email, only interrupts at or below configMAX_SYSCALL_INTERRUPT_PRIORITY can call interrupt safe FreeRTOS functions (those that end in FromISR).  The port never completely disables interrupts, and interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY are never disabled. 

Interrupts at or below configMAX_SYSCALL_INTERRUPT_PRIORITY get masked in critical sections using a bit mask in basepri.  To allow interrupts of priority 0 to call interrupt safe FreeRTOS functions it would be required to have a bit mask that masks off interrupts at priority 0, and you cannot have a 0 bitmask on a Cortex-M core because the core itself (i.e. there is nothing the software can do about it) treats 0 as a special case that means all interrupts are enabled.  This is a quirk of the backwards interrupt priorities on Cortex-M cores (where low values mean high priority), because there has to be a mask which means enable everything, and that mask cannot be 0xff because 0xff means mask all but the very lowest priority.

I would personally be very interested in any alternative you had for this, because I don’t think there is one other than globally disabling interrupts (not desirable), but if you come up with something I’m afraid it is unlikely to make it into the main line code because it would probably result in more lines of code for a result with less functionality.


darrenjenkins wrote on Tuesday, May 22, 2012:

if configMAX_SYSCALL_INTERRUPT_PRIORITY is 0 you want to mask _all_ interrupts, which is equivalent to disabling them.
I was thinking of something like

#define portSET_INTERRUPT_MASK()						\
	__asm volatile										\
	(													\
		"	mov r0, %0								\n"	\
		"	msr basepri, r0							\n" \
#define portSET_INTERRUPT_MASK() asm volatile ("cpsie i");

with something similar for portCLEAR_INTERRUPT_MASK and xPortPendSVHandler.

Which is just some simple code to make it work, in that specific configuration.


rtel wrote on Wednesday, May 23, 2012:

Yes - I think that would work without adding more code.  I was thinking about having an ‘if’ in the asm code, but doing it with the pre-processor is better.  I had to think for a moment if this would break the interrupt nesting code (where the current mask level is stored and then restored as you enter/exit critical sections in ISRs), but I think because the NVIC is intelligent on the CM3 it will be ok.  That is why the macros for the interrupt same critical sections don’t even store the mask and just restore it to 0 (saves time/space and has the same effect).

Could you do me a favor and add this to the “feature request” tracker.