Electronic – STM32F103, Having trouble nesting interrupts

armcortex-m3interruptsstm32stm32f10x

I'm trying to interrupt into a USART handler from inside an RTC_Alarm handler, but it doesn't work.

I have set the NVIC:

void NVIC_Configuration() {
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_SetPriorityGrouping(NVIC_PriorityGroup_4);

/* Configure UART IRQ */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Configure RTC Alarm IRQ */
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

I have also noticed that my SysTick handler also isn't running while executing code inside the RTC_Alarm handlers.

How do I get the interrupt to nest ?

Here is some of the rest of the code:

So I have this loop waiting for an interrupt from a UART to set the CurrentMode, but the interrupt never occurs. The same interrupt works in the rest of the code.

void RTCAlarm_IRQHandler() {
    /* Reset the Alarm in 24 Hours */
    RTC_Set_Alarm(FALSE, (Get_Alarm_Time() + 3600*24));
    RTC_ClearITPendingBit(RTC_IT_ALR);
    EXTI_ClearITPendingBit(EXTI_Line17);
    RTC_WaitForLastTask();

    Op_Mode_Type SwapTemp = CurrentMode;
    CurrentMode = ModeOnAlarm;
    Alarm_Mode(SwapTemp);
}

void Alarm_Mode(Op_Mode_Type Initial_Mode) {
    /* Enable USART Interrupt */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    NVIC_EnableIRQ(USART1_IRQn);
    switch (ModeOnAlarm)
    {
        case Op_Mode_Single_Color:
            Set_Color(&Alarm_Color);
            while(CurrentMode == Op_Mode_Single_Color); //TODO - Add Timeout + UART Isn't interrupting here
            break;
//Some more cases here....
    }
    CurrentMode = Initial_Mode;
}

void USART1_IRQHandler() {
    uint8_t data;
    if (USART_GetITStatus(USART1,USART_IT_RXNE)) {
        data = USART_ReceiveData(USART1);
        CurrentMode = (Op_Mode_Type)(data);
        USART_ClearITPendingBit(USART1, USART_IT_RXNE); // Clear interrupt flag
        /* Disable USART Interrupt */
        USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
        NVIC_DisableIRQ(USART1_IRQn);
    }
}

Functionally I don't really need to use the interrupt in this code, but I want to understand why doesn't it work.

Best Answer

Since you have not assigned NVIC priority group, it is left with a default value of 2. This means that you have 2 bits for preemption priority and 2 bits for sub-priority. That allows you to use priority levels from 0 to 3 (2^n). Allowed priority levels for each group are illustrated in the following table:

enter image description here

As you can see, Group 4 has to be used in order to set preemption priority levels 0-15.

You may leave the group unassigned for UART interrupt (since it will be assigned to group 2 by default).

For more information and examples you can refer to this article.