Tengo dos fuentes de interrupción externas que entran en un STM32F105. Quiero que uno de ellos (llámelo "IRQHigh") para adelantarse al otro ("IRQLow"). Actualmente, si IRQHigh se activa durante el IRQLow ISR, el flujo del programa espera hasta que borre el bit IRQLow ITPending antes de que se ramifique en el IRQHigh ISR.
El STM32F105 es un microcontrolador basado en Cortex-M3. Soporta interrupciones anidadas. Mi solicitud está escrita en C, usando GCC (arm-none-eabi-gcc) en Eclipse, con la biblioteca de periféricos estándar STM32F1.
Creo que tengo las prioridades configuradas correctamente, pero me falta algo.
Aquí está el código de inicialización correspondiente. He eliminado los comandos de reloj de AFB, la configuración de GPIO, etc., ya que cada subsistema parece funcionar bien por sí mismo:
#define IRQHIGH_EXTI_PORT GPIO_PortSourceGPIOA
#define IRQHIGH_EXTI_PIN GPIO_PinSource3
#define IRQHIGH_EXTI_LINE EXTI_Line3
#define IRQHIGH_EXTI_IRQn EXTI3_IRQn
#define IRQLOW_EXTI_PORT GPIO_PortSourceGPIOC
#define IRQLOW_EXTI_PIN GPIO_PinSource11
#define IRQLOW_EXTI_LINE EXTI_Line11
#define IRQLOW_EXTI_IRQn EXTI15_10_IRQn
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
// Sixteen levels of pre-emption priority, no subpriorities
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
// IRQHigh
// Connect EXTI Line to GPIO Pin
GPIO_EXTILineConfig(IRQHIGH_EXTI_PORT, IRQHIGH_EXTI_PIN);
// Configure EXTI line
EXTI_InitStructure.EXTI_Line = IRQHIGH_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Configure and enable EXTI Interrupt
NVIC_InitStructure.NVIC_IRQChannel = IRQHIGH_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// IRQLow
// Connect EXTI Line to GPIO Pin
GPIO_EXTILineConfig(IRQLOW_EXTI_PORT, IRQLOW_EXTI_PIN);
// Configure EXTI line
EXTI_InitStructure.EXTI_Line = IRQLOW_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// Configure, but do not enable, EXTI Interrupt
NVIC_InitStructure.NVIC_IRQChannel = IRQLOW_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
NVIC_Init(&NVIC_InitStructure);
Los controladores de IRQ se configuran como tal:
void EXTI3_IRQHandler(void)
{
IRQHigh();
EXTI_ClearITPendingBit(IRQHIGH_EXTI_LINE);
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(IRQLOW_EXTI_LINE) == SET)
{
if (IRQLow()) // This returns a non-zero value if an overflow happened
{
CleanUpOverflow();
}
// Clear interrupt bit.
EXTI_ClearITPendingBit(IRQLOW_EXTI_LINE);
}
else // unknown EXTI source
{
ErrorHandler(ERR_UNKNOWN_EXTI15_10_IRQ); // This never happens
}
}
Algunas cosas importantes:
-
IRQHigh () e IRQLow () toman un tiempo significativo para completar (por eso quiero que uno interrumpa al otro)
-
IRQLow no está habilitado inicialmente, pero está habilitado en la línea con
NVIC_EnableIRQ(IRQLOW_EXTI_IRQn);
-
Dentro de EXTI15_10_IRQHandler (), obtengo un valor de retorno de IRQLow ().
-
He declarado las funciones xxx_IRQHandler () con y sin
__attribute__ ((interrupt ("IRQ")))
. Entiendo que este atributo no es necesario con Cortex-M3, pero lo intenté de todos modos (y obtuve los mismos resultados).
¿Qué estoy haciendo mal?
Actualización: con la ayuda de un comentario de @ Jeroen3, descubrí que IRQLow está interrumpiendo IRQHigh. Ahora necesito averiguar por qué ...