Forum: Mikrocontroller und Digitale Elektronik UART Rx TX Interrupt Beispiel für AT32UC3C-EK AVR32


von Franzis I. (reparateur)


Lesenswert?

Hallo,
ich habe eine Frage zu dem mitgelieferten Beispiel für das Board
AT32UC3C-EK
von Atmel.

Das Beispiel ist folgendermassen aufgebaut:
1. Rx Interrupt wird eingerichtet(aktiviert, ISR ahandler angemeldet)
2. Wenn ein Zeichen empfangen wird, wird die entsprechende ISR 
aufgerufen in der dann dieser Zeichen als Echo zurückgeschickt wird.

 Das Ganze funktioniert ohne irgendwelche Änderungen und anpassungen: 
Compilieren aufs Board laden, fertig. Das ganze funktioniert aber, wenn 
ich Zeichen für Zeichen in Terminal schicke (hterm). Sobald ich mehrere 
Zeichen reintippe und aufs "Absenden" drücke, wird das erste Zeichen des 
Strings oder manchmal auch irgendein Müll empfangen.

Meine Fehlersuche ergab bis jetzt: Wenn das erste Zeichen geschickt 
wurde, ist der uC ja in ISR und versucht in dieser ISR das Zeichen 
zurück zu schicken, dann trudelt schon das 2. Zeichen an, und ab da 
springt der uC immer wieder in die ISR und versendet meistens Müll. Der 
Interrupt request wird also nicht zurück gesetzt.

Meine Frage ist also, wie mache ich das manuele Zurücksetzen des 
Requests bei diesem uC? Und was noch wichtiger, wieso scheitert hier das 
automatische Rücksetzen des Requests, wo es doch beim "Zeichen für 
Zeichen" ohne das manuele Eingreifen funktionier?

Vielen Dank. Später hänge ich noch entspr. Code

von cskulkw (Gast)


Lesenswert?

Hallo Franzis,

die Beispiele sind immer nur funktional und häufig nur auf ein Thema 
zugeschnitten. Besser Du suchst Dir eine Demoapplikation, in der ein 
datenstreaming umgesetzt worden ist.

Wenn Du eine Zeichenkette empfangen möchtest, dann solltest Du einen 
Puffer definieren und zwei Zeiger (Anfang und Ende). Dann kann der 
Empfang ereignisunabhängig vom Senden durchgeführt werden.

Man nennt das auch FIFO. First in First out.

Ist allerdings nicht ganz mühelos.

von Franzis I. (reparateur)


Lesenswert?

cskulkw schrieb:
> die Beispiele sind immer nur funktional und häufig nur auf ein Thema
> zugeschnitten. Besser Du suchst Dir eine Demoapplikation, in der ein
> datenstreaming umgesetzt worden ist.
>
> Wenn Du eine Zeichenkette empfangen möchtest, dann solltest Du einen
> Puffer definieren und zwei Zeiger (Anfang und Ende). Dann kann der
> Empfang ereignisunabhängig vom Senden durchgeführt werden.
>
> Man nennt das auch FIFO. First in First out.

@cskulkw:
Vielen Dank für die hilfreihe Antwort. Ich dachte schon deren Beispiel 
ist schlecht/ mit Fehlern programmiert worden.

Ich werde mich nach solch einem Beispiel suchen.
@all:
Kann jemand was generel zu den Interrupts bei diesem AVR32 sagen, Tips 
geben?
Oder gar zu den USART Interrupts. Hier ist der Code worum es hier geht:
1
static void usart_int_handler(void)
2
{
3
  int c;
4
  // The USART Rx interrupt flag is cleared by side effect when reading the
5
  // received character.
6
  // Waiting until the interrupt has actually been cleared is here useless as
7
  // the call to usart_write_char will take enough time for this before the
8
  // interrupt handler is leaved and the interrupt priority level is unmasked by
9
  // the CPU.
10
  usart_read_char(EXAMPLE_USART, &c);
11
12
  // Print the received character to USART.
13
  // It is a simple echo
14
  usart_write_char(EXAMPLE_USART, c);
15
}
16
17
int main(void)
18
{
19
  static const gpio_map_t USART_GPIO_MAP =
20
  {
21
    {EXAMPLE_USART_RX_PIN, EXAMPLE_USART_RX_FUNCTION},
22
    {EXAMPLE_USART_TX_PIN, EXAMPLE_USART_TX_FUNCTION}
23
  };
24
25
  // USART options.
26
  static const usart_options_t USART_OPTIONS =
27
  {
28
    .baudrate     = EXAMPLE_USART_BAUDRATE,
29
    .charlength   = 8,
30
    .paritytype   = USART_NO_PARITY,
31
    .stopbits     = USART_1_STOPBIT,
32
    .channelmode  = USART_NORMAL_CHMODE
33
  };
34
35
36
  // Configure Osc0 in crystal mode (i.e. use of an external crystal source, with
37
  // frequency FOSC0) with an appropriate startup time then switch the main clock
38
  // source to Osc0.
39
  pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);
