Tengo otro problema ( temporizador del sistema de alta resolución en STM32 ) que he rastreado (principalmente) hasta este problema, y he creado un caso de prueba aquí para el procesador STM32 más simple que pude encontrar (en la placa STM32VLDISCOVERY).
El problema es que no puedo obtener una interrupción de mayor prioridad para interrumpir una de menor prioridad.
En el ejemplo, la interrupción SysTick parpadea lentamente el LED1, el bucle principal parpadea el LED2.
Gastos esperados
Cuando se presiona BTN1, se llama a la interrupción EXTI0, el LED2 parpadea rápidamente hasta que se dispara la interrupción SysTick de mayor prioridad y luego sale. El LED1 sigue parpadeando como antes.
resultado real
Cuando se presiona BTN1, se llama a la interrupción EXTI0, parpadea rápidamente el LED2. La interrupción SysTick de mayor prioridad nunca se dispara, el LED1 nunca parpadea y el LED2 continúa parpadeando rápidamente.
¿Algunas ideas? ¿Es la preferencia de interrupción algo que debe activarse de alguna manera?
#include "stm32f10x.h"
typedef char bool;
volatile bool toggle;
void delay(void) {
volatile int i = 100000;
while (i-- > 0) {
}
}
void delaySlow(void) {
volatile int i = 1000000;
while (i-- > 0) {
}
}
// Toggle LED1 on SysTick
void SysTick_Handler(void) {
if (toggle = !toggle)
GPIO_SetBits(GPIOC, GPIO_Pin_8);
else
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
}
// On EXTI IRQ, flash LED2 quickly, and wait for a SysTick
void EXTI0_IRQHandler(void) {
bool lastToggle = toggle;
GPIO_SetBits(GPIOC, GPIO_Pin_9);
while (lastToggle==toggle) { // wait for systick
// Flash LED2 quickly
GPIO_SetBits(GPIOC, GPIO_Pin_9);
delay();
GPIO_ResetBits(GPIOC, GPIO_Pin_9);
delay();
}
GPIO_ResetBits(GPIOC, GPIO_Pin_9);
EXTI_ClearITPendingBit(EXTI_Line0);
}
int main(void){
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE, ENABLE);
// set preemption
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_Init(GPIOE, &GPIO_InitStructure);
// button
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// leds
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// systick
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
SysTick_Config(0xFFFFFF); // 24 bit
NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Highest priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// exti 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; // Lowest priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_Init(&NVIC_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_InitTypeDef s;
EXTI_StructInit(&s);
s.EXTI_Line = EXTI_Line0;
s.EXTI_Mode = EXTI_Mode_Interrupt;
s.EXTI_Trigger = EXTI_Trigger_Rising;
s.EXTI_LineCmd = ENABLE;
EXTI_Init(&s);
while (1)
{
// Flash LED2 slowly
GPIO_SetBits(GPIOC, GPIO_Pin_9);
delaySlow();
GPIO_ResetBits(GPIOC, GPIO_Pin_9);
delaySlow();
}
}
Acabo de encontrar la respuesta en un póster muy útil en el foro STM32
Lo siguiente no es correcto. SysTick es un 'Controlador del sistema' y, como tal, la prioridad no se establece de esta manera en absoluto:
NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Highest priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
En realidad está configurado con:
NVIC_SetPriority(SysTick_IRQn, 0);
¡Llamar a ese código resuelve el problema!
estrella azul
gordon williams