Unverständliches Verhalten bei XMega32e5

Gast #4498745
Lesenswert?
• ▲
▼
Guten Morgen,

leider habe ich wieder einmal ein Verständnisproblem. Es geht um 
folgenden Code:
1
#define F_CPU 2000000L
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5

6
volatile uint8_t tmp = 0;
7

8

9
ISR( TCD5_OVF_vect )
10
{
11
  
12
  PORTD.OUTTGL = PIN6_bm;
13
}
14

15

16
int main(void)
17
{
18

19
  //Oszillator auf 2Mhz stellen
20
  OSC.CTRL |= OSC_RC2MEN_bm;
21
  // Warten bis der Oszillator bereit ist
22
  while(!(OSC.STATUS & OSC_RC2MRDY_bm));
23
  //Schützt I/O Register, Interrupts werden ignoriert
24
  CCP = CCP_IOREG_gc;
25
  //aktiviert den internen Oszillator
26
  CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC2M_gc;
27

28
  PORTD.DIR |= PIN5_bm | PIN6_bm | PIN7_bm;    // PORTD Pins 5, 6 und 7 sind Ausgang
29

30
  
31
  
32
  PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; 
33

34
  TCD5.CTRLA |= TC45_CLKSEL_DIV1024_gc;      // Timer 4 Vorteiler 1024
35
  TCD5.CTRLB |= TC45_WGMODE_NORMAL_gc;      // NormalMode
36
  TCD5.INTCTRLA |= TC45_OVFINTLVL_HI_gc;      // Interrupt hat höchste Priorität
37
  TCD5.PER = 0x07A1;                // entspricht 1.953, sollte eine Sekunde ergeben
38
  //TCD5.CNT = 65000L;
39

40
  sei();
41
  
42
    /* Replace with your application code */
43
    while (1) 
44
    {
45
  PORTD.OUTTGL = PIN5_bm;
46
  for (uint8_t i = 0; i < 100; i++)
47
  {
48
    _delay_ms(5);
49
  }
50

51
    }
52

53
}

Was sollte passieren? Nun: es sollten Pin D5 (in der Hauptschleife 
getoggelt) mit 2 Hz und Pin D6 (über den Timer getoggelt) mit 1 Hz 
blinken! Was tun sie: Nach Reset gehen Sie sofort an und blinken dann 
unregelmäßig (!!!!!!!!!!!!!!!!!) mit einer Periode zwischen 1 und 10 
sec. (Oder so!)

Nein, das Programm hat keinen Sinn! Es ist nur zum Verständnis 
geschrieben.

Ja, wenn ich den ganzen Timerzirkus rausnehme, dann blinkt PIN D5 wie 
erwartet. Ich habe den Eindruck, dass der Timerkrempel den ganzen µC 
blockiert!
#4498791
Lesenswert?
• ▲
▼
@ ArduStemmi (Gast)


>ISR( TCD5_OVF_vect )
>{

>  PORTD.OUTTGL = PIN6_bm;
>}

Beim Überlauf von TCD5 soll IO in PD6 umgeschaltet werden.


>
>  //Oszillator auf 2Mhz stellen
>  OSC.CTRL |= OSC_RC2MEN_bm;
>  // Warten bis der Oszillator bereit ist
>  while(!(OSC.STATUS & OSC_RC2MRDY_bm));
>  //Schützt I/O Register, Interrupts werden ignoriert
>  CCP = CCP_IOREG_gc;
>  //aktiviert den internen Oszillator
>  CLK.CTRL = (CLK.CTRL & ~CLK_SCLKSEL_gm) | CLK_SCLKSEL_RC2M_gc;

Das ist Unsinn, denn der 2 MHz Oszillator ist nach dem Reset 
standardmäßuig aktiv. Kann man alles weglassen.

>  TCD5.CTRLA |= TC45_CLKSEL_DIV1024_gc;      // Timer 4 Vorteiler 1024

Sowas ist hier ungünstig bis falsch. Eine direkte Zuweisung ist das 
Mittel der Wahl.

   TCD5.CTRLA = TC45_CLKSEL_DIV1024_gc;      // Timer 4 Vorteiler 1024

