Uart interrupt issue in LPC546

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

Uart interrupt issue in LPC546

3,036 Views
prasannanaik
Contributor III

Hi,

   I am using LPC54608J512BD208 microcontroller in a feeder protection relay.

   Relay has RS485 communication. I have used ISO3082DWR IC for uart to RS485 conversion.

   I am able to receive the data correctly but when i am trying to send the data through RS485, i am getting uart transfer completion interrupt before even 1st byte is transferred.

   While going through data sheet i have found that tx data is written to FIFOWR buffer and later it shifts the daata through shift register. Because of this even when the data is still in FIFOWR buffer, i am getting tx complete interrupt.

   I wanted to transfer 7 bytes but i got the transfer completion interrupt even before the first byte was actually transmitted by the controller.

   I have attached screenshot of the signals observed on oscillscope. Yellow signal indicates the nre_de line which is made low after interrupt of complete data transfer. Pink line indicates the TX data.

I am using uart in non blocking transfer mode. I have attached the reference uart files as well.

Beacuse of premataure interrupt, i am not able to control the ISO3082DWR  IC in TX mode. I want uart interrupt when actual data is sent out from the TX pin. Please help in aceiving this.

gauravmore

Thanks and best regards,

Prasanna

Labels (1)
0 Kudos
5 Replies

2,479 Views
k_sunilgupta
Contributor II

hey everyone,

i am doing programing on LPC546 to config USART in POLLING MODE but not happing, actually i am doing register level programing, is there anyone who can help on this.

0 Kudos

2,834 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Prasanna,

I see your trouble. The void USART_RS485_Callback(USART_Type *base, usart_handle_t *handle, status_t status, void *userData) is called after all the transferred data has written to transmitter FIFO, but FIFO has not completed it's transfer, I you change the direction of RS485 at the time, there s issue.

I suppose that you have to modify the ISR of uart. This is what I tried to modify, but I have not tested yet, pls have a try.

BR

XiangJun Rong

