[Cortex] using ISRs before starting scheduler

bodev wrote on Friday, November 21, 2008:

Hi all,
   in the Main(), i need to initialize some low level components and their FreeRTOS drivers.
Drivers are implemented through queues, semaphores and/or tasks.

in some components i need to insert a precise DELAY, so i am using internally a timer.

the function Delay(ms) set up the timer and then poll on a variable. The Timer handler is finally called and the loop will stop.

NB: i am doing this because the scheduler is not started yet.

the problem i am experiencing is that if i use such Delay(ms) _after_ i created even one queue/semaphore/task (whatever it is), then the delay works iff the timer priority level is lower than 11 (–>it is high priority)

any suggestions or hints on why is this happening?

Regards
Bo

davedoors wrote on Friday, November 21, 2008:

The kernel will leave interrupts up to the configKERNEL_INTERRUPT_PRIORITY disabled following most API calls that are made before the scheduler is started. I think this is to ensure that interrupts don’t attempt to cause a context switch before the scheduler has been configured and started. You could probably call taskENABLE_INTERRUPTS() after an API call to set the interrupt mask level back to zero.

bodev wrote on Friday, November 21, 2008:

Hi Dave and thank you very much for the reply.
In fact, i tried using your suggestion after API calls and all works perfect!

However, according to the documentation,

taskDISABLE_INTERRUPTS (–>portDISABLE_INTERRUPTS–>portSET_INTERRUPT_MASK–>configMAX_SYSCALL_INTERRUPT_PRIORITY)

use configMAX_SYSCALL_INTERRUPT_PRIORITY and not configKERNEL_INTERRUPT_PRIORITY as you mentioned. correct?

in this case, configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 191 (and the comment says it is equal to Cortex level = 5) while my timer worked with isr level < 10.

can you or someone here shed some light on this "priority" topic? i am totally confused…

Thanks a lot,
Bo

bodev wrote on Friday, November 21, 2008:

Hi Dave and thank you very much for the reply.
In fact, i tried using your suggestion after API calls and all works perfect!

However, according to the documentation,

taskDISABLE_INTERRUPTS (–>portDISABLE_INTERRUPTS–>portSET_INTERRUPT_MASK–>configMAX_SYSCALL_INTERRUPT_PRIORITY)

use configMAX_SYSCALL_INTERRUPT_PRIORITY and not configKERNEL_INTERRUPT_PRIORITY as you mentioned. correct?

in this case, configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 191 (and the comment says it is equal to Cortex level = 5) while my timer worked with isr level < 10.

can you or someone here shed some light on this "priority" topic? i am totally confused…

Thanks a lot,
Bo

rtel wrote on Friday, November 21, 2008:

Did you see this page: http://www.freertos.org/a00110.html#kernel_priority ?

Be very careful enabling interrupts again after installing an interrupt handler IF that interrupt handler makes any API calls that could cause a context switch to be attempted.  Any attempt to context switch before the scheduler is started will be hazardous for your application.

Regards.

bodev wrote on Friday, November 21, 2008:

Hi Richard,
    yes i have read that page and my ISR is neither calling  any API nor causing any context switch.

However, as i mentioned, i think that could be a "problem" at least is the comment of the FreeRTOSConfig.h for the CortexM3.

In fact, FreeRTOS APIs call taskDISABLE_INTERRUPTS with configMAX_SYSCALL_INTERRUPT_PRIORITY = 191
(changing basepri register).
According to the comment, 191 is equal to priority 5 for STM32. I am not sure of this, because
my ISR work at priority_level < 11 and not priority_level < 5 as you comment suggests.

Am i missing something?

Regards & Thanks,
Bo

bodev wrote on Friday, November 21, 2008:

I have found some more info.
STM32 implements only the 4 MSB bits of the PRIMASK.
(i.e. see http://www.st.com/mcu/forums-cat-6944-23.html)

So the line

#define configMAX_SYSCALL_INTERRUPT_PRIORITY     191 /* equivalent to 0xa0, or priority 5. */

i think should be

#define configMAX_SYSCALL_INTERRUPT_PRIORITY     191 /* equivalent to 0x0A, or priority 11. */

I am not sure if the assumption (191 map to 5) caused other indesired bahaviors in FreeRTOS

Furthermore, NVIC controller can be set up with the 4 bits splitted in two groups: priority and subpriority.

I think FreeRTOS consider all 4 bits as priority and no bits for sub priority.

I am not sure what can happen if someone use different schemes.

Bo

rtel wrote on Friday, November 21, 2008:

Yes - the STM32 implements 4 bits of priority, these four bits being the top 4 bits of an 8 bit number.  So 0xff (255, 0xf0, or (0x0f<<4) are all equivalent as the bottom 4 bits are ignored) is the lowest priority and 0x0f (31, or 0, or (0<<4)) the highest priority.

191 is (0x0b<<4), which as you point out is effectively 11, not 5.

This is a cut and paste error from the Luminary Micro ports, where only 3 bits are implemented, so 5 is the correct value.

Sorry for any confusion caused and thanks for pointing it out.  I have corrected the comments in the SVN repository to ensure they get included in the next release.

Regards.

ntfreak wrote on Wednesday, April 15, 2009:

Hi Richard,

Just a small typo, should the comment actually be 0xbf rather than 0xb0:
#define configMAX_SYSCALL_INTERRUPT_PRIORITY     191 /* equivalent to 0xbf, or priority 11. */

Cheers
Spencer Oliver

rtel wrote on Wednesday, April 15, 2009:

Hi Spenser,

It could really be either I think, because the bottom 4 bits are not used by the STM32 the two are equivalent.  The bottom four bits are set to 0x0f in the macro for future compatibility (should the code be used on a part with more priority bits defined) but the priority is really 11 relative to the range of priorities available.

I agree this should be explained more clearly in the comment.  Really its priority (0x0b << 4).

Regards.

ntfreak wrote on Wednesday, April 15, 2009:

I just mentioned it as the comment did not match the code, in the case of the stm32 the lower 4 bits can be any value as this is ignored by the nvic anyway.

Cheers
Spen