Jaecko
25.11.2009, 11:56
Moin.
Ich versuche gerade, einen Bootloader mit einem Timer-Interrupt auszustatten, um die Möglichkeit eines Timeouts zu haben (falls die Kommunikation abreisst etc.)
Das Problem ist aber jetzt: Statt des Interrupts löst der Mega8 einen Reset aus.
Das erste was ja getan werden muss, ist ja die ISR-Tabelle in den Bootbereich zu legen. Das hab ich erst mit C versucht:
GICR |= (1 << IVCE); // Move interrupt table to boot section
GICR |= (1 << IVSEL);
aber auch mal direkt mit ASM, um wirklich die beiden Bits so eng wie möglich nacheinander zu setzen (muss ja innerhalb von 4 Zyklen passiert sein):
asm volatile (
"PUSH R24" "\n\t" // Save R24
"PUSH R25" "\n\t" // Save R25
"IN R24,0x3B" "\n\t" // GICR => R24
"IN R25,0x3B" "\n\t" // GICR => R25
"ORI R24, 0x01" "\n\t" // "GICR |= (1 << IVCE)"
"ORI R25, 0x03" "\n\t" // "GICR |= (1 << IVCE) | (1 << IVSEL)"
"OUT 0x3B, R24" "\n\t" // R24 => GICR
"OUT 0x3B, R25" "\n\t" // R25 => GICR
"PUSH R25" "\n\t" // Restore R25
"PUSH R24" "\n\t" // Restore R24
::);
Nächstes war der Verdacht, dass evtl. an der Timereinstellung was falsch ist.
Deshalb auch 2 Versuche; einmal als "normaler Timer":
TCCR1A = 0; // Standard timer (No Counting, No PWM)
TCCR1B = 0 | (1<<CS12); // Prescaler = 256
TCNT1 = 0xFFFF - 31250; // Preload value
TIMSK |= (1<<TOIE1);
sei();
und einmal als CTC:
TCNT1 = 0;
TCCR1B = (1<<WGM12); // CTC-Mode
TCCR1B |= (1<<CS12); // Prescaler 256 (normal operation)
OCR1A = 31250; // Counting value: // 8 MHz / Prescaler 256 = 31250
TIMSK |= (1<<OCIE1A); // Enable timer
sei();
Die ISRs sind natürlich beide definiert:
SIGNAL(SIG_OUTPUT_COMPARE1A) // = TIMER1_COMPA_vect
{
LED_Toggle(BLUE);
}
ISR (SIG_OVERFLOW1)
{
LED_Toggle(GREEN);
}
Beide LEDs machen jedoch nichts; es wird stattdessen ein Reset durchgeführt. Lt. Simulator im AVR-Studio wird die jeweilige ISR aber korrekt angesprungen. Verfracht ich das ganze in die normale App.-Section (also als normales Programm), dann klappt das ganze wunderbar.
Ohne Interrupts funktioniert auch der Bootloader problemlos.
aktivierte Fuses: SPIEN, EESAVE, BOOTSZ: 1024 Words (0x0C00), BOOTRST
Linker-Kommando: -Wl,--section-start=.text=0x1800
Hab ich für die Interrupts im Bootloader noch irgendwas übersehen?
mfG
Ich versuche gerade, einen Bootloader mit einem Timer-Interrupt auszustatten, um die Möglichkeit eines Timeouts zu haben (falls die Kommunikation abreisst etc.)
Das Problem ist aber jetzt: Statt des Interrupts löst der Mega8 einen Reset aus.
Das erste was ja getan werden muss, ist ja die ISR-Tabelle in den Bootbereich zu legen. Das hab ich erst mit C versucht:
GICR |= (1 << IVCE); // Move interrupt table to boot section
GICR |= (1 << IVSEL);
aber auch mal direkt mit ASM, um wirklich die beiden Bits so eng wie möglich nacheinander zu setzen (muss ja innerhalb von 4 Zyklen passiert sein):
asm volatile (
"PUSH R24" "\n\t" // Save R24
"PUSH R25" "\n\t" // Save R25
"IN R24,0x3B" "\n\t" // GICR => R24
"IN R25,0x3B" "\n\t" // GICR => R25
"ORI R24, 0x01" "\n\t" // "GICR |= (1 << IVCE)"
"ORI R25, 0x03" "\n\t" // "GICR |= (1 << IVCE) | (1 << IVSEL)"
"OUT 0x3B, R24" "\n\t" // R24 => GICR
"OUT 0x3B, R25" "\n\t" // R25 => GICR
"PUSH R25" "\n\t" // Restore R25
"PUSH R24" "\n\t" // Restore R24
::);
Nächstes war der Verdacht, dass evtl. an der Timereinstellung was falsch ist.
Deshalb auch 2 Versuche; einmal als "normaler Timer":
TCCR1A = 0; // Standard timer (No Counting, No PWM)
TCCR1B = 0 | (1<<CS12); // Prescaler = 256
TCNT1 = 0xFFFF - 31250; // Preload value
TIMSK |= (1<<TOIE1);
sei();
und einmal als CTC:
TCNT1 = 0;
TCCR1B = (1<<WGM12); // CTC-Mode
TCCR1B |= (1<<CS12); // Prescaler 256 (normal operation)
OCR1A = 31250; // Counting value: // 8 MHz / Prescaler 256 = 31250
TIMSK |= (1<<OCIE1A); // Enable timer
sei();
Die ISRs sind natürlich beide definiert:
SIGNAL(SIG_OUTPUT_COMPARE1A) // = TIMER1_COMPA_vect
{
LED_Toggle(BLUE);
}
ISR (SIG_OVERFLOW1)
{
LED_Toggle(GREEN);
}
Beide LEDs machen jedoch nichts; es wird stattdessen ein Reset durchgeführt. Lt. Simulator im AVR-Studio wird die jeweilige ISR aber korrekt angesprungen. Verfracht ich das ganze in die normale App.-Section (also als normales Programm), dann klappt das ganze wunderbar.
Ohne Interrupts funktioniert auch der Bootloader problemlos.
aktivierte Fuses: SPIEN, EESAVE, BOOTSZ: 1024 Words (0x0C00), BOOTRST
Linker-Kommando: -Wl,--section-start=.text=0x1800
Hab ich für die Interrupts im Bootloader noch irgendwas übersehen?
mfG