ATMEGA 644 Timer1 CTC Interrupt

Gast #6441033
Lesenswert?

Hallo in die Runde,

wahrscheinlich habe ich etwas vor den Augen und übersehen - ich habe 
folgenden Code und bin der Meinung, den Timer1 des ATMEGA 644 in den CTC 
Mode mit Interrupt on Compare Match (A) gesetzt zu haben. Zum Test soll 
in der ISR eine LED getoggelt werden. Hier der Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/wdt.h>
4

5
#define CANIX_LED_YELLOW 1
6
#define LED_PORT PORTA
7
#define LED_PORT_DDR DDRA
8

9
ISR(TIMER1_COMPA_vect) {
10
  LED_PORT ^= (1 << CANIX_LED_YELLOW);
11
}
12

13
void timer_init(void) {
14
  TCNT1 = 0;
15

16
  OCR1A = 200;
17
  TIMSK1 = (1 << OCIE1A); /* Enable interrupt on compare match */
18
  TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10); /* Prescaler */
19

20
  sei();
21
}
22

23
int main(void) {
24

25
  /* Enable watchdog with 2 secs timeout */
26
  //wdt_enable(WDTO_2S);
27
  //wdt_reset();
28

29
  /* Yellow LED */
30
  LED_PORT_DDR |= (1 << CANIX_LED_YELLOW);
31
        LED_PORT &= ~(1 << CANIX_LED_YELLOW);
32

33
  timer_init();
34

35
  /* test */
36
  while(1) {
37
    wdt_reset();
38
  }
39

40
  return 0;
41
}

F_CPU ist 8MHz, Fuses sind E:FC, H:D2, L:E7, der Code wird an Stelle 
7800hex als Bootloader geschrieben.
Ich sollte bei dem eingestellten Prescaler von 1024 doch ein gut 
sichbares Blinken der LED erwarten können?!
Nach meinen Recherchen wird die ISR nicht ausgeführt. Der Zähler aber 
läuft, denn wenn ich z.B. in der Hauptschleife den Zählerstand abfrage 
und bei jeweils 0 bzw. 100 die LED an- und ausschalte habe ich mein 
Blinken.

Der WD ist nur testweise im Code, der dürfte doch keinen Einfluss haben, 
oder?

Irgendwelche Fallstricke? Etwas übersehen? Interrupts global noch aus 
trotz sei()?

Viele Grüße Uli
Gast #6441077
Lesenswert?

Es ist die Boot start address, die mir der fuse-calculator bei einer 
boot-size von 2048 words vorgibt (https://www.engbedded.com/fusecalc/). 
Im Makefile habe ich diese 7800 dann als Beginn der Text-Section 
eingetragen. Was müsste ich denn sonst dem Linker mitgeben?

Der Code wird ja auch ausgeführt - die LED kann ich ja "händisch" über 
zB:
1
PORTA |= (1 << LED); //einschalten
2
PORTA &= ~(1 << LED); //ausschalten

Nur der Interrupt will nicht.
Ich hatte am Anfang meiner Versuche nicht den CTC mode sondern den 
normalen mode und einfach den Overflow-Interrupt nutzen wollen; das 
gleiche Ergebnis. Kein Interrupt.
Moderator Persönliche Seite #6441082
Lesenswert?

Uli schrieb:
> Was müsste ich denn sonst dem Linker mitgeben?

Schrob ich doch: 0xf000.

Du hast ein 4 KiB-Page für den Bootloader reserviert. Dein Device hat 64 
KiB. Folglich muss der Bootloader bei 60 KiB beginnen. Das ist 0xf000.

Atmel zählt das halt alles in 16-bit-Worten (weil der Flash so 
organisiert ist). Ist nicht wirklich logisch, macht sonst niemand: auf 
einem 32-bit-ARM werden trotzdem Byteadressen benutzt, die müssen dann 
halt durch 4 teilbar sein.

Wenn du das mit der Bootloader-Adresse vergurkst, funktioniert der Code 
an sich schon, nur die Interrupts nicht, denn es gibt an der Stelle, wo 
der Controller sie sucht, keine Vektortabelle.
Gast #6441088
Lesenswert?

Okay, mein Fehler. Klingt logisch. Dennoch noch eine Verständnisfrage: 
Warum startet der Code dennoch, wenn er doch - zumindest bei dem, was 
ich dem Linker mitgebe, nämlich 7800 - an der falschen Stelle im Flash 
liegt (liegen müsste)? Ich nahm an, dass die Adresse, die ich der 
Text-Section mitgebe dem Programmiertool - bei mir avrdude - sagt, an 
welche Stelle im Flash der Anfang geschrieben wird?

Gruß Uli
Moderator Persönliche Seite #6441090
Lesenswert?

Uli schrieb:
> Warum startet der Code dennoch

Er startet auf (byteweise) 0xf000. Dort ist aber nichts, also 0xFFFF. 
Das wird (wenn auch nicht dokumentiert) wie ein NOP behandelt. Der PC 
tickt weiter, läuft bei 0xFFFE dann über auf 0x0000 (er zählt immer 
16-bit-weise). Dort stehen auch wieder 0xFFFF-NOPs … irgendwann erreicht 
er dann deinen Code auf 0x7800, auf dem steht der Sprung auf deinen 
eigentlichen Reset-Vektor, ab da "tickt" es normal – bis zum ersten 
Interrupt. Der findet keinen Vektor, sondern nur 0xFFFF, und es geht von 
vorn los …

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren