Hi all.
I am using a Tiva Launchpad EK-TM4C123GXL.and was trying to get console activity on UART0 and UART1. I haven't done anything with UART 1 yet so I don't know if the same problem will occur on that UART also. If its important then you can know that the part is configured to operate at 80MHz.
What I did was take the uartstdio.c file and hack it by essentially duplicating all the functions and making them uart specific (one for UART0 and the other set for UART1). The code is identical and I haven't change the functionality. The problem I am experiencing also occurs if I just attach UART0 to the <unmodified> uartstdio.c directly and not use my modified variant.
UART0 is in fact working fine - it transmits characters [if you can get them into the buffer] and echoes received characters without any problems (since this is done from within the ISR). This functionality distracted me from the true source of the problem since I thought that the UART interrupt was working fine.
In the application ADC0 interrupts and SYSTick interrupts are enabled and working perfectly. I have a UART0printf() call every 1 second from within the SYSTick ISR which prints out ADC and time information and it scrolls up the console screen perfectly. However what does seem to happen is after whatever is in the initial transmit buffer is sent out the serial port (transmitted) the interrupt is repeatedly called. I have put GPIO toggles around the entry and exit of the UART0 handler and it runs for about 900ns then is back 700ns later [except when there is something to transmit or so...] I have copied the UARTStatus register value to an external location and printed that value out. When masked the status register is 0x0000, and the unmasked value is 0x000F indicating that the modem control signals need attention (but the UART is working without any handshaking).
Whatever is happening out of interrupt service land can occur up until the end of whatever is first sent, thereafter only interrupt service land exists and I can't do anything useful. If anyone can suggest how normal service might be resumed, I would be very grateful.
So, the configuration is like this :
-----
// Enable the peripherals used
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
// UART0 is on peripheral A
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// Set GPIO A0 and A1 as UART pins.
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART (GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
/* console on UART0 */
UART0StdioConfig();
---------------------
The further configuration
---------------------
void UART0StdioConfig(void) {
/* Enable the UART peripheral for use */
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
/* Configure the UART for 115200, 8N1 */
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE | UART_CONFIG_WLEN_8));
/* Set the UART to interrupt * - whenever the TX FIFO is almost empty * - whenever any character is received */
UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);
// UARTFlowControlSet(UART0_BASE, UART_FLOWCONTROL_NONE);
UARTIntClear(UART0_BASE, UARTIntStatus(UART0_BASE, false));
/* Flush both the buffers */
UART0FlushRx();
UART0FlushTx(true);
/* enable interrrupts */
UARTIntDisable (UART0_BASE, 0xFFFFFFFF);
UARTIntEnable (UART0_BASE, UART_INT_RX | UART_INT_RT);
IntEnable (INT_UART0);
/* enable the UART */
UARTEnable (UART0_BASE);
}
----------------------------------------------
And the ISR
-------------------------------------------------
void UART0intHandler(void) {
unsigned long interrupts;
char data;
unsigned long value;
static bool lastCR = false;
/* Get and clear the current interrupt source(s) */
interrupts = UARTIntStatus(UART0_BASE, true);
temporary = UARTIntStatus(UART0_BASE, false);
UARTIntClear(UART0_BASE, interrupts);
/* Handle transmit FIFO draining */
if (interrupts & UART_INT_TX) {
/* fill it up */
UART0Tx();
/* turn off the transmit interrupt? */
if (TX0_BUFFER_EMPTY)
UARTIntDisable(UART0_BASE, UART_INT_TX);
}
/* Handle receive interrupts */
if (interrupts & (UART_INT_RX | UART_INT_RT)) {
/* transfer to the buffer */
while (UARTCharsAvail(UART0_BASE)) {
value = UARTCharGetNonBlocking(UART0_BASE);
data = (char)(value & 0xFF);
/* convert "\r\n" to "\r" only */
if((data == '\n') && lastCR) { lastCR = false; continue; }
/* make '\n' the only line terminator */
if ((data == '\r') || (data == '\n') || (data == 0x1B)) {
/* isolated CR was received */
if (data == '\r')
lastCR = true;
data = '\n';
}
/* handling echoes */
if (!DisableEcho0) {
if (data == '\b') {
/* delete the last character */
if (!RX0_BUFFER_EMPTY) {
// Rub out the previous character on the users
// terminal.
UART0write("\b \b", 3);
/* strip the character */
if (UART0RxWriteIndex == 0) {
UART0RxWriteIndex = UART_RX_BUFFER_SIZE - 1;
} else {
UART0RxWriteIndex--;
}
}
/* read the next character */
continue;
}
}
/* buffer the character or throw it away */
if (!RX0_BUFFER_FULL) {
UART0RxBuffer[UART0RxWriteIndex] = data;
RX_BUFFER_ADVANCE(UART0RxWriteIndex);
/* echo the character to the transmit buffer */
if (!DisableEcho0)
UART0write(&data, 1);
}
}
}
}