Forum: Mikrocontroller und Digitale Elektronik Xmega: USART legt Timer lahm? Kennt jemand das Problem?


von Stefan E. (stefanosch)


Lesenswert?

Hallo,

nach mehreren Stunden der Portierung von einem ATmega168 auf einen 
ATxmega128A4U, des Debuggen, Lesens des Manuals und Ausprobierens 
stehe ich immer noch auf dem Schlauch.

Der aufs wesentliche gekürzte Code am Ende hat in der main drei 
verschiedene Implementierungen, die sich durch das entsprechende 
define umschalten lassen.

Kurz zur Funktionsweise :

Zuerst wird das System initialisiert und der Timer gestartet. Der Timer 
lässt ganz profan mehrere LEDs nacheinander kurz aufleuchten. Das ganze 
erfolgt solange bis er wieder gestoppt wird. Danach wird er erneut 
gestartet.

Das Starten/Stoppen erfolgt in den ersten beiden Varianten regelmässig 
durch umschalten/warten.

In der dritten Variante soll es durch Befehle von aussen erfolgen.

Hier das Problem :

Variante 1 und 2 funktionieren einwandfrei, die 3. nur solange 
kein Zeichen von der seriellen Schnittstelle empfangen wurde. Sobald 
irgend ein Zeichen empfangen wurde wird der Timer abgschaltet und lässt 
sich auch nicht mehr aktivieren. Der Sprung in die beiden Funktionen 
enable_timer() und disable_timer() bei Empfang der Zeichen d oder e 
erfolgt auch korrekt, nur das sich dann aber nichts tut.

Hier meine Fragen :

1. Hat schon mal jemand ein ähnliches Verhalten bei den Xmegas 
festgestellt?

2. Wo gibt es die Errata-Files für die Xmegas, bei den Megas waren sie 
einfach zu finden?

3. Gibt es eine Abhängigkeit zwischen Timer und Usart, die man erst 
wegkonfigurieren muss?

4. Wäre jemand so nett den Code bei sich zu testen, um zu sehen ob er da 
genauso versagt?

5. Ist es schon dunkel draußen? ;-)

Hier der Code :

