Problem bei NVIC STM32F100

Ich verwende das STM32VL Discovery Board (STM32f100rb6). Ich habe folgenden Code für NVIC geschrieben:

void Interrupt_Init(void)
{
    __enable_irq();
    /*Core Base(NVIC)*/

    //set priority to 0
    //NVIC->IP[6] &= ~((uint32_t)0xff00);

    //Activate Interrupts
    NVIC->ISER[0] |= BIT6;

    //Enable Pending BIT for Interrupt 6
    NVIC->ISPR[0] |= BIT6;
    lcd_writechar('1');
} 

Und

int main(void)
{
Interrupt_Init();
    while (1)
    {

    }
}
void EXTI0_IRQHandler(void)
{
    //NVIC->ICPR[0] |= BIT6;

    lcd_writechar('2');
}

wie Sie unter Interrupt_Init()I user NVIC->ISPR[0] |= BIT6;phrase sehen, um exti0-IRQ weich zu aktivieren. Also void EXTI0_IRQHandler(void)muss das Unterprogramm ausgeführt werden und ich habe '2' auf dem LCD. aber als NVIC->ISPR[0] |= BIT6;execute next line( ) läuft es lcd_writechar('1');nie.NVIC->ISPR[0] |= BIT6;

Aktualisieren:

Ich schaue weiter in die Datei "startup_stm32f10x_md_vl.s" in meinem Projekt als Startdatei:

.section  .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b  Infinite_Loop
  .size  Default_Handler, .-Default_Handler

Und:

g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler
  .word  WWDG_IRQHandler
  .word  PVD_IRQHandler
  .word  TAMPER_IRQHandler
  .word  RTC_IRQHandler
  .word  FLASH_IRQHandler
  .word  RCC_IRQHandler
  .word  EXTI0_IRQHandler
...

Und:

.weak  EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler

Es scheint, dass "EXTI0_IRQHandler" in meinen Projekten immer gleich "Default_Handler" ist, so dass es eine Endlosschleife verursacht, wie wir oben definiert haben.

Ich denke dieser Teil:

void EXTI0_IRQHandler(void)
{
  NVIC->ICPR[0] |= BIT6;

  lcd_writechar('2');
}

nie die "EXTI0_IRQHandler"-Definition beeinflusst. Warum?

Aktualisieren:

Gibt es eine Möglichkeit, zu EXTI0_IRQHandler zu springen, ohne etwas in der Peripherie zu implementieren? Wie asm ("B 0x58")? Mein Ziel ist es, sicher zu sein, von Kernkonfigurationen dann an peripheren Konfigurationen zu arbeiten?

Aktualisieren:

Ich habe das Problem fast gefunden, brauche aber Hilfe, um es zu beheben. Nach vielen Untersuchungen und der Verwendung von Debug-Funktionen habe ich festgestellt, dass dieser Codeabschnitt fehlerhaft ist:

    void EXTI0_IRQHandler()
    {
      lcd_writechar('2');
      LED_ON();
      NVIC->ICPR[0] |= BIT6;
    }

im Detail lcd_writechar('2');Grund zum Problem, weil ich innerhalb der Funktion die Funktion delay () verwende. Dies ist das Stück Code, das die Verzögerung durch die SycTick-Funktion beinhaltet:

/*Enable SysTick*/
  //Processor clock (AHB)
  SysTick->CTRL |= BIT2;
  //Counting down to zero to asserts the SysTick exception request.
  SysTick->CTRL |= BIT1;
  SysTick->LOAD = 8000 - 1;
void SysTick_Handler(void)
{
  SysTick_Tick++;
  //lcd_writechar('7');
  SCB->ICSR |= BIT25;
}
void delay(int ms)
{
  SysTick_Tick = 0;
  //Enable Systick Counter
  SysTick->CTRL |= BIT0;
  while (SysTick_Tick < ms) {}
  //Disable Systick Counter
  SysTick->CTRL &= ~BIT0;
  SCB->ICSR |= BIT25;
  return;
}

Wie Sie sehen, versuche ich, das ausstehende Bit von SysTick zu löschen, SCB->ICSR |= BIT25;aber nach dem Ausführen der Funktion delay () von innen EXTI0_IRQHandler()hängt eindeutig alles.