>  TCD5.CTRLB |= TC45_WGMODE_NORMAL_gc;      // NormalMode
>  TCD5.INTCTRLA |= TC45_OVFINTLVL_HI_gc;      // Interrupt hat höchste Priorität

Hier ebenfalls.

>  TCD5.PER = 0x07A1;                // entspricht 1.953, sollte eine Sekunde 
ergeben

Warum schreibst du das in Hex, das kann kein Mensch verstehen.

2 MHz / 1024 = 1953 Hz.

Also eher

   TCD5.PER = 1953;

  sei();

>    /* Replace with your application code */
>    while (1)
>    {
>  PORTD.OUTTGL = PIN5_bm;
>  for (uint8_t i = 0; i < 100; i++)
>  {
>    _delay_ms(5);
>  }

>    }

Hier läßt du PD5 per Software blinken.


>
>Was sollte passieren? Nun: es sollten Pin D5 (in der Hauptschleife
>getoggelt) mit 2 Hz und Pin D6 (über den Timer getoggelt) mit 1 Hz
>blinken! Was tun sie: Nach Reset gehen Sie sofort an und blinken dann
>unregelmäßig (!!!!!!!!!!!!!!!!!) mit einer Periode zwischen 1 und 10
>sec. (Oder so!)

Klingt nach einem Watchdogreset. Ist der per Fuses ausgeschaltet?

>Ja, wenn ich den ganzen Timerzirkus rausnehme, dann blinkt PIN D5 wie
>erwartet. Ich habe den Eindruck, dass der Timerkrempel den ganzen µC
>blockiert!

Dann läuft was schief ;-)

Mach mal wie oben geschrieben normale Zuweisungen beim Timer-Init.
Gast #4498875
Lesenswert?
• ▲
▼
Danke für Deine Erläuterungen! Ich verstehe nicht, warum die direkte 
Zuweisung anders funktionieren sollte! Kannst Du das bitte kurz 
erläutern?

Die Einstellung des Taktes ist nur zur Sicherheit drin! Ich wollte halt 
sicher gehen, dass es nicht am falschen Takt liegt!

Wie sollten denn die Fuses stehen, um den Watchdog zu unterdrücken? Und, 
warum kann man beim XMega alles per SW einstellen, nur den WD 
ausgerechnet nicht?
#4499307
Lesenswert?
• ▲
▼
@  ArduStemmi (Gast)


>Danke für Deine Erläuterungen! Ich verstehe nicht, warum die direkte
>Zuweisung anders funktionieren sollte! Kannst Du das bitte kurz
>erläutern?

Das kommt auf den vorherigen Zustand des Registers an. Manchmal will man 
das, manchmal eben nicht.

>Wie sollten denn die Fuses stehen, um den Watchdog zu unterdrücken? Und,
>warum kann man beim XMega alles per SW einstellen, nur den WD
>ausgerechnet nicht?

Frag das Atmel.

Prbier einfach mal die aufgeräumte Version.
1
#define F_CPU 2000000L
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5

6
volatile uint8_t tmp = 0;
7

8
ISR( TCD5_OVF_vect )
9
{
10
  
11
  PORTD.OUTTGL = PIN6_bm;
12
}
13

14