1
#define F_CPU 2000000
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
7
8
#define LED_PORT  PORTD
9
#define LED0_PIN_bm  PIN0_bm
10
#define LED1_PIN_bm  PIN1_bm
11
#define LED2_PIN_bm  PIN2_bm
12
#define LED3_PIN_bm  PIN3_bm
13
#define LED4_PIN_bm  PIN4_bm
14
15
#define LED_bm    LED0_PIN_bm | LED1_PIN_bm | LED2_PIN_bm | LED3_PIN_bm | LED4_PIN_bm
16
17
#define BAUDRATE 38400
18
#define RS232 USARTD1
19
#define RS232_PORT PORTD
20
#define RS232_RX_PIN_bm PIN6_bm
21
#define RS232_TX_PIN_bm PIN7_bm
22
23
void init_clock()
24
{
25
   OSC.CTRL = OSC_RC2MEN_bm;
26
   OSC.PLLCTRL = OSC_PLLSRC_RC2M_gc;
27
   while(!(OSC.STATUS & OSC_RC2MRDY_bm));
28
   CCP = CCP_IOREG_gc;
29
   CLK.CTRL = CLK_SCLKSEL_RC2M_gc;
30
}
31
32
void init_leds()
33
{
34
   PORTCFG.MPCMASK = LED_bm;
35
   LED_PORT.PIN0CTRL = PORT_OPC_PULLDOWN_gc;
36
   LED_PORT.DIR  |=  LED_bm;
37
   LED_PORT.OUT  &= ~LED_bm;
38
}
39
40
void init_usart(void)
41
{
42
   RS232.BAUDCTRLB = (unsigned char)((F_CPU/16/BAUDRATE-1)>>8);
43
   RS232.BAUDCTRLA = (unsigned char)((F_CPU/16/BAUDRATE-1));
44
   RS232.CTRLA = USART_RXCINTLVL_HI_gc;
45
   RS232.CTRLB = USART_TXEN_bm | USART_RXEN_bm;
46
   RS232.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;
47
   PORTD.DIR &= ~PIN6_bm;
48
   PORTD.DIR |=  PIN7_bm;
49
}
50
51
int rxChar()
52
{
53
   while(!(RS232.STATUS & USART_RXCIF_bm));
54
   return (int)RS232.DATA;
55
}
56
57
void init_timer()
58
{
59
   TCC0.CTRLA = (TCC0.CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_DIV8_gc;
60
   TCC0.CTRLB |= TC_WGMODE_NORMAL_gc;
61
   TCC0.PER = 0xffff;
62
   TCC0.CCA = 0x2000;
63
   TCC0.CCB = 0x4000;
64
   TCC0.CCC = 0x8000;
65
   TCC0.CCD = 0xC000;
66
}
67
68
void enable_timer()
69
{
70
   TCC0.CTRLA = (TCC0.CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_DIV8_gc;
71
   TCC0.INTCTRLA = TC_OVFINTLVL_HI_gc;
72
   TCC0.INTCTRLB = (TC_CCAINTLVL_MED_gc | TC_CCBINTLVL_MED_gc | TC_CCCINTLVL_MED_gc | TC_CCDINTLVL_MED_gc);
73
   TCC0.CTRLFSET = TC_CMD_RESET_gc;
74
   TCC0.INTFLAGS = TCC0.INTFLAGS;
75
}
76
77
void disable_timer()
78
{
79
   TCC0.CTRLA = (TCC0.CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_OFF_gc;
80
   TCC0.INTCTRLA = 0;
81
   TCC0.INTCTRLB = 0;
82
}
83
84
void reset()
85
{
86
   LED_PORT.OUT &= ~(LED_bm);
87
   PMIC.CTRL = PMIC_HILVLEN_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm;
88
   sei();
89
}
90
91
ISR(TCC0_CCA_vect)
92
{
93
   LED_PORT.OUT &= ~(LED_bm);
94
   LED_PORT.OUT |= LED1_PIN_bm;
95
}
96
97
ISR(TCC0_CCB_vect)
98
{
99
   LED_PORT.OUT &= ~(LED_bm);
100
   LED_PORT.OUT |= LED2_PIN_bm;
101
}
102
103
ISR(TCC0_CCC_vect)
104
{
105
   LED_PORT.OUT &= ~(LED_bm);
106
   LED_PORT.OUT |= LED3_PIN_bm;
107
}
108
109
ISR(TCC0_CCD_vect)
110
{
111
   LED_PORT.OUT &= ~(LED_bm);
112
   LED_PORT.OUT |= LED4_PIN_bm;
113
}
114
115
ISR(TCC0_OVF_vect)
116
{
117
   LED_PORT.OUT &= ~(LED_bm);
118
}
119
120
int main(void)
121
{
122
   init_clock();
123
   init_leds();
124
   init_usart();
125
   init_timer();
126
   enable_timer(0);
127
   reset(0);
128
129
   while(1)
130
   {
131
132
#define TEST_CODE 3
133
#if TEST_CODE == 1
134
135
      /*
136
         Timer aktivieren und deaktivieren funktioniert
137
         bei Verwendung nur dieses Codes einwandfrei
138
      */
139
      enable_timer(0);
140
      _delay_ms(500);
141
      LED_PORT.OUT &= ~(LED_bm);
142
      disable_timer();
143
      _delay_ms(2000);
144
145
#elif TEST_CODE == 2
146
147
      /*
148
         Timer aktivieren und deaktivieren funktioniert
149
         bei Verwendung nur dieses Codes einwandfrei
150
      */
151
      static int ch = 'e';
152
      switch(ch)
153
      {
154
         case 'e':
155
            enable_timer();
156
            _delay_ms(500);
157
            break;
158
159
         case 'd':
160
            disable_timer();
161
            LED_PORT.OUT &= ~(LED_bm);
162
            _delay_ms(2000);
163
            break;
164
165
         default:
166
            ch = 0;
167
            break;
168
      }
169
      ch = (ch == 'e') ? 'd' : 'e';
170
171
#elif TEST_CODE == 3
172
173
      int ch = rxChar();
174
      switch(ch)
175
      {
176
         case 'e':
177
            enable_timer();
178
            break;
179
180
         case 'd':
181
            disable_timer();
182
            LED_PORT.OUT &= ~(LED_bm);
183
            break;
184
185
         default:
186
            ch = 0;
187
            break;
188
      }
189
190
#endif
191
   }
192
   return 0;
193
}

von Konrad S. (maybee)


Lesenswert?

Stefan E. schrieb:
> 2. Wo gibt es die Errata-Files für die Xmegas, bei den Megas waren sie
> einfach zu finden?

Wie bei allen ATxmega-Serien im Baustein-spezifischen Datenblatt, nicht 
in der Beschreibung für die ganze Serie. Also z.B. hier:
http://www.atmel.com/Images/Atmel-8387-8-and16-bit-AVR-Microcontroller-XMEGA-A4U_Datasheet.pdf

> 5. Ist es schon dunkel draußen? ;-)

Nein. ;-)

von Gerhard G. (g_g)


Lesenswert?

Hallo,

ich habe deinen Code getestet. Fehler liegt hier:

int ch = rxChar();

Es wird kein 'e' oder 'd' empfangen, sondern hier passiert irgend etwas 
fehlerhaftes!! Das Programm hängt sich hier auf.


Mit meiner USART-Routine ist dein Code ok!

USART-Lib hier rs232.h/rs232.c
https://github.com/BodyTrack/BodyTrack_CustomLoggers

Gruß G.G.

von Stefan E. (stefanosch)


Lesenswert?

ich habe den Code jetzt mal zu Hause auf einem XPlain-Board getestet. Da 
ging erst auch nichts.

Nachdem ich die Antwort von G.G. gelesen hatte bin ich noch mal die 
Usart-Teile durchgegangen und siehe da es gab noch eine 
Interrupt-Zuweisung

RS232.CTRLA = USART_RXCINTLVL_HI_gc;

ohne zugehörige ISR. Nachdem ich diese entfernt hatte, funktioniert der 
Code bei mir auch wie gewollt. Jetzt muss es nur noch auf dem 
ATxmega128A4U laufen.

Irgendwie ist man nach 8 Stunden betriebsblind.

Danke für Eure Hilfe

Stefan

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Stefan E. schrieb:
> void enable_timer()
> {
Aber dann in mehreren Aufrufen so was:

> enable_timer(0);
Da die Funktion keine Parameter entgegen nimmt, solltest du sie auch 
nicht mit welchen aufrufen. Eigentlich sollten da auch Fehler beim 
Kompilieren erscheinen, a la : "Too many parameters when calling 
enable_timer"
Wenn keine Fehler erscheinen, schau dir mal deine Prototypen an...

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.