Other Parts Discussed in Thread: EK-TM4C129EXL,
We are running a TM4C129ENCPDT on a EK-TM4C129EXL and trying to send and receive characters between the board and a PC running PuTTY.
We are using the board's ICDI virtual UART, the jumpers are set correctly, and the TivaWare example program at C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c129exl\uart_echo is working perfectly. That program does not use interrupts. It just runs in a loop, reads a character from the receiver when one becomes available and writes it back to the transmitter.
Now we want to use our interrupt based code. The receive interrupt is working perfectly. The transmit interrupt is never triggered. Consequently characters are received and processed correctly but characters are never transmitted.
If we take our transmit code out of the interrupt handler and stick it in the main loop of the program, then the program works as expected with interrupt handling of receives but polled handling of transmitting. We need transmitting to be interrupt based as well. Not only that, but because we are not transmitting all the time, only in bursts, we need to enable the transmit interrupt as soon as anything is placed into our software buffer and we need to disable it when our software buffer becomes empty. But right now we're just telling it to always be enabled just to get it working.
We have tried UARTFIFOEnable() and UARTFIFOLevelSet() with various watermark levels but that makes no difference. We have tried UARTFIFODisable() but that doesn't help either.
This is the initialization code:
void SetupUart0(void)
{
Global.SysClockFreqHz = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), SYSTEM_CLOCK_FREQ_HZ);
SysCtlPeripheralEnable(GPIO_PORTA_BASE);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
while (SysCtlPeripheralReady(SYSCTL_PERIPH_UART0) != true)
{
}
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, Global.SysClockFreqHz, 115200, (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE | UART_CONFIG_WLEN_8));
// Set UART to interrupt when Tx FIFO is almost empty or any char received
//UARTFIFOEnable(UART0_BASE);
//UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
IntEnable(INT_UART0);
UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT | UART_INT_TX);
}
The commented code is left over from trying different things with the FIFO.
This is the interrupt handler:
void Uart0InterruptHandler(void)
{
uint32_t InterruptFlags;
InterruptFlags = UARTIntStatus(UART0_BASE, false);
UARTIntClear(UART0_BASE, InterruptFlags);
if (InterruptFlags & UART_INT_TX)
{
// Room in Tx FIFO
while (UARTSpaceAvail(UART0_BASE))
{
UARTCharPutNonBlocking(UART0_BASE, BufGet(&Tx));
}
}
if (InterruptFlags & (UART_INT_RX | UART_INT_RT))
{
// Data in Rx FIFO
while (UARTCharsAvail(UART0_BASE))
{
BufPut(&Rx, UARTCharGetNonBlocking(UART0_BASE));
}
}
}
As I said, removing the while loop with UARTSpaceAvail() and UARTCharPutNonBlocking() from the interrupt handler and putting it in the main loop makes the code work, but then transmit is polled, not interrupt based.
This is what the registers contain after initialization:
