With USART1, how long does the LSR THRE bit take to update after writing to the THR? I ask because the UART is supposed to have a 16-byte deep transmit FIFO, but what I'm seeing is that after writing a single byte to the THR, the LSR THRE bit goes to zero indicating I can't write anymore bytes. There about about a dozen assembly instructions between the point where the THR is written and the LSR THRE bit is (re)examined, so there is plenty of time for the THRE bit to get updated.
The documentation for the UART timing is woefully inadequate. Can anyone shed some light on this matter?
My CCLK is running at 100 MHz, PCLK is at 50 MHz, UART in async mode, 8N1, running at 57600 bits per sec.
Thanks in advance,
KM
Hi, Ken,
Regarding your question, I suppose that you do not enable the FIFO module. If you do not enable the FIFO, after the data has been transmitted via the USART_TX pin completely, the LSR THRE bit goes to 1, which means you can write another character.
If you enable the FIFO, after the data has been transmitted to transmitter FIFO, the LSR THRE bit goes to 1, which means you can write another character.
Pls try to enable FIFO and have a test.
Hope it can help you
BR
XiangJun Rong
Hi
Thank you for your prompt reply. I can confirm I enable the FIFOs in our UART init code. Here is the code (pardon the formatting, I didn't have time to wrestle with the email code formatter):
Chip_UART_Init( LPC_UART1 );
// Set word length to 8 bits, no parity, one stop.
Chip_UART_ConfigData( LPC_UART1, ( UART_LCR_WLEN8
| UART_LCR_PARITY_DIS | UART_LCR_SBS_1BIT ) );
// Set up GPIO pins for exclusive UART functionality.
// Full handshake :: Outputs -> TX, DTR, RTS.
// Inputs --> RX, DSR, CTS.
SetGPIOPinOutput( AC4490_TXD_Port, AC4490_TXD_Pin );
SetGPIOPinOutput( AC4490_DTR_Port, AC4490_DTR_Pin );
SetGPIOPinOutput( AC4490_RTS_Port, AC4490_RTS_Pin );
SetGPIOPinInput ( AC4490_RXD_Port, AC4490_RXD_Pin );
SetGPIOPinInput ( AC4490_DSR_Port, AC4490_DSR_Pin );
SetGPIOPinInput ( AC4490_CTS_Port, AC4490_CTS_Pin );
// Set pin alt funcs - give exclusive control of pins to UART
SetGPIOAltFunc( AC4490_TXD_Port, AC4490_TXD_Pin, ( IOCON_FUNC2
| IOCON_MODE_INACT ) );
SetGPIOAltFunc( AC4490_DTR_Port, AC4490_DTR_Pin, ( IOCON_FUNC2
| IOCON_MODE_INACT ) );
SetGPIOAltFunc( AC4490_RTS_Port, AC4490_RTS_Pin, ( IOCON_FUNC2
| IOCON_MODE_INACT ) );
SetGPIOAltFunc( AC4490_RXD_Port, AC4490_RXD_Pin, ( IOCON_FUNC2
| IOCON_MODE_INACT ) );
SetGPIOAltFunc( AC4490_CTS_Port, AC4490_CTS_Pin, ( IOCON_FUNC2
| IOCON_MODE_INACT ) );
// DCD and DSR are not used but can't be left floating
// add internal PU and make general GPIO.
SetGPIOAltFunc( AC4490_DSR_Port, AC4490_DSR_Pin, ( PIN_GPIO_MODE
| IOCON_MODE_PULLUP ) );
SetGPIOAltFunc( AC4490_DCD_Port, AC4490_DCD_Pin, ( PIN_GPIO_MODE
| IOCON_MODE_PULLUP ) );
// RTS function: enable auto-RTS mode.
Chip_UART_SetModemControl( LPC_UART1, UART_MCR_AUTO_RTS_EN );
// Enable CTS flow control
Chip_UART_SetModemControl( LPC_UART1, UART_MCR_AUTO_CTS_EN );
// Set bit rate
Chip_UART_SetBaud( LPC_UART1, 57600 );
// Set FIFO Rx Int level to 8 bytes. Issue a FIFO reset first
Chip_UART_SetupFIFOS( LPC_UART1, ( UART_FCR_FIFO_EN
| UART_FCR_RX_RS | UART_FCR_TX_RS ) );
Chip_UART_SetupFIFOS( LPC_UART1, ( UART_FCR_FIFO_EN
| UART_FCR_TRG_LEV2 ) );
// Can now enable the UART TX
Chip_UART_TXEnable( LPC_UART1 );
// Enable UART ints on NVIC
NVIC_SetPriority( UART1_IRQn, LPC_UART1_IRQ_LEVEL );
NVIC_EnableIRQ( UART1_IRQn );
Here is transmit loop from my send data method. I can confirm that only a single byte gets written in the while( wNextByte... ) loop (the buffer being sent contains 4 bytes) and I know that the Tx FIFO is empty at that point because this is the first send data operation.
// First, stuff as many bytes as we can in the Tx FIFO
WORD wNextByte = 0;
while( wNextByte < wLength )
{
// Have data to send. If the FIFO is full, break out
if( ( Chip_UART_ReadLineStatus( LPC_UART1) & UART_LSR_THRE ) == 0 )
break;
// FIFO has room - feed it with data
Chip_UART_SendByte( LPC_UART1, pBuffer[wNextByte] );
// Increment read index
wNextByte++;
}
// If we still have bytes to send, set up the data block
if( wNextByte < wLength )
{
// Enable Tx buffer ints now. A THRE interrupt will occur as soon as
// there is space in the Tx FIFO for a byte to send.
Chip_UART_IntEnable( LPC_UART1, UART_IER_THREINT );
}
My UART1 ISR does something similar if the Interrupt ID register reports a INT_ID_THR condition: it loops writing bytes to the THR while the LSR THRE bit is high. Only one byte ever gets written per interrupt though.
Any guidance you can provide would be helpful.
Thank you,
KM
Hi
How about using the following code:
while( wNextByte < wLength )
{
// Have data to send. If the FIFO is full, break out
while(! Chip_UART_ReadLineStatus( LPC_UART1) & UART_LSR_THRE )) {}
/*while(! Chip_UART_ReadLineStatus( LPC_UART1) & UART_LSR_TEMT )) {}*/
// FIFO has room - feed it with data
Chip_UART_SendByte( LPC_UART1, pBuffer[wNextByte] );
// Increment read index
wNextByte++;
}
pls have a try
BR
XiangJun Rong
Thanks for the suggestion XiangJun, but unfortunately that turns my send procedure into a blocking call.
Because the protocol over the UART is like an "enquire/ack" type, I've opted to check the status of the UART_LSR_THRE bit in my send routine and if THRE is set then I fill the FIFO with up to 16 bytes of data. In my ISR, I just send one byte per interrupt, which is suboptimal, but I can live with that.
KM