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.

TM4C123GH6PGE: UART1 lost bytes with DMA TX

Part Number: TM4C123GH6PGE

I configured UART0 for transmitting and receiving bytes frames from an external device with DMA

Then I configured also UART1 for transmitting and receiving bytes frames from a different external device

Both to 57600 

Sometimes UART1 transmits a frame without some bytes. With UART0 stopped all bytes are always transmitted.

Every UART is configured in the same way....this is UARt1

#define DMA_UART1_RX (22) // RX
#define DMA_UART1_TX (23) // TX

SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);


GPIOPinConfigure(GPIO_PC4_U1RX);
GPIOPinConfigure(GPIO_PC5_U1TX);
GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);


UARTConfigSetExpClk(UART1_BASE,SysCtlClockGet(),57600,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

UARTFIFOLevelSet(UART1_BASE,UART_FIFO_TX4_8, UART_FIFO_RX4_8);

UARTTxIntModeSet(UART1_BASE,UART_TXINT_MODE_EOT);

UARTEnable(UART1_BASE);

UARTDMAEnable(UART1_BASE,UART_DMA_RX | UART_DMA_TX);
uDMAChannelAssign(UDMA_CH22_UART1RX);
uDMAChannelAssign(UDMA_CH23_UART1TX);

IntPrioritySet(INT_UART1, INT_PRIORITY_LEVEL_5);

IntEnable(INT_UART1);

uDMAChannelAttributeDisable(EVO_DMA_UART1_RX, UDMA_ATTR_ALTSELECT |
UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

uDMAChannelControlSet (EVO_DMA_UART1_RX | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);

start_RX();

uDMAChannelAttributeDisable(EVO_DMA_UART1_TX, UDMA_ATTR_ALTSELECT |
UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

uDMAChannelControlSet (EVO_DMA_UART1_TX | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

void IntHandler_UART1(void)
{
uint32_t ulStatus;
uint32_t ulMode;


ulStatus = UARTIntStatus(UART1_BASE,1);
UARTIntClear(UART1_BASE,ulStatus);

ulMode = uDMAChannelModeGet(DMA_UART1_RX | UDMA_PRI_SELECT);
if (ulMode == UDMA_MODE_STOP)
{

start_RX1();
}
else
;

if ((HWREG(UART1_BASE + UART_O_RIS) & UART_RIS_TXRIS) == UART_RIS_TXRIS)
{
uDMAChannelDisable(DMA_UART1_TX);

}
else
;

uDMAIntClear((1 << DMA_UART1_RX) | (1 << DMA_UART1_TX));
}

static void start_RX1(void)
{

uDMAChannelDisable(EVO_DMA_UART1_RX);


UDMA_MODE_BASIC,
(void*)(UART1_BASE + UART_O_DR),
rx1_bytes,
DIM_MAX_TXRX_BYTES);

uDMAChannelEnable(DMA_UART1_RX);

}

static void start_TX1(uint32_t dim)
{



uDMAChannelTransferSet(DMA_UART1_TX | UDMA_PRI_SELECT,
UDMA_MODE_BASIC,
tx1_bytes,
(void*)(UART1_BASE + UART_O_DR),
dim);

uDMAChannelEnable(DMA_UART1_TX);
}

  • Hi,

      This is the first time I have come across an issue like this. Can you answer me a few questions?

      - Are there other DMA channels other than UART0 and UART1?

      - Can you reproduce the same issue with different baudrate? 

      - You use the BASIC_MODE. I will suggest you try the PING_PONG mode instead. It is possible that the CPU has not enough time to fill the buffer for the UART1 to transmit. Ping-pong mode is normally desired to handle this. 

      - *What if you make the UART1 higher interrupt priority than UART0? Will this make the UART1 problem go away but instead make the UART0 missing bytes? 

      - What system clock is the CPU operating at? Is it 80Mhz or slower? Can you make the CPU run at the max which is 80Mhz.

  • Hi Charles,

    1) Yes, I  use DMA channel also for UART5 transmission and receive. I haven't noted the same problem on UART5 but UART5 transmits and receives very short bytes frames.

    2) Today I will try with different baud rate

    3) I have same problem also with PINGPONG mode

    4) I'm using system clock of 80MHz

  • I disabled tx on UART0 and on UART1 and also disabled UART5

    Then I tryed to activate PING PONG mode on RX also on UART0 (not only on UART1) and I started to have a lot of problems.....

    This is  configuration for UART0 (UART1 is equivalent):

    uint8_t uart0_rx_bytes[DIM_MAX_RX_BYTES];

    void UART0_Init(void)

    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);


    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);


    UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),57600,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));


    UARTFIFOLevelSet(UART0_BASE,UART_FIFO_TX4_8, UART_FIFO_RX4_8);


    UARTEnable(UART0_BASE);


    UARTDMAEnable(UART0_BASE,UART_DMA_RX | UART_DMA_TX);
    uDMAChannelAssign(UDMA_CH8_UART0RX);
    uDMAChannelAssign(UDMA_CH9_UART0TX);


    IntPrioritySet(INT_UART0, INT_PRIORITY_LEVEL_UART0);


    IntEnable(INT_UART0);


    uDMAChannelAttributeDisable(UDMA_CHANNEL_UART1RX, UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);


    uDMAChannelControlSet (UDMA_CHANNEL_UART1RX| UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);


    uDMAChannelControlSet (UDMA_CHANNEL_UART1RX| UDMA_ALT_SELECT,
      UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);


    uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX| UDMA_PRI_SELECT,
     UDMA_MODE_PINGPONG,
    (void*)(UART0_BASE + UART_O_DR),
         uart0_rx_bytes,
       DIM_MAX_RX_BYTES/2);

     uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX| UDMA_ALT_SELECT,
    UDMA_MODE_PINGPONG,
     (void*)(UART0_BASE + UART_O_DR),
    &uart0_rx_bytes[DIM_MAX_RX_BYTES/2],
    DIM_MAX_RX_BYTES/2);
    }

    void IntHandler_UART0(void)
    {
    uint32_t ulStatus;
    uint32_t ulMode;


    ulStatus = UARTIntStatus(UART0_BASE,1);
    UARTIntClear(UART0_BASE,ulStatus);


    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART0RX| UDMA_PRI_SELECT);
    if (ulMode == UDMA_MODE_STOP)
    {

    uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX| UDMA_PRI_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART0_BASE + UART_O_DR),
    uart0_rx_bytes, DIM_MAX_TXRX_BYTES/2);
    }
    else
    ;


    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART0RX| UDMA_ALT_SELECT);
    if (ulMode == UDMA_MODE_STOP)
    {

    uDMAChannelTransferSet(UDMA_CHANNEL_UART0RX| UDMA_ALT_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART0_BASE + UART_O_DR),
    &uart0_rx_bytes[DIM_MAX_RX_BYTES/2], DIM_MAX_RX_BYTES/2);
    }
    else
    ;


    }

    #define INT_PRIORITY_LEVEL_UART0  (0xA0)

    #define INT_PRIORITY_LEVEL_UART1 (0xA0)

    When arrives Interrupt on UART0 both PRI and ALT are both executed !!! 

    I have a question....

    How can I interpretate this from datasheet?

  • Hi, 

      In your UART0_Init you have several UART1 references. See below. 

    void UART0_Init(void)

    {
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);


    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);


    UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),57600,
    (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));


    UARTFIFOLevelSet(UART0_BASE,UART_FIFO_TX4_8, UART_FIFO_RX4_8);


    UARTEnable(UART0_BASE);


    UARTDMAEnable(UART0_BASE,UART_DMA_RX | UART_DMA_TX);
    uDMAChannelAssign(UDMA_CH8_UART0RX);
    uDMAChannelAssign(UDMA_CH9_UART0TX);


    IntPrioritySet(INT_UART0, INT_PRIORITY_LEVEL_UART0);


    IntEnable(INT_UART0);


    uDMAChannelAttributeDisable(UDMA_CHANNEL_UART1RX, UDMA_ATTR_ALTSELECT |
    UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);


    uDMAChannelControlSet (UDMA_CHANNEL_UART1RX| UDMA_PRI_SELECT,
    UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);


    uDMAChannelControlSet (UDMA_CHANNEL_UART1RX| UDMA_ALT_SELECT,
      UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);


    uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX| UDMA_PRI_SELECT,
     UDMA_MODE_PINGPONG,
    (void*)(UART0_BASE + UART_O_DR),
         uart0_rx_bytes,
       DIM_MAX_RX_BYTES/2);

     uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX| UDMA_ALT_SELECT

  • I apologize  but in my message I attached the wrong  part ...In my real code I used the correct UART!!

    In my real code I have a lot of define ..to clarify I tried to substitute ...

  • Hi,

    Can you confirm one more time that when UART1 is the only module operating then everything is fine. Is that correct?

    When you said UART1 is not working - missing some bytes, can you elaborate how many bytes are you trying to transfer and how many are missing?  

    Earlier I asked to change the interrupt priority for UART1. Did you have a chance to do that? The reason I asked for changing the priority is because you said UART1 is working if UART0 is stopped. Therefore, I have no reason to believer any misconfiguration with UART1 other than it's interrupt priority.

    I see the below line of code. 

    IntPrioritySet(INT_UART1, INT_PRIORITY_LEVEL_5);

    If UART0 has a higher priority then UART1 will not have a equal chance for interrupt service. Can you make both UART0 and UART1 with equal priority so that both will get serviced equally. With equal priority level, NVIC will round-robin between the modules. Will that make difference?

  • Hi

    1) I confirm that if UART1 is the only operating module everything is fine, also when UART0 is the only operating module everything is fine.

    2) with both module on same priority nothing change

    3) If I have UART5 and UART 1 both operating everything is fine.. so the problem seems to be on UART0

    4) If I have UART0 and UART1 both in RX PINGPONG mode nothing is operating....when I say nothing I intend that both channel doesn't receive correct bytes...received bytes are casually or repeated or sometimes nothing is received...

    Problem starts when I receive first interrupt on UART0..even if same priority level or UART1 with higher priority or UART0 with higher priority

    5) The only way to see something to work is with UART0 in RX BASIC mode and UART1 in RX PINGPONG or BASIC mode but with UART0 INT HANDLER like this:

    void iot_IntHandler_UART0(void)
    {
    uint32_t ulStatus;


    ulStatus = UARTIntStatus(UART0_BASE,0);
    UARTIntClear(UART0_BASE,ulStatus);

    //leggo lo stato degli interrupt del DMA
    ulStatus = uDMAIntStatus();

    if ((ulStatus & (1 << UDMA_CHANNEL_UART0RX)) != 0)
    {
        start_IOT_RX();
       uDMAIntClear(ulStatus & (1 << UDMA_CHANNEL_UART0RX));
    }
    else;

    }

    and UART1 INT HANDLER as usual (below when in PINGPONG mode)

    void IntHandler_UART1(void)
    {
    uint32_t ulStatus;
    uint32_t ulMode;


    ulStatus = UARTIntStatus(UART1_BASE,1);
    UARTIntClear(UART1_BASE,ulStatus);


    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART1RX| UDMA_PRI_SELECT);
    if (ulMode == UDMA_MODE_STOP)
    {

    uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX| UDMA_PRI_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART1_BASE + UART_O_DR),
    uart1_rx_bytes, DIM_MAX_TXRX_BYTES/2);
    }
    else
    ;


    ulMode = uDMAChannelModeGet(UDMA_CHANNEL_UART1RX| UDMA_ALT_SELECT);
    if (ulMode == UDMA_MODE_STOP)
    {

    uDMAChannelTransferSet(UDMA_CHANNEL_UART1RX| UDMA_ALT_SELECT,
    UDMA_MODE_PINGPONG,
    (void *)(UART1_BASE + UART_O_DR),
    &uart1_rx_bytes[DIM_MAX_RX_BYTES/2], DIM_MAX_RX_BYTES/2);
    }
    else
    ;

    //UART1 channel is half-duplex so I need to intercept end of transmission; so I enabled interrupt 

    // se é finita la trasmissione su UART1 riattivo la ricezione
    if ((HWREG(UART1_BASE + UART_O_RIS) & UART_RIS_TXRIS) == UART_RIS_TXRIS)
    {

    evo_tx = false;
    // enable receiving on transiver
    DIS_EVO_TX();
    EN_EVO_RX();
    }
    else
    ;


    }

    In this way all seems functioning but sometimes when UART1 transmits bytes,  in the middle of one bytes frame, 4 or 5 bytes are not transmitted.

    I start transmission on UART1 in the same way of UART0 (below for UART0):

    static void start_UART0_TX(uint32_t dim)
    {

    uDMAChannelTransferSet(IOT_DMA_UART0_TX | UDMA_PRI_SELECT,
    UDMA_MODE_BASIC,
    iot_tx_bytes,
    (void*)(UART0_BASE + UART_O_DR),
    dim);


    uDMAChannelEnable(IOT_DMA_UART0_TX);
    }

    To have INTERRUPT when UART1 ends trasmitting bytes I added this line in UART1 configuration function:

    UARTTxIntModeSet(UART1_BASE,UART_TXINT_MODE_EOT);

    Below a photo from oscilloscope when UART1 TX lost bytes to transmit...(5 bytes just before end of UART0 TX)

    YELLOW UART1 RX

    RED/PINK  UART1 TX

    GREEN UART0 TX

    CYAN UART1 RX

  • Hi Lisa,

      Can you upload another scope shot so the signals are not overlapped? It is too difficult for me to see what happens when you have 4 signals overlap each other. If the problem is on the TX, then you don't need to show the RX pins. Please also indicate what is the expected values to appear in place of the missing bytes. 

      I really don't know why would add adding UART0 break UART1. At first I was thinking about the interrupt priority but you proved it is not the case. 

      Can you try a simple example? Take the TivaWare udma_demo example and add UART0 in addition to UART1. Will you see any missing bytes?The example has also DMA transfer between memory to memory which you can remove. The example already has DMA transfer to UART1 in ping-pong mode. Do you see the same issue?