RT685 USART Driver

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

RT685 USART Driver

265 Views
jwprice100
Contributor I

I'm using a RT685 with the FreeRTOS USART driver provided in the SDK. The driver seems to work most of the time. However I end up somehow getting into a weird state after an indeterminate period of time.  It seems the base USART driver's IRQ Handler is called repeatedly over and over again. Digging into the reason it seems the tx level FIFO interrupt is firing. However there is no data to send. 

Digging into the code I find:

 /* Send data */
        if (sendEnabled && ((base->FIFOSTAT & USART_FIFOSTAT_TXNOTFULL_MASK) != 0U))
        {
            base->FIFOWR = *handle->txData;
            handle->txDataSize--;
            handle->txData++;
            sendEnabled = handle->txDataSize != 0U;
            if (!sendEnabled)
            {
                base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;

                base->INTENSET = USART_INTENSET_TXIDLEEN_MASK;
            }
        }

When tx data runs out it clearly disabled that interrupt. Yet I find from a breakpoint that txDataSize is zero! So it's like it ran out of data without executing the code path that would disable tx lvl interrupts.

To confirm I added the following code:

    if (!sendEnabled && (base->FIFOINTENSET & USART_FIFOINTENCLR_TXLVL_MASK) )
    {
        base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
        base->INTENSET = USART_INTENSET_TXIDLEEN_MASK;
    }

This code does indeed fire. This seems impossible! Can anyone shed any light?

Thanks!

0 Kudos
Reply
4 Replies

199 Views
jwprice100
Contributor I

The issue does appear to be that when two writes to the FIFOINTENCLR register that are spaced closely in time, the second write may not work. I've confirmed via debugging that the register was written but did not clear. My solution is as follows:

In the USART_TransferHandleIRQ function replace:

base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;

with 

while((base->FIFOINTENSET & USART_FIFOINTENCLR_TXLVL_MASK) || (base->FIFOINTENSET & USART_FIFOINTENCLR_TXLVL_MASK))
{
  base->FIFOINTENCLR = USART_FIFOINTENCLR_RXLVL_MASK | USART_FIFOINTENSET_RXERR_MASK;
 }

 

and replace 

base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;

 

with

//This is necesary in case the previous loop iteration just wrote it or the receive logic just wrote it.
while(base->FIFOINTENSET & USART_FIFOINTENCLR_TXLVL_MASK)
{
  base->FIFOINTENCLR = USART_FIFOINTENCLR_TXLVL_MASK;
}

 

Hopefully this helps anyone else encountering this issue.

0 Kudos
Reply

170 Views
jwprice100
Contributor I

This wasn't the source of the problem afterall. I just got really lucky and ran for many hours without getting stuck in the ISR. I think I know the real problem/solution, I'll report that if I am right.

0 Kudos
Reply

108 Views
gusarambula
NXP TechSupport
NXP TechSupport

Hello @jwprice100 ,

Did you find the root cause of this problem or are you still requiring support on this matter?

If you did find the root cause, we would appreciate it if you would please share it so that it may benefit other community members.

Regards,
Gustavo

0 Kudos
Reply

220 Views
jwprice100
Contributor I

Does anyone know if writing to the FIFOINTENCLR register twice, very close in time together, would cause the second write to not take? That appears to be what's happening. 

0 Kudos
Reply