Forum: Mikrocontroller und Digitale Elektronik AVR64DD: TCA0.SINGLE.PER verändert util/delay-Verhalten


von Michael W. (micha124)


Lesenswert?

Hallo,

vorab: mein erster Einsatz der neuen DD-Familie, bisher immer Atmega und 
Attiny (alt)

Nach einigen Versuchen aufgrund eines seltsamen Verhalten beim AVR64DD 
habe ich folgendes eingegrenzt:

Ich betreibe den Chip mit 3.3V und einem externen 3,6864MHz Quarz und 
nutze auch die util/delay.h. Den TCA0 nutze ich zum Zählen von 
50ms-Einheiten. Sobald ich bei der Initialisierung des TCA0 einen Wert 
in TCA0.SINGLE.PER schreibe, wird delay_ms nun massiv langsamer.

Ich benutze an anderer Stelle die RTC - daher hier der TCA.

Initialisierung auf 3,6864 MHZ - kontrolliert mit DSO über aktivierten 
PA7:
1
int main(void) {
2
  //Systemspeed 3,6864 MHz using external crystal
3
  ccp_write_io((uint8_t *)&CLKCTRL.XOSCHFCTRLA, 
4
    CLKCTRL_RUNSTDBY_bm
5
    | CLKCTRL_CSUTHF_4K_gc
6
    | CLKCTRL_FRQRANGE_8M_gc
7
    | CLKCTRL_ENABLE_bm);
8
  while(!(CLKCTRL.MCLKSTATUS & CLKCTRL_EXTS_bm)){;}
9
10
  /* Clear Main Clock Prescaler */
11
   _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0);
12
13
  //activate external clock    
14
  ccp_write_io((uint8_t *)&CLKCTRL.MCLKCTRLA, 
15
    CLKCTRL_CLKSEL_EXTCLK_gc
16
    | CLKCTRL_CLKOUT_bm  //output clock on PA7
17
    );
18
  while(CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm){;}

nun das interessante:
1
  _delay_ms(5000);  //wartet 5 Sekunden
2
3
  //Initialisierung TCA0
4
  /* set the period */
5
  TCA0.SINGLE.PER = 180;    //das hier ist die kritische Zeile...
6
  /* enable with prescaler */
7
  TCA0.SINGLE.CTRLA =
8
    TCA_SINGLE_CLKSEL_DIV1024_gc // -> 3600Hz
9
    | TCA_SINGLE_ENABLE_bm; /* start timer */
10
11
  /* enable overflow interrupt */
12
  TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm;
13
  /* set Normal mode */
14
  TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;
15
  /* disable event counting */
16
  TCA0.SINGLE.EVCTRL &= ~(TCA_SINGLE_CNTAEI_bm);
17
18
  sei();
19
20
  _delay_ms(5000);  //wartet ca. 170 (vermutlich 180) Sekunden
21
}
22
23
volatile uint8_t sensor_counter_50ms = 0;
24
ISR(TCA0_OVF_vect) {
25
  sensor_counter_50ms++;
26
  TCA0.SINGLE.INTFLAGS &= ~TCA_SINGLE_OVF_bm;
27
}

Ich habe zunächst vermutet, dass der TCA-Prescaler aus irgendeinem Grund 
den Systemtakt ändert. Via DSO habe ich aber verifiziert, dass auch im 
zweiten Delay der Systemtakt an PA7 noch bei den 3,68 MHz ist.

*Sobald ich das Setzen der PER aus dem TCA0 rausnehme, sind auch der 
untere delay 5 Sekunden (es reicht die eine Zeile auszukommentieren).*

Es scheint nun, dass der delay als Basis nicht den System Takt nimmt, 
sondern 5000 mal den Overflow von TCA0 (das wären dann ca. 250 Sekunden 
was hinkommenm könnte). Da ich hierzu aber keinerlei Hinweis im 
Datasheet finde und ich auch nicht von so einem Hardware-Bug ausgehe, 
ist die tatsächliche Ursache aber vermutlich eine andere.

Kann hier jemand zur Aufklärung und Lösung beitragen?

Grüße Micha

von Peter D. (peda)


Lesenswert?

Das Delay-Macro läuft im Main-Kontext. Es verlängert sich daher bei 
hoher Interruptlast, z.B. durch fehlendes Löschen des Interruptflags.
Beim AVR ist eine beliebte Fallgrube, daß Interruptflags durch Setzen 
gelöscht werden.

von Michael W. (micha124)


Lesenswert?

Hi Peter,

Peter D. schrieb:
> Das Delay-Macro läuft im Main-Kontext. Es verlängert sich daher bei
> hoher Interruptlast, z.B. durch fehlendes Löschen des Interruptflags.
> Beim AVR ist eine beliebte Fallgrube, daß Interruptflags durch Setzen
> gelöscht werden.

Aktuell sind keine weiteren IRQ aktiv.

