Forum: Mikrocontroller und Digitale Elektronik [ARM] Tiva C Launchpad UART Interrupt Probleme


von Tobias S. (ucfreak)


Lesenswert?

Ich habe mir mal einiges zurecht programmiert um die UART interrupt 
gesteuert zu nutzen.

Das funktionierte auch schon alles. Nur heute will es nur noch halb 
funktionieren.

Jedes Mal wenn ich ein Zeichen über die UART bekomme, sende ich die 
Temperatur des Temperatursensor per UART wieder zurück.

Der Receive-Interrupt kommt auch wunderbar, nur der Sendeinterrupt kommt 
mal gar nicht :(

Mein gesamter UART-Code sieht so aus:
1
void
2
Uart_Init(void)
3
{
4
  // enable UART and GPIO port A
5
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
6
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
7
  // init FIFOs
8
  FifoQueue_Init(&g_sUartRxFifo,UART_RX_FIFO_SIZE);
9
  FifoQueue_Init(&g_sUartTxFifo,UART_TX_FIFO_SIZE);
10
  // set GPIO ports
11
  GPIOPinConfigure(GPIO_PA0_U0RX);
12
  GPIOPinConfigure(GPIO_PA1_U0TX);
13
  GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0 | GPIO_PIN_1);
14
  // disable UART
15
//  UARTDisable(UART0_BASE);
16
  // set UART clock
17
  UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),115200,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
18
  // disable FIFOs
19
  UARTFIFODisable(UART0_BASE);
20
  // enable RX and disable TX interrupt
21
  IntEnable(INT_UART0);
22
  UARTIntEnable(UART0_BASE,UART_INT_RX);
23
  UARTIntDisable(UART0_BASE,UART_INT_TX);
24
  // enable UART
25
//  UARTEnable(UART0_BASE);
26
}
27
28
void
29
Uart0_Isr(void)
30
{
31
  uint32_t status;
32
  // get status
33
  status = UARTIntStatus(UART0_BASE,true);
34
  // clear status
35
  UARTIntClear(UART0_BASE,status);
36
  // RX interrupt?
37
  if(status & UART_INT_RX)
38
  {
39
    while(UARTCharsAvail(UART0_BASE)) //loop while there are chars
40
    {
41
      char chr = UARTCharGetNonBlocking(UART0_BASE);
42
      // push character into fifo queue
43
      FifoQueue_Push(&g_sUartRxFifo,chr);
44
    }
45
  }
46
  // TX interrupt?
47
  if(status & UART_INT_TX)
48
  {
49
    while(FifoQueue_ItemAvailable(&g_sUartTxFifo) && UARTSpaceAvail(UART0_BASE))
50
    {
51
      char chr;
52
      // pop character from fifo and put it into the UART fifo
53
      FifoQueue_Pop(&g_sUartTxFifo,(uint8_t*)&chr);
54
      UARTCharPutNonBlocking(UART0_BASE,chr);
55
    }
56
    // check if we need another interrupt
57
    if(!FifoQueue_ItemAvailable(&g_sUartTxFifo))
58
    {
59
      // disable UART TX interrupt
60
      UARTIntDisable(UART0_BASE,UART_INT_TX);
61
    }
62
63
    g_sUartTxIntOccured = true;
64
  }
65
}
66
67
void
68
Uart0_SendBuffer(char*    buffer,
69
         uint16_t size)
70
{
71
  uint16_t pos = 0;
72
  // go through the buffer
73
  while(pos < size)
74
  {
75
    // disable TX interrupt
76
    UARTIntDisable(UART0_BASE,UART_INT_TX);
77
    // if the FIFO is full, we need to wait
78
    if(FifoQueue_IsFull(&g_sUartTxFifo))
79
    {
80
      g_sUartTxIntOccured = false;
81
      // enable interrupts
82
      UARTIntEnable(UART0_BASE,UART_INT_TX);
83
      // wait for interrupt
84
      while(!g_sUartTxIntOccured)
85
      {
86
        ;
87
      }
88
      // disable interrupts
89
      UARTIntDisable(UART0_BASE,UART_INT_TX);
90
    }
91
    // push characters into the FIFO
92
    while(pos < size && !FifoQueue_IsFull(&g_sUartTxFifo))
93
    {
94
      FifoQueue_Push(&g_sUartTxFifo,buffer[pos++]);
95
    }
96
    // enable interrupts
97
    UARTIntEnable(UART0_BASE,UART_INT_TX);
98
  }
99
}
100
101
bool
102
Uart0_CharAvailable(void)
103
{
104
  return (g_sUartRxFifo.header.numItems > 0);
105
}
106
107
char
108
Uart0_GetChar(void)
109
{
110
  char chr = 0;
111
  // disable interrupts
112
  UARTIntDisable(UART0_BASE,UART_INT_RX);
113
  // get character
114
  if(g_sUartRxFifo.header.numItems > 0)
115
  {
116
    FifoQueue_Pop(&g_sUartRxFifo,(uint8_t*)&chr);
117
  }
118
  // enable interrupts
119
  UARTIntEnable(UART0_BASE,UART_INT_RX);
120
121
  return chr;
122
}

