vPortValidateInterruptPriority() bug or feature?

stephanhd wrote on Sunday, January 18, 2015:

printf(“hello world!”)

I am just on 8.2.0 (FreeRTOSV8.2.0\FreeRTOS\Source\portable\IAR\ARM_CM3) port.

I wonder if the following code really works or if i had to continue studying…


// (port.c)
vPortValidateInterruptPriority( void ){
	uint32_t ulCurrentInterrupt;
	uint8_t ucCurrentPriority;
	/* Obtain the number of the currently executing interrupt. */
	__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );

	/* Is the interrupt number a user defined interrupt? */
	if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ){
		/* Look up the interrupt's priority. */
                    //ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];

[…]

Since pcInterruptPriorityRegisters is pointing to the very beginning of the NVIC_IP table at [#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )], pcInterruptPriorityRegisters[ ulCurrentInterrupt] will in my opinion point to the wrong location (by 16 Byte to short).

Using this small modification:


ucCurrentPriority = pcInterruptPriorityRegisters[ portFIRST_USER_INTERRUPT_NUMBER + ulCurrentInterrupt ];
ucCurrentPriority will be derived from the correct IRQn.

What do you think?

Kind regards, Stephan

davedoors wrote on Sunday, January 18, 2015:

I was sure the code is right because I tested it when it first appeared in FreeRTOS, and I dont think it has changed since. But you made me doubt myself so I looked again.

I think you have made a mistake here

Since pcInterruptPriorityRegisters is pointing to the very beginning of the
NVIC_IP table at [#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )],

The table begins at 0xE000E400 so the OFFSET_16 refers to a negative 16 from the start of the table. pcInterruptPriorityRegisters is not pointing to the very beginning of the NVIC_IP table it is pointing 16 bytes behind the beginning of the table.

But if you thought pcInterruptPriorityRegisters pointed to the start of the table I dont see why your modification is adding portFIRST_USER_INTERRUPT_NUMBER to ulCurrentInterrupt rather than subtracting portFIRST_USER_INTERRUPT_NUMBER from ulCurrentInterrupt?

stephanhd wrote on Sunday, January 18, 2015:

Hi Dave and thanks for taking care!

please let me explain how I came to this point: (using IAR EWARM; Cortex M4 - AT91SAM4S)

1.) NVIC_SetPriority(28, 11); // set somewhere at start; value visible in NVICIP29
2.) then PIOB_Irq is fired
3.) and PIOB_IrqHandler is called
4.) some MessageProcessing is done and via xQueueSendToFrontFromISR() …
5.) … in vPortValidateInterruptPriority():

   __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );

ulCurrentInterrupt is derived as 28 (0x1C). 
Perfect as it fits to __vector_table[28] == PIOB_IrqHandler() :)

6.) Status at this point in time:
* 0xE000E3F0: it contains (uint8_t)0x00
* 0xE000E400: it contains (uint8_t)0x00
* 0xE000E40C: it contains (uint8_t)0x00 (this is pcInterruptPriorityRegisters[ulCurrentInterrupt])

But:
* 0xE000E41C: contains (uint8_t)176 (0xB0) // (11 << 4) from (step 1.)

and this is exactely: 0xE000E3F0 plus 16 + 28 == 0xE000E41C
pcInterruptPriorityRegisters[portFIRST_USER_INTERRUPT_NUMBER + ulCurrentInterrupt]

This is as I could see it in the debugger …

Indeed: if portNVIC_IP_REGISTERS_OFFSET_16 would not be pointing to 0xE000E3F0, but to 0xE000E400 (the real start of the NVIC_IP) then pcInterruptPriorityRegisters[ulCurrentInterrupt] would be fine as well.

Maybe you can help me to get the knot out of my brain? :wink:
Kind regards, Stephan

stephanhd wrote on Sunday, January 18, 2015:

I found it by myself. Finally it was too simple :slight_smile: shame on me :wink:

I made the mistake to set the idx of the __vector_table[] equal to the numbering of the specific IRQs like PIOB_IRQn; which is 12 and thats __vector_table[16 + 12 == 28].

So setting NVIC_SetPriority(28, 11) is bullShit as it set the NVIC_IP for IRQ28 which is not equal PIOB_IRQn…
Use NVIC_SetPriority((IRQn_Type)PIOB_IRQn, 11) instead…

Ok sessions learned; thanks a lot and good night!
Kind regards, Stephan

p.s.
FreeRTOS is a really cool thing!