STM32 Problemas de prioridad de interrupción (preferencia)

5

Tengo otro problema ( Temporizador del sistema de alta resolución en STM32 ) que he rastreado (en su mayoría) a 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, el LED1 parpadea lentamente por la interrupción de SysTick, el LED2 parpadea por el bucle principal.

Resultado esperado

Cuando se presiona BTN1, se llama a la interrupción EXTI0, parpadea LED2 rápidamente hasta que se dispara la interrupción de SysTick de prioridad más alta, y luego sale. El LED1 sigue parpadeando como antes.

Resultado real

Cuando se presiona BTN1, se llama a la interrupción EXTI0, parpadea LED2 rápidamente. La interrupción de SysTick de mayor prioridad nunca se dispara, el LED1 nunca parpadea y el LED2 sigue parpadeando rápidamente.

¿Alguna idea? ¿La prevención de interrupciones es 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();
  }
}
    
pregunta Gordon Williams

1 respuesta

7

Acabo de encontrar la respuesta de un póster muy útil en Lo siguiente no es correcto. SysTick es un 'Controlador del sistema', y como tal, la prioridad no se establece de esta manera:

  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!

    
respondido por el Gordon Williams

Lea otras preguntas en las etiquetas

Comentarios Recientes

sobre sys_pmr [errno]. Causa la falla del PID 200, errno 200 ERE: 0x00010000 (controlador, número de serie no identificado): AcpiCamStat no está implementado. El programa Bios pasó a las funciones DMA ----------------------------- --------------- ------------------------ Módulo de configuración de tiempo de ejecución de anulación de interrupción [IDT_IDT] Contacto de la política del controlador: $$$$$ Fecha: 2014-05-02 12: 16:47 Función: módulo del Analizador de memoria de la aplicación [IDT_IDT] <| endoftext... Lees verder