LPC4078 USART1 LSR THRE Timing

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC4078 USART1 LSR THRE Timing

1,093 Views
kenatmicrolynx
Contributor I

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

Labels (2)
0 Kudos
4 Replies

1,087 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

 

 

 

xiangjun_rong_0-1646720864509.png

 

0 Kudos

1,078 Views
kenatmicrolynx
Contributor I

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

0 Kudos

1,067 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

0 Kudos

1,059 Views
kenatmicrolynx
Contributor I

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

0 Kudos