Das IRQ-Flag für den TCA lösche ich doch dadurch - oder nicht?
1
TCA0.SINGLE.INTFLAGS &= ~TCA_SINGLE_OVF_bm;

Grüße Micha

von S. L. (sldt)


Lesenswert?

The OVF flag is not cleared automatically. It will be cleared only by 
writing a ‘1’ to its bit location.

von N. M. (mani)


Lesenswert?

Michael W. schrieb:
> Das IRQ-Flag für den TCA lösche ich doch dadurch - oder nicht?
>
> TCA0.SINGLE.INTFLAGS &= ~TCA_SINGLE_OVF_bm;

Den Read Modify Write kannst du dir vermutlich noch sparen und direkt 
das Bit schreiben:
1
TCA0.SINGLE.INTFLAGS=TCA_SINGLE_OVF_bm;

Normalerweise werden Interrupt Flags ja sowieso immer mit der 1 an der 
richtigen Stelle gelöscht.

Beitrag #7557482 wurde vom Autor gelöscht.
von Ron-Hardy G. (ron-hardy)


Lesenswert?

richtig, siehe TB3217-Getting Started with TCA
/* The interrupt flag has to be cleared manually */
 TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;

von Peter D. (peda)


Lesenswert?

Mir haben die alten AVRs besser gefallen, wo alle nötigen Information in 
nur einem Datenblatt konzentriert waren und nicht über viele Dokumente 
verstreut. Das hatte es auch viel einfacher gemacht, festzustellen, was 
denn nun für den konkreten Typ zutreffend ist.

von S. L. (sldt)


Lesenswert?

> ... nur einem Datenblatt konzentriert ...
Das ist hier doch der Fall, oder?

Nochmal zum
1
TCA0.SINGLE.INTFLAGS &= ~TCA_SINGLE_OVF_bm;
Genau falsch herum: das OVF bleibt bestehen, während eventuell gesetzte 
CMPn gelöscht werden.

von Georg M. (g_m)


Angehängte Dateien:

Lesenswert?

Peter D. schrieb:
> alle nötigen Information in nur einem Datenblatt

von Peter D. (peda)


Lesenswert?

S. L. schrieb:
> Das ist hier doch der Fall, oder?

Stimmt, in den aktuellen Datenblättern ist wieder alles drin. Da haben 
sich wohl welche beschwert.
Ich hab noch ein altes ATmega3209/4809 Datenblatt, was nur 68 Seiten 
kurz ist. Und dazu ein extra megaAVR 0-series Manual.

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

> ... altes ATmega3209/4809 Datenblatt ... dazu ein extra
> megaAVR 0-series Manual ...

Oh ja, darüber hatte ich mich damals auch geärgert.
  Das wurde dann ja sinnvollerweise wieder geändert.

von Gerhard H. (hauptmann)


Lesenswert?

Peter D. schrieb:
> Beim AVR ist eine beliebte Fallgrube, daß Interruptflags durch Setzen
> gelöscht werden.

Vorsicht. Nicht immer (nur). Zu allem Überfluß ist/war das in manchem 
Datenblatt der neuen AVRs auch noch falsch beschrieben, Copy&Paste aus 
alten Dokus ist hier offensichtlich die bevorzugte Erstell-Methode 
gewesen...

Die althergebrachte  Methode "IFlag wird beim Ausführen des 
Interrupt-Vektor gelöscht" ist bei SPI bis heute falsch im AVR128DA 
Blatt beschrieben, beim DB inzwischen korrigiert. Die richtige Methode 
zum Löschen ist da das pure Auslesen von INTFLAGS und Zugriff aufs DATA 
Register, hintereinander im Interrupt.

: Bearbeitet durch User
von Michael W. (micha124)


Lesenswert?

Hallo,

danke für die Schwarmintelligenz. Ursache war tatsächlich das falsche 
Resetten durch 0 des IRQ-Flags.

Grüße Micha

von Veit D. (devil-elec)


Lesenswert?

Peter D. schrieb:
> S. L. schrieb:
>> Das ist hier doch der Fall, oder?
>
> Stimmt, in den aktuellen Datenblättern ist wieder alles drin. Da haben
> sich wohl welche beschwert.
> Ich hab noch ein altes ATmega3209/4809 Datenblatt, was nur 68 Seiten
> kurz ist. Und dazu ein extra megaAVR 0-series Manual.

Hallo Peter,

das hatte ich dir schon einmal geantwortet. Als die megaAVR0 Serie 
frisch rauskam gab es tatsächlich 2 getrennte Manuals. Alles danach hat 
nur noch eins. Man sollte seine Dokumente hin und wieder aktualisieren. 
;-) Vor paar Monaten kamen für viele Controller neue Manuals raus. Ein 
nachschauen lohnt sich. Die TCB Kaskadierung für alle Mess-Modi steht 
bspw. im ARVxDB Manual jetzt drin.

PS: Wer Fehler findet kann das ruhig an Microchip melden. Kann zwar über 
ein Jahr dauern, aber man hat die Chance genutzt.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.