Hallo zusammen,
also direkt zum Problem:
Ich empfange mit dem USART1 einen Frame
der wird mit dem RXRDY-Interrupt behandelt
0x7e Delimiter
0xnn Länge des Frames
speichern in einer Array
wenn die Länge bekannt ist, PDCA initialisieren
und restliche Bytes ebenfalls in die Array schaufeln
klappt wunderbar, d.h. solange ich die Frames manuell mit Hterm eintippe
Tippe ich 0x7e 0x05 PAUSE 0x01 0x02 0x03 ein läuft alles problemlos.
Sende ich dagegen 0x7e 0x05 0x01 0x02 0x03 an einem Stück werden 2
Zeichen verschluckt!? Das ganze ist reproduzierbar und habe es auch
schom mit verschiedenen Baudraten probiert. Getaktet ist der
AT32UC3B0512 mit 12Mhz.
Habe ich irgendwas vergessen zu initialisieren? Ich habe keine Ahnung,
wo ich weiter suchen kann/soll.
Ergebins im Array: 0x00 0x00 0x03 sonst 0x00
Ich bin ein bisschen ratlos. Eigentlich stammen die Funktionen von einem
8bitter. Da klappt das ganze - natürlich ohne DMA - ganz gut, und wollte
jetzt, wo schon ein PDCA vorhanden ist, den auch benutzen.
Init-Routine vor Endlosschleife
1 | sysclk_init();
|
2 |
|
3 | //Oscillator konfigurieren
|
4 | osc_enable(OSC_ID_OSC0);
|
5 | osc_wait_ready(OSC_ID_OSC0);
|
6 | sysclk_set_source(SYSCLK_SRC_OSC0);
|
7 |
|
8 | static const usart_options_t USART_OPTIONS =
|
9 | {
|
10 | .baudrate = 57600,
|
11 | .charlength = 8,
|
12 | .paritytype = USART_NO_PARITY,
|
13 | .stopbits = USART_1_STOPBIT,
|
14 | .channelmode = USART_NORMAL_CHMODE
|
15 | };
|
16 |
|
17 | gpio_enable_module(USART_GPIO_MAP, sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));
|
18 | usart_init_rs232((&AVR32_USART1), &USART_OPTIONS, 12000000L);
|
19 |
|
20 | INTC_init_interrupts();
|
21 | INTC_register_interrupt(&pdca_recieve_complete, AVR32_PDCA_IRQ_1 , AVR32_INTC_INT1);
|
22 | INTC_register_interrupt(&usart1_int_handler, AVR32_USART1_IRQ, AVR32_INTC_INT3);
|
23 | (&AVR32_USART1)->ier = AVR32_USART_IER_RXRDY_MASK;
|
24 |
|
25 | Enable_global_interrupt();
|
Hier wird der Wechsel von Interrupt-Steuerung nach DMA vollzogen:
1 | __attribute__((__interrupt__)) static void usart1_int_handler(void)
|
2 | {
|
3 | gpio_tgl_gpio_pin(AVR32_PIN_PA08);
|
4 |
|
5 | int c = 0;
|
6 | usart_read_char((&AVR32_USART1), &c );
|
7 |
|
8 | unsigned char tmp_UDR = (unsigned char) c ;
|
9 | unsigned char tmp_ES = EmpfangsSeite;
|
10 | unsigned char tmp_Position = Seite[tmp_ES].position;
|
11 |
|
12 | switch(frameError)
|
13 | {
|
14 | case FALSE:
|
15 | if(tmp_Position == 0x00)
|
16 | {
|
17 | if(tmp_UDR != 0x7e)
|
18 | {
|
19 | usart_write_line((&AVR32_USART1),"no Delimiter\r\n");
|
20 | frameError = TRUE;
|
21 | return;
|
22 | }
|
23 | usart_write_line((&AVR32_USART1),"Delimiter\r\n");
|
24 | tmp_Position++;
|
25 | Seite[tmp_ES].position=tmp_Position;
|
26 | return;
|
27 | }
|
28 |
|
29 | if(tmp_Position == 0x01)
|
30 | {
|
31 |
|
32 |
|
33 | usart_write_line((&AVR32_USART1),"Laenge\r\n");
|
34 | usart_putchar((&AVR32_USART1),tmp_UDR);
|
35 | Seite[tmp_ES].framelaenge = tmp_UDR;
|
36 |
|
37 | if(tmp_UDR > MAX_FRAME_LENGTH)
|
38 | {
|
39 | usart_write_line((&AVR32_USART1),"!max Laenge\r\n");
|
40 | frameError = TRUE;
|
41 | return;
|
42 | }
|
43 |
|
44 |
|
45 | //empfangenes Byte speichern
|
46 | Seite[tmp_ES].frame[tmp_Position] = tmp_UDR;
|
47 |
|
48 | //Position in der Bank erhöhen
|
49 | tmp_Position++;
|
50 | Seite[tmp_ES].position=tmp_Position;
|
51 |
|
52 | //Hier ist möglicherweise der Fehler versteckt, wenn man die Daten in einem Rutsch ankommen
|
53 | //Disable USART1 Empfangsroutine: usart1_int_handler()
|
54 | usart_write_line((&AVR32_USART1),"DMA active\r\n");
|
55 |
|
56 | (&AVR32_USART1)->idr = AVR32_USART_IDR_RXRDY_MASK;
|
57 |
|
58 | //DMA: Ziel und Quelle wählen
|
59 | pdca_channel_options_t PDCA_USART1_OPTIONS_RX;
|
60 | PDCA_USART1_OPTIONS_RX.pid = AVR32_PDCA_PID_USART1_RX; // Quelle
|
61 | PDCA_USART1_OPTIONS_RX.addr = &Seite[tmp_ES].frame[2]; // Zieladresse
|
62 | PDCA_USART1_OPTIONS_RX.size = (unsigned int)tmp_UDR-2;
|
63 | PDCA_USART1_OPTIONS_RX.transfer_size = PDCA_TRANSFER_SIZE_BYTE;
|
64 | PDCA_USART1_OPTIONS_RX.r_addr = 0; //ungenutzt
|
65 | PDCA_USART1_OPTIONS_RX.r_size = 0; //ungenutzt
|
66 |
|
67 | pdca_init_channel(1,&PDCA_USART1_OPTIONS_RX);
|
68 |
|
69 | //mit DMA Transfer beginnen
|
70 |
|
71 | pdca_enable(1);
|
72 | pdca_enable_interrupt_transfer_complete(1);
|
73 |
|
74 | }
|
Bei Transferende wieder auf Interrupt-Behandlung wechseln:
1 | __attribute__((__interrupt__)) static void pdca_recieve_complete(void)
|
2 | {
|
3 |
|
4 | usart_write_line((&AVR32_USART1),"DMA beendet\r\n");
|
5 |
|
6 | //PDCA: Kanal&Interrupt deaktivieren
|
7 | pdca_disable_interrupt_transfer_complete(1);
|
8 | pdca_disable(1);
|
9 |
|
10 | //USART1_RX Int einschalten
|
11 | (&AVR32_USART1)->ier = AVR32_USART_IER_RXRDY_MASK;
|
12 |
|
13 | //Bankwechsel
|
14 | Seite[EmpfangsSeite].status = AUSWERTEN;
|
15 |
|
16 | //leere Bank suchen
|
17 | unsigned char i = 0;
|
18 | for(; i<MAXSEITEN; i++)
|
19 | {
|
20 | if(Seite[i].status == UNBENUTZT)
|
21 | {
|
22 | EmpfangsSeite = i;
|
23 | Seite[i].status = EMPFANGEN;
|
24 | usart_write_line((&AVR32_USART1),"Neue Seite");
|
25 |
|
26 | usart_putchar((&AVR32_USART1), EmpfangsSeite);
|
27 |
|
28 | return;
|
29 | }
|
30 | }
|
31 |
|
32 | // wird nur bei nicht-vorzeitigem verlassen ausgeführt
|
33 |
|
34 | usart_write_line((&AVR32_USART1),"!Bank");
|
35 | pageError = TRUE;
|
36 | frameError = TRUE;
|
37 | }
|