40
41
  // Assign GPIO to USART.
42
  gpio_enable_module(USART_GPIO_MAP,
43
                     sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));
44
45
  // Initialize USART in RS232 mode.
46
  usart_init_rs232(EXAMPLE_USART, &USART_OPTIONS, EXAMPLE_TARGET_PBACLK_FREQ_HZ);
47
  print(EXAMPLE_USART, ".: Using interrupts with the USART :.\r\n\r\n");
48
49
  // Disable all interrupts.
50
  Disable_global_interrupt();
51
52
  // Initialize interrupt vectors.
53
  INTC_init_interrupts();
54
55
  // Register the USART interrupt handler to the interrupt controller.
56
  // usart_int_handler is the interrupt handler to register.
57
  // EXAMPLE_USART_IRQ is the IRQ of the interrupt handler to register.
58
  // AVR32_INTC_INT0 is the interrupt priority level to assign to the group of
59
  // this IRQ.
60
  // void INTC_register_interrupt(__int_handler handler, unsigned int irq, unsigned int int_level);
61
  INTC_register_interrupt(&usart_int_handler, EXAMPLE_USART_IRQ, AVR32_INTC_INT0);
62
63
  // Enable USART Rx interrupt.
64
  EXAMPLE_USART->ier = AVR32_USART_IER_RXRDY_MASK;
65
  print(EXAMPLE_USART, "Type a character to use the interrupt handler.\r\n"
66
                       "It will show up on your screen.\r\n\r\n");
67
68
  // Enable all interrupts.
69
  Enable_global_interrupt();
70
71
72
  // When the USART interrupt occurs, this will wake the CPU up which will then
73
  // execute the interrupt handler code then come back to the while(1) loop below
74
  // to execute the sleep instruction again.
75
76
  while(1)
77
  {
78
    // If there is a chance that any PB write operations are incomplete, the CPU
79
    // should perform a read operation from any register on the PB bus before
80
    // executing the sleep instruction.
81
    AVR32_INTC.ipr[0];  // Dummy read
82
83
    // Go to FROZEN sleep mode.
84
    SLEEP(AVR32_PM_SMODE_FROZEN);
85
    // When the device wakes up due to an interrupt, once the interrupt is serviced,
86
    // go back into FROZEN sleep mode.
87
  }

Un dieser "cleared by side effect" scheint wohl nicht immer zu 
funktionieren und deswegen springt der uC immer wieder in diese ISR.

von Franzis I. (reparateur)


Lesenswert?

Keiner, der irgendwas zu den Interrupts bei AVR32 generel oder noch 
genauer zu den UART Interrupts was sagen?

von Powerpedro (Gast)


Lesenswert?

Hallo Franzis,
Ich habe gerade das gleiche Problem und bin über deinen Eintrag 
gestolpert...  Konntest du inzwischen das Problem beheben mit dem 
clearen des Interruptflags? Würde mir sehr weiterhelfen...

von Locutus (Gast)


Lesenswert?

Hallo zusammen,
ich habe das gleiche Problem. Hat jemand von euch eine Lösung gefunden?
Beste Grüße
Locutus

von Locutus (Gast)


Lesenswert?

Nachtrag: Bei mir funktioniert der Code solange ich eine Baudrate <3 
Mega-Baud verwende. Gehe ich höher, passiert das gleiche wie oben 
Beschrieben

Beste Grüße
Locutus

von Philipp S. (pschaefer)


Lesenswert?

Hallo,

ich habe ein sehr sehr ähnliches Problem.

Wenn ich ein Zeichen sende, klappt dies wunderbar. Wenn ich aber mehrere 
direkt hintereinander mit hterm versende, bekomme ich non stop das erste 
zurückgesendet.

Auftreten tut dies auf einem AT32UC3A3256 mit 57600 Baud. Wenn ich die 
Baudrate auf 9600 senke, dann funktioniert alles.

Hat jemand eine Lösung?

Gruß

Philipp

von Michael B. (Gast)


Lesenswert?

Hab' auch das Problem. Hat schon jemand eine Lösung!?

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.