This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Concerto M35 Cortex M3 core, setting interrupt priority bug?

In the Cortex M3 core, I am trying to have 2 interrupts with different priority.

I want the higher priority interrupt interrupting the lower priority interrupt.

One, the higher priority, supposes to increment counter, "volatile Uint32 mSecCounter", and I put it into SysTick interrupt which has priority 0 by default.

// The 1 millisecond tick timer, SysTick has priority 0
void SysTickIntHandler( void ) //when servicing lower priority interrupt, program does not stop there and not incrementing counter
{
    mSecCounter++;// This simply increments and wraps, when it's used, the user zeroes the count beforehand
}

The second interrupt is Timer0 interrupt, it is a service interrupt, it can call a function which checks increment of mSecCounter and waits until it reaches certain value, like:

//inside one of the functions called from the lower priority interrupt:

mSecCounter=0;//reset counter

do {

//wait and do something, <<<<< program stack there, because counter is not incrementing in another interrupt

} while (mSecCounter<100);//until 100 ms passed

 I tried to assign to it priority 2, so this timer interrupt and the function which checks counter, supposed to be interrupted by priority 0 interrupt (which increments counter).

I believe the following functions have a bug:

    int i = IntPriorityGet(INT_TIMER0A); // default priority of TIMER0A = 0, register NVIC_PRI8
    IntPrioritySet(INT_TIMER0A, (char)(i+1)<<5); //priority TIMER0A set to 1 (upper 3 bits of a byte)
    i = IntPriorityGet(INT_TIMER0A); // read back priority of INT_TIMER0A = 32 (or 1 in upper 3 bits)

//IntPrioritySet(INT_TIMER0A, changes NVIC_PRI4 to 0x20000000 (WRONG NVIC_PRI4, IRQ16 to 19, should be NVIC_PRI8, IRQ32 to 35)
I checked with emulator, and the call IntPrioritySet(INT_TIMER0A, (char)(i+1)<<5); changes register NVIC_PRI3 to 0x20000000 , not register NVIC_PRI8 according to TRM.

Besides, even if I pause execution and manually change NVIC_PRI8 register to 0x20000000, I still see the program is stack inside the second interrupt with supposed to be lower priority (=1), in the function which was called from it, waiting for counter to increment. The higher priority(=0) SysTick interrupt is not called, counter is not incrementing.

If this waiting for counter function is NOT called from the second interrupt, the first interrupt IS working and incrementing counter.

Either there is a bug in IntPrioritySet(), or I do something incorrectly, or both.

Should the interrupts be re-enabled inside lower priority interrupt?

Any more detailed examples on interrupt priorities?

Thanks, Igor

  • Hi,

    //IntPrioritySet(INT_TIMER0A, changes NVIC_PRI4 to 0x20000000 (WRONG NVIC_PRI4, IRQ16 to 19, should be NVIC_PRI8, IRQ32 to 35)
    I checked with emulator, and the call IntPrioritySet(INT_TIMER0A, (char)(i+1)<<5); changes register NVIC_PRI3 to 0x20000000 , not register NVIC_PRI8 according to TRM.

    The comment says that NVIC_PRI4 need to be set (which is correct) . NVIC PRI registers sets the priority for external interrupts and not for system interrupts. For System interrupts there are SYS_PRIx registers. External interrupt number for TIME0A 19 hence it's part of NVIC_PRI4 register.

    But you mention that function IntPrioritySet is setting NVIC_PRI3 with value 0x2000_0000. Could you confirm the same again? If yes, then please try setting NVIC_PRI4 with value 0x2000_0000 (not NVIC_PRI8) and see if that works.

    Regards,

    Vivek Singh 

  • Hi, Vivek,

    I finally had time to debug this puzzle.

    You were right (as well as TRM) - I made a typo: NVIC_PRI3 should be NVIC_PRI4

    I set priorities of timer interrupts, and they correctly interrupt each other. Below is example of test code

    volatile char TimerIntPriorty[5];
    #define GetInterruptPriority_0to8(INTR) (IntPriorityGet(INTR)>>5)
    void GetTimersIntrruptsPriorities(void) //writes priorities (starting from zero, not from 64) into array TimerIntPriorty[5]
    {
        int ch;
        for (ch = 0; ch<3; ch++)
        {
            TimerIntPriorty[ch] = GetInterruptPriority_0to8(INT_TIMER0A+(ch<<1)); // read priority of INT_TIMER0A, 1A,2A = interrupt 35,37,39
        }
        TimerIntPriorty[3] = GetInterruptPriority_0to8(INT_TIMER3A);    // read priority of INT_TIMER3A
        TimerIntPriorty[4] = GetInterruptPriority_0to8(FAULT_SYSTICK); //priority of SysTick = 64 (or 2 in upper 3 bits)
    }

    ........
    //EXAMPLE OF SETTING AND VERIFYING PRIORITIES

    // Configure the 32-bit periodic timers:
    // TIMER CONFIGURATION
        TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
        TimerConfigure(TIMER1_BASE, TIMER_CFG_32_BIT_PER);
        TimerConfigure(TIMER2_BASE, TIMER_CFG_32_BIT_PER);
        TimerConfigure(TIMER3_BASE, TIMER_CFG_32_BIT_PER);
    //TIMER LOAD
        TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet(M3_MILLI_SECOND_IN_INTERRUPTS));      // 1 ms period  increments mSecCounter,  priority 2
        TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet(SYSTEM_CLOCK_SPEED) / 72000);         // 8 KHz SPI interrupt,  priority 1
        TimerLoadSet(TIMER2_BASE, TIMER_A, SysCtlClockGet(M3_MICRO_SECOND_IN_INTERRUPTS*10));   // 10 us each interrupt (set to = 200)   priority 1 (or 0 if needed)
        TimerLoadSet(TIMER3_BASE, TIMER_A, SysCtlClockGet(M3_MILLI_SECOND_IN_INTERRUPTS*5));      // 5 ms period   ISR_Ethernet();   priority 4

    // TIMER INTERRUPT PRIORITY: the shorter time interval should have higher priority
        IntPrioritySet(INT_TIMER0A,  (char)(+2)<<5); //priority TIMER0A set to 2 (middle)
        IntPrioritySet(INT_TIMER1A,  (char)(+1)<<5); //priority TIMER1A set to 1 (highest)
        IntPrioritySet(INT_TIMER2A,  (char)(+1)<<5); //priority TIMER2A set to 1 (highest)
        IntPrioritySet(FAULT_SYSTICK,(char)(+3)<<5); //priority SysTick set to 3 (lowest)
        IntPrioritySet(INT_TIMER3A,  (char)(+4)<<5); //priority TIMER3A set to 4. NOTE: SysTick will block it because it has higher priority

    // Setup the interrupts for the timer timeouts.
        IntEnable(INT_TIMER0A);
        IntEnable(INT_TIMER1A);
        IntEnable(INT_TIMER2A);
        IntEnable(INT_TIMER3A);
        TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
        TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
        TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
        TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
        IntRegister(INT_TIMER0A, Timer0IntHandler);
        IntRegister(INT_TIMER1A, Timer1IntHandler);
        IntRegister(INT_TIMER2A, Timer2IntHandler);
        IntRegister(INT_TIMER3A, Timer3IntHandler);

        GetTimersIntrruptsPriorities(); //SysTimer and timers have priorities set and verified


        TimerEnable(TIMER2_BASE, TIMER_A); //Enable Timer ONLY AFTER SOMETHING USED IN INTERRUPT IS CONFIGURED

    ......

  • Hi Igor,Thanks for posting the resolution to your issue.