[AT91SAM] IRQ-getriebener DMA-Transfer auf UART führt zu Absturz

Gast #2519487
Lesenswert?

Hallo Mikros!

UART 1-Kanal ist per DMA angebunden zum Empfangen (RX) und Senden (TX) 
zum PC-Terminalprogramm (Baudrate 57600).

Beim Empfang eines Bytes wird dieses verarbeitet und sofort 
zurückgesandt (echo). Das Verarbeiten ist sehr fix und wird innerhalb 
der IRQ-Routine erledigt, die vom beendeten DMA-Transfer ausgelöst wird. 
(siehe UART1_irqHandler()).

Versuche ich nun, das eben empfangene Byte zurückzusenden 
(UART1_sendCharacter()), scheint irgendwas im Mikro schief zu laufen 
(sieht so aus, als ob ein Reset folgt ... bin mir unsicher). Auf jeden 
Fall reagiert danach der UART 1 nicht mehr (und einige andere Dinge auch 
nicht).

Vermutung:
Aus einer Interrupt-Routine (RX-Zweig) wird Senden ausgeführt, welches 
so fix fertig ist, dass noch während des Sendens ein weiterer Interrupt 
ausgelöst wird (TX).

Kann mit jmd bei der Deutung ein paar Tipps geben?

Danke fürs Lesen,
Paule

PS: Hier der Code-Schnippsel.
1
/** Connection baud rate. */
2
#define    BAUDRATE    57600
3

4
/** Debug input (RX) buffer. */
5
char    inBuffer[4];
6
/** Debug output (TX) buffer. */
7
char    outBuffer[128];
8

9
/**
10
 * Sends a single character to device connected on UART 1.
11
 *
12
 * Blocks, if sending of previous buffer is in progress.
13
 *
14
 * @param[in]  character    single character to send
15
 */
16
void     UART1_sendCharacter(
17
    const char      character){
18

19
  /* wait until former communication ends */
20
  USART1_waitForEndTx();
21

22
  /* make local copy of value */
23
  outBuffer[0] = character;
24

25
  AT91C_BASE_US1->US_TCR  = 1;
26
  AT91C_BASE_US1->US_PTCR = AT91C_PDC_TXTEN;
27
}
28

29
/**
30
 * IRQ handler for incoming (RX) and outgoing (TX) UART 1 communication.
31
 *
32
 * Incoming signals are sent byte-wise to user command unit.
33
 */
34
void    UART1_irqHandler() {
35

36
  if ((AT91C_BASE_US1->US_CSR & AT91C_US_ENDRX) == AT91C_US_ENDRX) {      /* reception done interrupt (ENDRX) */
37

38
    AT91C_BASE_US1->US_RCR = 1;            /* restore the receive count - clears ENDRX flag */
39
    AT91C_BASE_US1->US_RPR = (AT91_REG)inBuffer;  /* address of DMA input buffer */
40

41
    USERCMD_addCharacterToCommand(inBuffer[0]);    /* try to add character to user command input buffer */
42
    
43
    UART1_sendCharacter(inBuffer[0]);        // <<<<<---- crashes
44
    
45

46
  } else if ((AT91C_BASE_US1->US_CSR & AT91C_US_ENDTX) == AT91C_US_ENDTX) {  /* transmission done interrupt (ENDTX) */
47

48
    AT91C_BASE_US1->US_PTCR = AT91C_PDC_TXTDIS;
49
    AT91C_BASE_US1->US_TCR = 1;            /* restore the transmit count - clears ENDTX flag */
50
    AT91C_BASE_US1->US_TPR = (AT91_REG)outBuffer;  /* address of DMA output buffer */
51

52
  }
53
}
Gast #2520613
Lesenswert?

Hallo,

ich denke da fehlt noch was in der UART1_sendCharacter. Vorschlag:

AT91C_BASE_US1->US_TCR  = 1;
AT91C_BASE_US1->US_TPR  = (AT91_REG)outBuffer;
AT91C_BASE_US1->US_PTCR = AT91C_PDC_TXTEN;

Damit wäre die DMA Adresse des Buffers nicht mehr NULL wenn zum ersten 
mal zurück gesendet werden soll und noch kein TX-Ready IRQ kam.

Gruß Micoman

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