This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G3507: Noise on UART with observation of the IDDX STAT reading 0x00 observing that the code will vector to the UART IRQ handler with the event condition register empty (IIDX STAT reading 0x00).

Part Number: MSPM0G3507
Other Parts Discussed in Thread: MSPM0-SDK,

Tool/software:

TI Team,

Our customer has first observed noise on the MSPM0G UART that lead to an observation of the IDDX STAT reading 0x00 observing that the code occasionally will vector to the UART IRQ handler with the event condition register empty (IIDX STAT reading 0x00).  Seeing this roughly every several thousand characters.  We wonder what condition might cause this?  

Additional debug conversations has lead to this input directly from the customer:

"

I have collected some more information. First, I'd like to share some details about how we are handling received data, as it might be peculiar.

 

We are running this data bus at 10MBaud and using DMA to collect the received data in a buffer. We do not know how long each line on the data bus will be, so we are running DMA one byte at a time, and have the UART FIFO enabled:

Transfer size is configured at runtime to be the size of the receive buffer, so that we can let DMA handle data until our end of line characters are received. We send/receive two EOL characters at the end of every line.

 

Baud rate is also set at runtime.

 

To detect EOL, I am using the UART RXINT to trigger searching the buffer for the first EOL. It would certainly be better to perform this search after the DMA completes, but I did not see a good way to get an interrupt after the DMA is done with each individual character yet keep the DMA active in case the interrupt is handled late. This isn't a problem though, as with two EOLs, we can just search for the first, and missing/discarding the second EOL isn't a problem.

 

Upon further investigation, I noticed the UART interrupt handler only observes IIDX of 0 after a line is received. This happens every couple of lines and is after we have identified that first EOL.

 

 

I noticed the reference manual details two ways for RXINT to be cleared. The first, by reading IIDX as our interrupt handler does:

 

 

But this can also clear the interrupt, which the DMA will be doing often:

  

However, there is some timing I can't yet explain. I'd expect the DMA to often complete before our interrupt handler is called, causing the interrupt handler to see IIDX set to 0 most of the time, if not always. But I only observe IIDX set to zero in the interrupt handler at the end of a received line, and only at the end of every couple received lines.

 

When I modify the sender to wait roughly 2ms between sending each byte, IIDX is never observed as 0, even if a delay is added between the interrupt handler call and checking IIDX. Perhaps it is somehow related to interaction between the DMA and the FIFIO, when the FIFO contains more than one byte?

 

Here's a code snippet of the interrupt handler: (apologies for the formatting!)

 

void UART0_IRQHandler(void)

{

    SCIIntManager(isrSciStructHandlePtrs[SCI_UART_0]);

}

 

void UART1_IRQHandler(void)

{

    SCIIntManager(isrSciStructHandlePtrs[SCI_UART_1]);

}

 

void UART3_IRQHandler(void)

{

    SCIIntManager(isrSciStructHandlePtrs[SCI_UART_3]);

}

 

void SCIIntManager(sciStruct *handle)

{

    DL_GPIO_setPins(GPIO_TEST_POINTS_PORT, GPIO_TEST_POINTS_Rosc_PIN); // hooked up to logic analyzer so timing can be observed

    //delay_cycles(300); // uncommenting this in does not cause IIDX to be observed as 0 after every byte, even when bytes are sent 2ms apart.

    /* Assume the handle is valid if its register field pointer is mapped */

    if (handle != NULL && handle->uartReferences->registers != NULL)

    {

        /* Read the UART interrupt event condition, which is assigned as the active UART interrupt

           with the highest priority. Reading will cause it to clear. */

        switch (handle->uartReferences->registers->CPU_INT.IIDX & UART_CPU_INT_IIDX_STAT_MASK)

        {

            case 0:

                delay_cycles(10); // just so a breakpoint may be placed here.

                break;

            case UART_CPU_INT_IIDX_STAT_BEFG: // Break Error

                SCIBreakInt(handle);

                break;

            case UART_CPU_INT_IIDX_STAT_RXIFG:// Received byte

                SCIUartRxInt(handle);

                break;

            case UART_CPU_INT_IIDX_STAT_EOT:  // end of transmission

                SCIUartEndTransmitDMA(handle);

                break;

            case UART_CPU_INT_IIDX_STAT_OEFG: // overrun error

            case UART_CPU_INT_IIDX_STAT_FEFG: // framing error

            default:                          // just in case something else was configured...

                SCIErrorInt(handle);

                break;

        }

    }

    DL_GPIO_clearPins(GPIO_TEST_POINTS_PORT, GPIO_TEST_POINTS_Rosc_PIN);

}

 

 

SCIUartRxInt is what searches the receive buffer for the first EOL. Upon finding that EOL, it will disable DMA before indicating to other code the receive buffer is ready to be processed.

 

 Let me know if this brings about any further questions!

'

Your feedback welcomed.

TY,

