AVR-Bootloader-Interrupt-Problem

Ich benutze seit geraumer Zeit einen avr ATmega324PA Controller und Atmel Studio, um die Programme zu schreiben. Wir haben einen TCP-Bootloader geschrieben. Es funktioniert gut ohne Unterbrechung. Später haben wir diesem Programm einen externen Interrupt hinzugefügt und jetzt startet der Controller immer neu, wenn er zum ISR springt. Hier ist der Code

void main()
{
  init_interrupt();
  init_uart();
  while(1);
}

void init_interrupt()
{
  /* PortA3 as input for external interrupt*/
 DDRB|=(0<<2);
  /*Pulll up disable*/
 PORTB &=~ (1<<PORTB2);
  /*Interrupt_vector change enable*/
 MCUCR|=(1<<IVCE);
  /*Interrupt vector change to boot section*/
 MCUCR|=(1<<IVSEL);
  /*Interrupt_vector change enable*/
 MCUCR&=~(1<<IVSEL);
 _delay_ms(5000);
  /* Enable external interrupt-2*/
 EIMSK |= (1<<INT2);
  /* Enable rising edge of the input signal as interrupt*/
 EICRA |= (1<<ISC21)|(1<<ISC20);
  /* Enable global interrupt*/
 sei();
}

ISR(INT2_vect)
{
    uart_send("Print on interrupt");
}

Hier versuche ich, den Interrupt-Vektor in den Boot-Bereich zu ändern.

HINWEIS: Die BOOTRST-Sicherung ist bereits gesetzt

BEARBEITET: Nachdem ich den MCUCR-Wert wie unten gezeigt geändert habe, habe ich ihn durch UART anstelle von '01' gesendet, die Ausgabe wird als "A0 2E 57 C9 D1 95 91 FF" angezeigt.

    MCUCR|=(1<<IVCE);

Muss ein Problem mit dem MCUCR-Register sein

Sind Sie sicher, dass Sie nicht zu einem Interrupt-Vektor springen, der in Ihrem Code nicht definiert ist, wodurch der Prozessor zurückgesetzt wird?
Wie Sie sehen, habe ich die Routine INT2_vect definiert und die externen Interrupt-Einstellungen in init_interrupt() aktiviert. Derselbe Interrupt ohne IVSEL-Einstellungen funktioniert gut mit Anwendungscode. Aber mit Bootcode wird es zurückgesetzt
Verwendet Ihr Bootloader Interrupts? Ich persönlich habe sie in Bootloadern vermieden, aber ich denke, es gibt ein paar Registerbits, die Sie benötigen, um die Interrupts in den Bootloader-Bereich zu verschieben. Vielleicht werden sie vom Bootloader im falschen Zustand belassen.

Antworten (1)

Damit die Interrupts im Bootloader funktionieren, sollten Sie das Interrupt Vector Change Enable(IVCE)-Bit wie unten setzen

   MCUCR|=(1<<IVCE); // or GICR|=(1<<IVCE) in some controllers

Und innerhalb von vier Zyklen müssen Sie das IVSEL-Bit setzen und das IVCE-Bit zurücksetzen.

   MCUCR=0x02; // or GICR=0x02;  IVSEL=1, IVCE=0 at same time

Was im obigen Code schief gelaufen ist, steht unten

     /*Interrupt_vector change enable*/
    MCUCR|=(1<<IVCE);
    /*Interrupt vector change to boot section*/
    MCUCR|=(1<<IVSEL);
    /*Interrupt_vector change enable*/
    MCUCR&=~(1<<IVSEL);

Die erstere Methode könnte meiner Meinung nach innerhalb von vier Zyklen abgeschlossen sein. Ich kann jetzt jedoch den TCP-Bootloader mit Interrupts verwenden, um den Anwendungscode zu laden.