Ich habe ein weiteres Problem ( Hochauflösender Systemtimer in STM32 ), das ich (meistens) zu diesem Problem zurückverfolgt habe, und habe hier einen Testfall für den einfachsten STM32-Prozessor erstellt, den ich finden konnte (auf dem STM32VLDISCOVERY-Board).
Das Problem ist, dass ich einen Interrupt mit höherer Priorität nicht dazu bringen kann, einen Interrupt mit niedrigerer Priorität zu unterbrechen.
Im Beispiel wird LED1 langsam durch den SysTick-Interrupt geblinkt, LED2 wird durch die Hauptschleife geblinkt.
Erwartetes Ergebnis
Wenn BTN1 gedrückt wird, wird der EXTI0-Interrupt aufgerufen, LED2 blinkt schnell, bis der SysTick-Interrupt mit höherer Priorität ausgelöst wird, und wird dann beendet. LED1 blinkt weiter wie zuvor.
Tatsächliches Ergebnis
Wenn BTN1 gedrückt wird, wird der EXTI0-Interrupt aufgerufen, LED2 blinkt schnell. Der SysTick-Interrupt mit höherer Priorität wird nie ausgelöst, LED1 blinkt nie und die LED2 blinkt weiterhin schnell.
Irgendwelche Ideen? Ist Interrupt Preemption etwas, das irgendwie eingeschaltet werden muss?
#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();
}
}
Ich habe gerade die Antwort von einem sehr hilfreichen Poster im STM32-Forum gefunden
Folgendes ist nicht korrekt. SysTick ist ein 'System Handler', und als solcher wird die Priorität überhaupt nicht auf diese Weise festgelegt:
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);
Es ist eigentlich eingestellt mit:
NVIC_SetPriority(SysTick_IRQn, 0);
Das Aufrufen dieses Codes löst das Problem stattdessen!
sternenblau
Gordon Williams