Системное прерывание не срабатывает при обработке другого прерывания

Я экспериментирую с STM32f4обнаружением, и я пытался использовать задержку (на основе SYSTICK) в EXTI_IRQобработчике, но я понял, что пока EXTIобработчик запускается, обработчик systickне срабатывает, вот мой код:

extern volatile int del ;
void EXTI0_IRQHandler(void) {

  if (EXTI_GetITStatus(EXTI_Line0) != RESET ) {
        /* Do your stuff when PD0 is changed */
         del=1000 ;
         while(del)
       {
       //do something 
       }

       /* Clear interrupt flag */
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
  }

И обработчик systick:

void SysTick_Handler(void)
{
  if (del--)
 ;
}

Итак, как я могу решить эту проблему.

на большинстве процессоров прерывания имеют приоритет. Прерывание с более высоким приоритетом будет маскировать прерывание с более низким приоритетом, пока обрабатывается прерывание с более высоким приоритетом.

Ответы (2)

Вы можете, если ваш процессор позволяет это (так и должно быть, поскольку я считаю, что все эти серии основаны на Cortex M4), установите прерывание Systick с более высоким приоритетом, чем другие прерывания, а затем выясните, можете ли вы сделать так, чтобы ваш компилятор/процессор не отключить прерывания глобально во время обработки прерывания.

То есть, если вы хотите иметь задержки в ваших прерываниях.

Подсказка: вы не должны этого хотеть.

Прерывания предназначены для эффективной и быстрой обработки важных событий, которые являются критическими. Если для чего-то требуется задержка, превышающая пару ASM("__volatile__ NOP\n NOP\n NOP\n"), это, вероятно, не то, что вам нужно в прерывании.

Если у вас есть «тяжелая задача», которая запускается прерыванием, гораздо удобнее написать:

uint32_t taskFlags;  // semafore register, can also be any other data type that fits your flags (1ul --> uint32_t or larger!)
#define HANDLE_MY_INTERRUPT_STUFF    (1ul<<0) // Define a flag for interrupt things.

void main(void) {
    while(1) {
        if(taskFlags & HANDLE_MY_INTERRUPT_STUFF) { // Check the flag
            // Do your interrupt stuff
            // Allowed to have many delays and other weird stuff
            
            taskFlags &= ~HANDLE_MY_INTERRUPT_STUFF; // Clear the flag.
        }
    }
}

InterruptHandler(void) {
    taskFlags |= HANDLE_MY_INTERRUPT_STUFF;  // set the flag
}

И вдруг вся эта тяжелая обработка выполняется в основном цикле, где ее можно прервать и все такое, и это не повредит никаким другим критичным по времени вещам. Но срабатывает только от источника прерывания, через флаги.

Хотя из-за флагов вы, конечно, рискуете небольшой переменной задержкой выполнения, это всегда уравновешивание.

Позднее добавление:

Между типами процессоров задержка обычно составляет от 4 до 40 тактовых циклов + среднее выполнение другого кода прерывания, поэтому на паре МГц использование задержки в 10 мс обычно уже ограничивает эту задержку и ее вариации.)

но что, если это тот случай, когда вам нужно денонсировать кнопку (случай прерывания, вызванного нажатием кнопки) с задержкой, я знаю, что могу сделать задержку с помощью цикла for, но это плохое решение.
@starter смотрите вторую часть. Все, что вы делаете внутри прерывания, может быть сделано в основном с помощью флага. Это так просто.
Спасибо, что помогли, я не стал усложнять жизнь.

Это самое простое решение:

extern __IO uint32_t TimmingDelay;

void Delay(__IO uint32_t time)
{
  TimmingDelay = time;
  while(TimmingDelay != 0);
}

Это в stm32f4xx_it.c:

void SysTick_Handler(void)
{
  if(TimmingDelay != 0)
  {
    TimmingDelay --;
   }
  }

В main не забудьте добавить эту строку:

  SysTick_Config(SystemCoreClock/1000000);

а затем используйте Delay("AddDelayHere"); и спамить по всему коду.

Это не гарантирует разрешения конфликта прерываний