Wie gesagt, ich bekomme im Moment nicht den TX Interrupt (RX kommt) 
obwohl ich diesen bei jedem Senden anmache.

Hat einer eine Idee was schief läuft oder wo ich noch einen Denkfehler 
habe?

von Tobias S. (ucfreak)


Lesenswert?

Ich habe das Problem jetzt gelöst indem ich die FIFOs vollständig nutze 
und mir nach deren Stand einen Interrupt geben lasse.

Keine Ahnung warum es ohne die Benutzung der FIFOs nicht funktioniert.

von Bernd N (Gast)


Lesenswert?

TIVA C oder LM4F120 sollten da ziemlich gleich funktionieren. Ich denke 
dein Code ist aus den TI Beispielen zusammen kopiert ? Das es 
funktioniert ist ja gut aber verstehst du auch warum ?

Du kannst das Ganze zu folgendem Code zusammendampfen:
1
#include "inc/hw_ints.h"
2
#include "inc/hw_memmap.h"
3
#include "inc/hw_types.h"
4
#include "driverlib/gpio.h"
5
#include "driverlib/interrupt.h"
6
#include "driverlib/rom.h"
7
#include "driverlib/sysctl.h"
8
#include "driverlib/uart.h"
9
10
11
// System Clock initialisieren
12
void SysClockInit (void)
13
{
14
    ROM_SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);   // 16 MHz Quarz
15
}
16
17
// UART initialisieren
18
void UartInit (void)
19
{
20
    ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_UART0);
21
    ROM_SysCtlPeripheralEnable (SYSCTL_PERIPH_GPIOA);
22
23
    ROM_GPIOPinConfigure (GPIO_PA0_U0RX);                                                          // GPIO A0, A1 as UART pins
24
    ROM_GPIOPinConfigure (GPIO_PA1_U0TX);
25
    ROM_GPIOPinTypeUART (GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
26
27
    ROM_UARTConfigSetExpClk (UART0_BASE, ROM_SysCtlClockGet(), 115200,                             // 115200 Baud, 8-N-1
28
                             (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
29
30
    ROM_IntEnable (INT_UART0);                                                                     // Enable UART interrupt
31
    ROM_UARTIntEnable (UART0_BASE, UART_INT_RX | UART_INT_RT);
32
}
33
34
// UART ISR
35
void UARTIntHandler (void)
36
{
37
    unsigned long ulStatus;
38
39
    ulStatus = ROM_UARTIntStatus (UART0_BASE, true);                                               // check if ISR is triggered
40
    ROM_UARTIntClear (UART0_BASE, ulStatus);                                                       // clear interrupt
41
42
    while (ROM_UARTCharsAvail (UART0_BASE)) {                                                      // read FIFO receive Buffer
43
        ROM_UARTCharPut (UART0_BASE, ROM_UARTCharGet (UART0_BASE));                                // echo received char.
44
    }
45
}
46
47
// simple printf
48
void printfEasy (const char *s)
49
{
50
    while (*s) UARTCharPut (UART0_BASE, (*s++));
51
}
52
53
void main (void)
54
{
55
    SysClockInit ();
56
    UartInit ();
57
    ROM_IntMasterEnable ();                                                                        // enable Interrupts
58
59
    printfEasy ("Hello World, Enter a text:\n\r");
60
61
    while (1) {
62
    }
63
}

von Tobias S. (ucfreak)


Lesenswert?

Jap, mein Code ist ein Mix aus Beispielen und eigenem. Ich weiß warum er 
funktioniert, was ich nicht weiß, wieso der ursprüngliche Code nicht 
funktioniert ;)

Allerdings ist mir das jetzt auch egal. Hauptsache es läuft und ich weiß 
warum.

Ich weiß aber nicht was du mir mit deinem Code sagen willst!?

von Bernd N (Gast)


Lesenswert?

Ich will dir sagen das es auch ohne Fifo geht.

von Tobias S. (ucfreak)


Lesenswert?

Ich weiß das es auch ohne FIFO geht, aber ich bekomme dann nicht den 
TX-Interrupt!

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.