Chris

  • To detect EOL, I am using the UART RXINT to trigger searching the buffer for the first EOL. It would certainly be better to perform this search after the DMA completes, but I did not see a good way to get an interrupt after the DMA is done with each individual character yet keep the DMA active in case the interrupt is handled late. This isn't a problem though, as with two EOLs, we can just search for the first, and missing/discarding the second EOL isn't a problem.

    Add a timeout timer, to detect UART received data periodly.

    UART Rx Int is also ok.

    I noticed the reference manual details two ways for RXINT to be cleared. The first, by reading IIDX as our interrupt handler does:

    Yes.

    However, there is some timing I can't yet explain. I'd expect the DMA to often complete before our interrupt handler is called, causing the interrupt handler to see IIDX set to 0 most of the time, if not always. But I only observe IIDX set to zero in the interrupt handler at the end of a received line, and only at the end of every couple received lines.

    Maybe, DMA will clear the RXINT.

    You can monitor the DMA size, each transfer, dma size will -1.

    observed noise on the MSPM0G UART that lead to an observation of the IDDX STAT reading 0x00

    Need to confirm whether this is caused by UART noise, try to catch the UART noise on osc scope.

    Same answer, maybe this is cleared by DMA.

    A 0b0 noise will trigger UART interrupt, you can also try to enable UART error int and to confirm whether this is from such as error frame.

  • Hello,

    Thank you for the input! I am the developer working on this.

    We fixed the UART noise by enabling the rx pin's pull up resistor. It now looks clean on the scope. However, IIDX of 0 is still observed.

    Other than the occasional IIDX of 0, the UART seems to work normally, so we have ignored it so far during development. We are mostly wanting to know if it is safe to just ignore the IIDX of 0 interrupt, or if there is some underlying misconfiguration or other issue that we need to address.

  • Other than the occasional IIDX of 0, the UART seems to work normally, so we have ignored it so far during development. We are mostly wanting to know if it is safe to just ignore the IIDX of 0 interrupt, or if there is some underlying misconfiguration or other issue that we need to address.

    It's not seen too much, I'm worried that other issue may have triggered this IIDX=0.

    Can not confirm the root cause.

    But considering from another perspective, if customer's application can pass the functional and stress test, it will be OK.

  • I tested with the following interrupts both enabled and disabled, and consistently observed IIDX still happen:
    * overrun error
    * framing error
    * parity error
    * break error

    I also attempted:
    * disable the rx interrupt after receiving the line ending byte we look for (the second-to-last byte on the bus) and observed no difference.
    * disable the UART after receiving our line ending byte, which also made no difference. (just to be clear, it seems the IIDX 0 interrupt will still come in while the UART is disabled)
    * setting the UART interrupts to highest priority, and observed no difference.

    I did find one interesting thing of note: If I disable the other DMA channels, IIDX of 0 happens much more consistently, perhaps 99/100 lines. Perhaps this confirms it is a race condition between out interrupt handler and the DMA?
    Does this bring anything to light, or can you think of any other tests I might do to help determine root cause?
    Thanks again for your help!
  • I did find one interesting thing of note: If I disable the other DMA channels, IIDX of 0 happens much more consistently, perhaps 99/100 lines.

    This test result seems greatly affect the CPU usage time.

    1.

    Could you please let customer test UART module based on a example code from MSPM0-SDK?

    Such as this one, modify it to interrupt mode, then test UART mode, make sure there is no other issue from MSPM0 UART and silicon level.

    C:\ti\mspm0_sdk_2_05_00_05\examples\nortos\LP_MSPM0G3507\driverlib\uart_rw_multibyte_fifo_poll

    2.

    Please try a new MSPM0 chip.

    3.

    Please try to clear NVIC status after UART handler, but I don't think this way works:

    NVIC_ClearPendingIRQ
    4.
    Please confirm the interrupt table, make sure there is no other NVIC interrupt re-direct to UARTxIRQHandler.
  • Re #2: This has been consistent across 3 different MSPM0.

    Re #3: Adding `NVIC_ClearPendingIRQ(UARTx_INT_IRQn);` after we identify a received line makes the IIDX of 0 stop happening entirely!

    Here is the exact change I added, once we detect the first line end character:

    if (handle->uartReferences->registers->CPU_INT.MIS == 0)
    {
        NVIC_ClearPendingIRQ(handle->uartReferences->irqN);
    }

  • Re #3: Adding `NVIC_ClearPendingIRQ(UARTx_INT_IRQn);` after we identify a received line makes the IIDX of 0 stop happening entirely!

    Glade to hear this, but this isn't the root cause of this problem.

    It's really strange.

    1.

    Could you please let customer test UART module based on a example code from MSPM0-SDK?

    Such as this one, modify it to interrupt mode, then test UART mode, make sure there is no other issue from MSPM0 UART and silicon level.

    C:\ti\mspm0_sdk_2_05_00_05\examples\nortos\LP_MSPM0G3507\driverlib\uart_rw_multibyte_fifo_poll

    Do we have this test result from customer?

    We need to confirm whether this is a software or hardware issue, (of course, if customer need root cause.)

  • For now, we are happy with the fix using `NVIC_ClearPendingIRQ`. We may revisit in the future to see if it can be replicated with the sample project if our time allows, but it is not on the schedule for now.

    Thank you for your assistance with this! We now have an idea what is going on, and feel confident in this work-around.

  • Thanks for your feedback. I will mark this thread as resolved.