STM32F103, Problemas para anidar interrupciones

Estoy tratando de interrumpir un controlador USART desde dentro de un controlador RTC_Alarm, pero no funciona.

He configurado el 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);
}

También me di cuenta de que mi controlador SysTick tampoco se ejecuta mientras ejecuta el código dentro de los controladores RTC_Alarm.

¿Cómo obtengo la interrupción para anidar?

Aquí está parte del resto del código:

Así que tengo este ciclo esperando una interrupción de un UART para establecer el modo actual, pero la interrupción nunca ocurre. La misma interrupción funciona en el resto del código.

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);
    }
}

Funcionalmente, realmente no necesito usar la interrupción en este código, pero quiero entender por qué no funciona.

¿Cuál es la configuración de la "prioridad de grupo"? ¿Por qué 15 para la prioridad de RTC? sería mejor si agregara más descripciones. No se que quieres hacer!? Tu primera oración no me queda clara.
Editaré la pregunta para explicar mejor el problema. No he configurado la prioridad de grupo, he leído en alguna parte que el esquema predeterminado tiene un byte para la prioridad de preferencia y un byte para la subprioridad. Me equivoco ?
¿Tienes algún depurador? si es así, ¿Qué ves en los registros? ¿Puedes agregar todos los códigos? ¿Cuál es tu IDE?
Estoy usando CooCox IDE y tengo un depurador. ¿Qué registros son de interés? USART_SR: solo tiene los bits TC y TXE configurados = 0xc00c0 USART_CR1: los bits RXNEIE, TE, RE y UE están configurados = 0x202c USART_CR2 y CR3 son = 0x0000 No creo que publicar todo el código sea útil, veré qué hay relevante y ver si puedo editar la pregunta.
¿Configuró el grupo de prioridad NVIC?
¿Sucede esto durante el funcionamiento normal o durante la sesión de depuración?
No configuré los grupos prioritarios de NVIC, ¿podría ser ese el problema?
Actualmente no hay diferencia entre el modo de depuración y el modo de ejecución normal, ya no puedo colocar el código dentro del flash sin optimización.
He configurado el Grupo Prioritario y sigue sin funcionar. He editado la pregunta con un poco más de código.
¿Revisaste la línea RX/TX? Tal vez el micro en realidad no recibe ningún dato.
Revisé los registros de USART, puedo ver que se recibió un byte, etc. Mire uno de mis comentarios: he indicado qué bits están configurados en los registros de USART.

Respuestas (2)

Dado que no ha asignado un grupo de prioridad NVIC, se deja con un valor predeterminado de 2. Esto significa que tiene 2 bits para la prioridad de preferencia y 2 bits para la subprioridad. Eso le permite usar niveles de prioridad de 0 a 3 (2^n). Los niveles de prioridad permitidos para cada grupo se ilustran en la siguiente tabla:

ingrese la descripción de la imagen aquí

Como puede ver, se debe usar el Grupo 4 para establecer los niveles de prioridad de prioridad 0-15 .

Puede dejar el grupo sin asignar para la interrupción de UART (ya que se asignará al grupo 2 de forma predeterminada).

Para obtener más información y ejemplos, puede consultar este artículo.

He establecido el grupo de prioridad en el grupo 4, pero parece que todavía no puedo anidarlos. Edité la pregunta y agregué algo de código.

Ok, aparentemente la biblioteca de periféricos estándar STM32 está totalmente rota. Usé NVIC_SetPriority para establecer la prioridad y finalmente funcionó.

Aquí está el código NVIC:

void NVIC_Configuration() {
    
    NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(4,0,0));
    NVIC_EnableIRQ(SysTick_IRQn);

    NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(4,1,0));
    NVIC_EnableIRQ(USART1_IRQn);

    NVIC_SetPriority(RTCAlarm_IRQn, NVIC_EncodePriority(4,15,0));
    NVIC_EnableIRQ(RTCAlarm_IRQn);    
}
En realidad, según este artículo es la forma correcta de asignar prioridad a algunas interrupciones. No tuve tiempo de echar un vistazo al manual de referencia para confirmarlo.
En cuanto a la biblioteca ST, siempre sugiero que las personas usen libopencm3 en su lugar :)
O use ChibiOS/RT : tiene una capa de abstracción de hardware (HAL) fantástica y limpia, y le permite codificar de manera portátil a otras MCU.
Tal vez use uno de esos en mi próximo proyecto, aunque gracias.
También creo que el problema aquí podría haber sido el hecho de que la biblioteca establece la interrupción de SysTick en la prioridad más baja (15) en SystemInit (), directamente opuesto a lo que desea (prioridad más alta) y también en conflicto con su RTCAlarm que tiene el mismo prioridad.