15
int main(void)
16
{
17

18
  PORTD.DIR |= PIN5_bm | PIN6_bm | PIN7_bm;      // PORTD Pins 5, 6 und 7 sind Ausgang
19
  
20
  TCD5.CTRLA = TC45_CLKSEL_DIV1024_gc;        // Timer 4 Vorteiler 1024
21
  TCD5.CTRLB = TC45_WGMODE_NORMAL_gc;          // NormalMode
22
  TCD5.INTCTRLA = TC45_OVFINTLVL_HI_gc;        // Interrupt hat höchste Priorität
23
  TCD5.PER = 1953;                        // 1s Periodendauer
24

25
  PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; 
26
  sei();
27
  
28
  /* Replace with your application code */
29
  while (1) 
30
  {
31
    PORTD.OUTTGL = PIN5_bm;
32
    for (uint8_t i = 0; i < 100; i++)
33
    {
34
      _delay_ms(5);
35
    }
36
  }
37
}
Gast #4499321
Lesenswert?
• ▲
▼
also ich hab das gerade mal nachgestellt. Auch mit einem ATxmega32e5. 
Bei mir blinkt PD5 regelmäßig ... allerdings komischerweise zu langsam 
(statt 2 Hz eher mit 0,3 Hz). Dafür leuchtet PD6 durchgehend. Zumindest 
sieht es so aus. Tatsächlich wird jedoch die ISR ständig aufgerufen. 
Laut Oszi toggelt PD6 alle 14,5 us.
Gast #4499324
Lesenswert?
• ▲
▼
Josef H. schrieb:
> Hei,
> mit TCD5.INTFLAGS |= 1;
> in interrupt Flag löschen.

Winn ich im ISR für den Overflow Interrupt den Interrupt Flag jedesmal 
lösche, dann klappt es. Soll das so sein? Das macht man aber beim Atmega 
nicht so! Also ich jedenfalls. Und es steht meines Erachtens auch 
nirgends.
Gast #4499491
Lesenswert?
• ▲
▼
Zeig' mir mal, wo es im Datenblatt steht! Viele andere und auch ich, 
haben des so explizit nicht herauslesen können! Bitte sag mir jetzt 
nicht: Nirgends steht, dass es gelöscht wird, daraus folgt ...! Das ist 
schon klar! Aber, da es sich um eine Besonderheit handelt, hätte man 
explizit drauf aufmerksam machen müssen.

Für mich ist das Thema damit erledigt. Geärgert habe ich mich auch 
genug. Ich spiele weiter mit dem Mega rum!
Moderator Persönliche Seite #4499527
Lesenswert?
• ▲
▼
ArduStemmi schrieb:
> Und, warum kann man beim XMega alles per SW einstellen, nur den WD
> ausgerechnet nicht?

Weil ein Wachhund, der sich von einer irrlaufenden Firmware
abschlachten lässt, kein sinnvoller Wachhund ist.

Man kann ihn natürlich auch per Software schalten, aber wenn
man ihn per Fuse aktiviert, dann ist das eine Nummer sicherer, und
er darf sich nicht wieder lahmlegen lassen.

(Hat mit deinem Problem nun nichts mehr zu tun, aber die Frage war
noch nicht beantwortet worden.)
Gast #4500186
Lesenswert?
• ▲
▼
ArduStemm schrieb:
>> OVFIF will not be cleared when the interrupt vector is executed. The
>> flag is cleared by writing a one to its bit location.


Das trifft bei dem E5 übrigens auf fast alle IRQ Flags zu. Über die 
Nummer bin ich auch schon gestolpert. Ist man nicht gewöhnt und 
überliest es gleich mal im Datenblatt. Beim OVFIF steht es wenigstens 
noch drin, das es nicht gelöscht wird ;-) Wenn da einfach nur "nichts" 
steht, fängst Du richtig an zu suchen, weil beim AVR rechnet man nicht 
damit...
(Firma: TravelRec.) Persönliche Seite #4500210
Lesenswert?
• ▲
▼
Willi schrieb:
> Das trifft bei dem E5 übrigens auf fast alle IRQ Flags zu.

Das stimmt nicht. Es trifft lediglich auf die Flags zu, die einen 
DMA-Tansfer auslösen und von dem DMA-Transfer auch zurückgesetzt werden 
und bei denen dieses Verhalten sinnvoll ist, da ein automatisches 
Löschen in Verbindung mit DMA eher Fehler provozieren würde. Flags, die 
ohnehin durch die Hardware (DRE, RXD...) oder durch Interrupte gelöscht 
werden, sind davon nicht betroffen. Es schadet daher nicht, beim 
Programmieren jedes verwendete Flag im DB auf sein Verhalten hin zu 
überprüfen. Einige dieser "besonderen" Flags sind auch in den anderen 
XMEGAs der Serien A-D zu finden.

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