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.

MSP432P401R: UART Comms stalls because UCTXIFG is clear after a character is sent.

Part Number: MSP432P401R

Hi all,

We've had a few different scenarios now where our UART drivers will occassionally stall because UCTXIFG remains clear after a character is sent (UCBUSY = 0).

We've observed this behaviour in an interrupt based UART driver for a port running at 57.6kBaud, and a DMA based driver for another port running at 2MBaud. 

In the case of the DMA driver, we only seem to get the UCTXIFG problem at the end of the DMA burst - have not observed a DMA burst halt early due to this issue.

We are working around this by detecting that UCTXIFG is clear when it shouldn't be and setting it (just before starting the burst for DMA, on a timer for the interrupt based UART).

Both UARTs are sourced from SMCLK and we do not poll UCTXIFG so I don't think errata USCI44 applies.   

Do you have any suggestions regarding why we might be seeing this effect and whether there is a better work around?

Cheers

Julian

 

  • Julian,

      Can you send a code snippet that would reliably exercise the problem you are seeing?

    Regards,

      Bob Landers.

  • G'Day Bob,

    The code below is a modified version of the uart_loopback_24mhz_brclk example that comes with Simplelink, modified to exhibit the problem I've described. 

    Fire up CCS, run the program on your MSP432 Launchpad.  Open a terminal program and connect to the second serial port on the Launchpad and you should see characters spewing out in ASCII order.  Now, in the terminal program, hammer the keyboard.  Hits lots of keys rapidly.  It might take a minute or so, but eventually you will see the output from the launchpad stop.  Now pause execution in the debugger and have a look at register EUSCI_A0 UCTXIFG.  It will be low when it shouldn't be.  Set it back to high and  characters will start being transmitted again.

    // For brevity, snip TI disclaimer.
    
    /* DriverLib Includes */
    #include <ti/devices/msp432p4xx/driverlib/driverlib.h>
    
    /* Standard Includes */
    #include <stdint.h>
    #include <stdbool.h>
    #include <ti/drivers/utils/RingBuf.h>
    
    /* UART Configuration Parameter. These are the configuration parameters to
     * make the eUSCI A UART module to operate with a 115200 baud rate. These
     * values were calculated using the online calculator that TI provides
     * at:
     * software-dl.ti.com/.../index.html
     */
    const eUSCI_UART_Config uartConfig =
    {
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            13,                                      // BRDIV = 13
            0,                                       // UCxBRF = 0
            37,                                      // UCxBRS = 37
            EUSCI_A_UART_NO_PARITY,                  // No Parity
            EUSCI_A_UART_LSB_FIRST,                  // MSB First
            EUSCI_A_UART_ONE_STOP_BIT,               // One stop bit
            EUSCI_A_UART_MODE,                       // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION  // Oversampling
    };
    
    RingBuf_Object ringbuf_hndl;
    uint8_t txChar_u8 = 0;
    uint8_t rxBuff_u8;
    
    int main(void)
    {
        /* Halting WDT  */
        MAP_WDT_A_holdTimer();
    
        /* Selecting P1.2 and P1.3 in UART mode and P1.0 as output (LED) */
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
                 GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
    
        /* Setting DCO to 24MHz (upping Vcore) */
        FlashCtl_setWaitState(FLASH_BANK0, 2);
        FlashCtl_setWaitState(FLASH_BANK1, 2);
        MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
        CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_24);
    
        /* Configuring UART Module */
        MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);
    
        /* Enable UART module */
        MAP_UART_enableModule(EUSCI_A0_BASE);
    
        /* Enabling interrupts */
        MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
        MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT);
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
        MAP_Interrupt_enableSleepOnIsrExit();
    
        // Prime the Tx pump.  Once this char is sent the UCTXIFG interrupt
        // will keep characters flowing out.
        MAP_UART_transmitData(EUSCI_A0_BASE, 'a');
    
        while(1)
        {
        }
    }
    
    
    void EUSCIA0_IRQHandler(void)
    {
        uint_fast8_t status_u8 = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
        uint_fast8_t flags_u8;
        uint8_t rx_char_u8;
    
        if(status_u8 & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
        {
          MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    
          flags_u8 = MAP_UART_queryStatusFlags(EUSCI_A0_BASE, EUSCI_A_UART_FRAMING_ERROR + EUSCI_A_UART_OVERRUN_ERROR + EUSCI_A_UART_PARITY_ERROR + EUSCI_A_UART_BREAK_DETECT + EUSCI_A_UART_RECEIVE_ERROR);
          rx_char_u8 = MAP_UART_receiveData(EUSCI_A0_BASE);
    
          if (!flags_u8)
          {
            // Put received char in a buffer for processing elsewhere
            rxBuff_u8 =  rx_char_u8;
          }
        }
    
    
        if(status_u8 & EUSCI_A_UART_TRANSMIT_INTERRUPT)
        {
          // Don't bother clearing the Tx interrupt flag here!  Its hardware controlled.
          MAP_UART_transmitData(EUSCI_A0_BASE, txChar_u8++);
        }
    }
    

  • Julian,
    Thanks. I'll have a look and get back to you when I understand this better.
    -Bob
  • G'Day Bob,

    Just checking in. Has there been any progress?

    Cheers
    Julian
  • G'Day Bob,

    Any news?

    Cheers
    Julian
  • G'Day Bob,

    Checking in again.
    Would be great to know if there has been any progress!

    Cheers
    Julian
  • > MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);

    I recommend you not do this.

    It's completely unnecessary, since reading RXBUF (a few lines later) clears RXIFG (atomically).

    What it does do is invite a read-modify-write race which could clear TXIFG.

  • Thank you Bruce!

    Removing that line does seem to make the problem go away.

    Cheers
    Julian

**Attention** This is a public forum