AnsweredAssumed Answered

STM32 Interrupt priorities and preemption

Question asked by Gordon Williams on Jul 18, 2013
Latest reply on May 11, 2015 by schperplata

Hi,

I have a problem where I cannot get a higher priority interrupt to interrupt a lower priority one. My understanding is that this should 'just work' so I'd really appreciate your input on this...

I've created a basic example which is designed to run on the STM32VLDISCOVERY board, but I've had the same issue with the F4 (and I imagine I would on other chips too)

In the example, LED1 is flashed slowly by the SysTick interrupt, and LED2 is flashed by the main loop.

Expected outcome

When BTN1 is pressed, the EXTI0 interrupt is called, it flashes LED2 quickly until the higher priority SysTick interrupt is fired, and then it exits. The LED1 keeps on flashing as before.

Actual outcome

When BTN1 is pressed, the EXTI0 interrupt is called, it flashes LED2 quickly. The higher priority SysTick interrupt is never fired, LED1 never flashes and the LED2 continues to blink quickly.

 

#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 slowly
        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();
  }
}

Outcomes