Forum: Mikrocontroller und Digitale Elektronik AVR32: USART Empfangproblem mit DMA/PDCA


von optimax (Gast)


Lesenswert?

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
}

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.