Antworten (3)

Wenn Sie in die Interrupt-Routine eintreten, müssen Sie das Interrupt-Quell-Flag löschen. Wenn Sie das Flag nicht löschen, wird es beim Verlassen der Interrupt-Routine einfach wieder in die Routine eintreten. Auf diese Weise bleiben Sie immer im EXTI0_IRQHandler hängen.

danke für deine antwort aber wie?? können Sie dieses Projekt anhand von Beispielen näher erläutern?
Ich benutze void EXTI0_IRQHandler(void) { NVIC->ICPR[0] |= BIT6; lcd_writechar('2'); }zum Löschen des Interrupt-Quell-Flags, lcd_writechar('2')läuft aber nie und alles ist gleich.
Ich denke, es wird immer in SysTick_Handler() hängen bleiben, bitte lesen Sie das letzte Update.

Das NVIC->ICPRentfernt nur das Pending-Bit im NVIC.
Wenn jedoch das IRQ-Signal zum NVIC noch aktiv ist (das EXTI PR-Register), hat das anstehende Bit-Löschen im NVIC keine Wirkung.

Stattdessen müssen Sie die Interrupt-Anforderungsquelle EXTI->PR = EXTI_PR_PR6in der ISR löschen. Andernfalls verketten Sie diese Interrupt-Routine, bis eine mit höherer Priorität eintrifft.

Die Definitionen, die Sie in startup.s finden, sind schwach , Sie überschreiben diese, wenn Sie die eigentliche Funktion schreiben.

Mit NVIC->ISPR[0] |= BIT6generieren Sie eine Software-Interrupt-Anforderung. Es wird beim Betreten des ISR gelöscht.

Allgemeiner Tipp, beim Debuggen fehlender Interrupt-Routinen hier einen Haltepunkt setzen:

.section  .text.Default_Handler,"ax",%progbits
Default_Handler:
 Infinite_Loop:
  b  Infinite_Loop  <-------- breakpoint
  .size  Default_Handler, .-Default_Handler
@peymankhalili Es gibt zwei Möglichkeiten, das ISR per Software auszuführen. Rufen Sie die Funktion auf. Oder setzen Sie das Pending-Bit.
Ja, ich habe es getan (Setting Pending Bit) by NVIC->ISPR[0] |= BIT6, also void EXTI0_IRQHandler(void)sollte die Funktion laufen ... aber es passiert nicht ... weil wir keine '1' auf dem LCD bekommen haben, wie lcd_writechar('1');es zugegeben wird.
@peymankhalili Lösen Sie durch eine Änderung den RCC_IRQHandler aus?
Nein, ich möchte EXTI0_IRQHandler auslösen. Ich denke, Sie möchten asm ("B 0x58") erwähnen, es ist die Adresse von EXTI0_IRQHandler.
@peymankhalili Das NVIC wird durch die Ausnahmen von der Vektortabelle versetzt. Vielleicht ist bit6 nicht der IRQ, für den Sie ihn halten. Außerdem können Sie nicht ohne Link verzweigen und eine Rückkehr erwarten. Suchen Sie nach dem Procedure Call Standard.
von core_cm3.h haben wir static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) { NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ }und von stm32f10x.h haben wir typedef enum IRQn{...EXTI0_IRQn = 6, ...}, wenn Sie diese Berechnung durchführen, kommen wir zum NVIC->ISER[0] |= BIT6;Aktivieren EXTI0_IRQnvon Interrupt, also für ausstehend gemäß diesen Dateien erhalten wir NVIC->ISPR[0] |= BIT6;. Ich weiß also genau, dass ich das ausstehende Bit von "EXTI0_IRQn" aktivieren muss, also müssen wir "void EXTI0_IRQHandler (void)" zum Laufen bringen, wo ist das Problem??
@peymankhalili Wenn ich deine gegebenen Snippets teste. Es funktioniert gut. Bei dir muss noch was los sein.

Endlich habe ich den Fehler gefunden. Priorität ist das Problem.

Wird verwendet NVIC_SetPriority(EXTI0_IRQn, 1);, um SysTick auf eine höhere Prioritätsstufe als EXTI0_IRQn einzustellen. Dann geht alles OK.