#define UART1_STAT_TXIDLE 0x08
#define UART1_FIFOSTAT_TXEMPTY 0x10
void USART_TransferHandleIRQ(USART_Type *base, usart_handle_t *handle)
{
    /* Check arguments */
    assert((NULL != base) && (NULL != handle));

    bool receiveEnabled = (handle->rxDataSize) || (handle->rxRingBuffer);
    bool sendEnabled    = handle->txDataSize;

    /* If RX overrun. */
    if (base->FIFOSTAT & USART_FIFOSTAT_RXERR_MASK)
    {
        /* Clear rx error state. */
        base->FIFOSTAT |= USART_FIFOSTAT_RXERR_MASK;
        /* clear rxFIFO */
        base->FIFOCFG |= USART_FIFOCFG_EMPTYRX_MASK;
        /* Trigger callback. */
        if (handle->callback)
        {
            handle->callback(base, handle, kStatus_USART_RxError, handle->userData);
        }
    }
    while ((receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK)) ||
           (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK)))
    {
        /* Receive data */
        if (receiveEnabled && (base->FIFOSTAT & USART_FIFOSTAT_RXNOTEMPTY_MASK))
        {
            /* Receive to app bufffer if app buffer is present */
            if (handle->rxDataSize)
            {
                *handle->rxData = base->FIFORD;
                handle->rxDataSize--;
                handle->rxData++;
                receiveEnabled = ((handle->rxDataSize != 0) || (handle->rxRingBuffer));
                if (!handle->rxDataSize)
                {
                    if (!handle->rxRingBuffer)
                    {
                        base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
                    }
                    handle->rxState = kUSART_RxIdle;
                    if (handle->callback)
                    {
                        handle->callback(base, handle, kStatus_USART_RxIdle, handle->userData);
                    }
                }
            }
            /* Otherwise receive to ring buffer if ring buffer is present */
            else
            {
                if (handle->rxRingBuffer)
                {
                    /* If RX ring buffer is full, trigger callback to notify over run. */
                    if (USART_TransferIsRxRingBufferFull(handle))
                    {
                        if (handle->callback)
                        {
                            handle->callback(base, handle, kStatus_USART_RxRingBufferOverrun, handle->userData);
                        }
                    }
                    /* If ring buffer is still full after callback function, the oldest data is overridden. */
                    if (USART_TransferIsRxRingBufferFull(handle))
                    {
                        /* Increase handle->rxRingBufferTail to make room for new data. */
                        if (handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
                        {
                            handle->rxRingBufferTail = 0U;
                        }
                        else
                        {
                            handle->rxRingBufferTail++;
                        }
                    }
                    /* Read data. */
                    handle->rxRingBuffer[handle->rxRingBufferHead] = base->FIFORD;
                    /* Increase handle->rxRingBufferHead. */
                    if (handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
                    {
                        handle->rxRingBufferHead = 0U;
                    }
                    else
                    {
                        handle->rxRingBufferHead++;
                    }
                }
            }
        }
        /* Send data */
        if (sendEnabled && (base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK))
        {
            base->FIFOWR = *handle->txData;
            handle->txDataSize--;
            handle->txData++;
            sendEnabled = handle->txDataSize != 0;
            if (!sendEnabled)
            {
                base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
                //////////////////////////////////////////////////////////////////////////
                //block the transfer, Rong modified
                while((base->FIFOSTAT&UART1_FIFOSTAT_TXEMPTY)&&(base->STAT&UART1_STAT_TXIDLE)) {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
                handle->txState    = kUSART_TxIdle;
                if (handle->callback)
                {
                    handle->callback(base, handle, kStatus_USART_TxIdle, handle->userData);
                }
            }
        }
    }

    /* ring buffer is not used */
    if (NULL == handle->rxRingBuffer)
    {
        /* restore if rx transfer ends and rxLevel is different from default value */
        if ((handle->rxDataSize == 0) && (USART_FIFOTRIG_RXLVL_GET(base) != handle->rxWatermark))
        {
            base->FIFOTRIG =
                (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | USART_FIFOTRIG_RXLVL(handle->rxWatermark);
        }
        /* decrease level if rx transfer is bellow */
        if ((handle->rxDataSize != 0) && (handle->rxDataSize < (USART_FIFOTRIG_RXLVL_GET(base) + 1)))
        {
            base->FIFOTRIG =
                (base->FIFOTRIG & (~USART_FIFOTRIG_RXLVL_MASK)) | (USART_FIFOTRIG_RXLVL(handle->rxDataSize - 1));
        }
    }
}

0 Kudos

2,834 Views
prasannanaik
Contributor III

Hi Xiangjun,

   This is a polling method which will lead to inefficient use of processor. I don't want to use blocking or polling method.

If I want to transfer say 7 bytes then controller should raise an interrupt when 6 bytes has been transferred through shift register and the 7th byte is still in the shift register. The last byte transfer can be handled through external delay in firmware. But I am not able to achieve this feature. As I explained my controller is giving interrupt even before 1 byte has been transmitted through shift register. I have attached status of FIFOTRIG register in this reply.

 Please help.

Thanks & best regards,

Prasanna

0 Kudos

2,834 Views
carstengroen
Senior Contributor II

Prasanna,

I would also not do the polling method described above, you are wasting valuable CPU cycles that way.

I normally start a MRT timer for this, when interrupt fires for the specific MRT timer I change direction on the RS485 transceiver.

0 Kudos

2,834 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Prasanna,

When all the bytes you want to transfer have been written to transmitter FIFO, but the FIFO has not completed it's transfer, so I add the following code:

  //block the transfer, Rong modified
                while((base->FIFOSTAT&UART1_FIFOSTAT_TXEMPTY)&&(base->STAT&UART1_STAT_TXIDLE)) {}

I do not think it is a polling mode, but I think it is required to wait that the FIFO is empty.

If you add a fixed time delay to solve the issue, it is okay.

I have not the other idea.

BR

XiangJun Rong

0 Kudos