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: Code sometimes sticks on UART_transmitData in driverlib

Part Number: MSP432P401R


Every once in a great while, my code will get stuck when trying to transmit data over UART on A0 (hooked into my SIMCOM 868 GPS module).

It gets stuck on the while loop in the driverlib function. I am not entirely sure why it gets stuck or what the while loop is looking for. 

What does this code do? How can I gracefully recover from this fault, without using a watchdog timer? Can I re-write this code to use my own timeout function?

The driverlib function looks like this:

void UART_transmitData(uint32_t moduleInstance, uint_fast8_t transmitData)
{
    /* If interrupts are not used, poll for flags */
    if (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->rIE.r, UCTXIE_OFS))
        while (!BITBAND_PERI(EUSCI_A_CMSIS(moduleInstance)->rIFG.r, UCTXIFG_OFS))
            ;

    EUSCI_A_CMSIS(moduleInstance)->rTXBUF.r = transmitData;
}

I am communicating with the GPS that sends out a transmission every 0.1 seconds. It sends them out at 115200bps, With about 100-200 characters per transmission.

My code attempts to send the GPS a control command. It normally works but about 1% of the time it gets hung up, for no reason that I can reasonably discern.


UPDATE:

Here is the code to setup the UART:

void UART_Init(int module){
    SetupTimers();
    if(module == EUSCI_A0_BASE){
        // Setup UART A0
        MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 |
                                                       GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
        MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig0);        //Add config to UART Module
        MAP_UART_enableModule(EUSCI_A0_BASE);                   //Enable the UART Module
        MAP_Interrupt_enableInterrupt(INT_EUSCIA0);         //enable the interrupt
        MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    }
}

The UART configuration:

const eUSCI_UART_Config uartConfig0 =
{
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,                 // SMCLK Clock Source
    4,//52,                                             // BRDIV
    5,//1,                                              // UCxBRF
    0x55,//0x49,                                           // UCxBRS
    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
};

And, the configuration of the system clocks:

  // Configure clocks

    /* Configuring pins for peripheral/crystal usage and LED for output */
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
            GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);

    /* Setting the external clock frequency. This API is optional, but will
     * come in handy if the user ever wants to use the getMCLK/getACLK/etc
     * functions
     */
    CS_setExternalClockSourceFrequency(32768, 25000000);

    /* Starting LFXT in non-bypass mode without a timeout. */
    CS_startLFXT(CS_LFXT_DRIVE3);
    MAP_CS_setDCOFrequency(CLK_FQ);    // Setting DCO (clock) to the specified clock speed

    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);  	// Tie SMCLK to DCO
    MAP_CS_initClockSignal (CS_ACLK, CS_VLOCLK_SELECT, CS_CLOCK_DIVIDER_1);		// Tie ACLK to VLO
	

  • What does your (UCA0) ISR look like?
  • The UCA0 ISR is as follows:

    /**
     * EUSCI A0 UART ISR - puts receved data into receiveArray
     */
    void EUSCIA0_IRQHandler(void)
    {
        uint32_t status;
        if(!expect_A0){
            status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); //stock code?
            MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status);
            return;
        }
    
        status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); //stock code?
    
        MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status); //not sure what this line does...
    
        if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) //if data received
        {
            MAP_Timer_A_stopTimer(TIMER_A0_BASE);   //stop the timer
            TA0R = 0;                               //reset the counter
            MAP_Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);   //restart the timer
    
            receiveArray_A0[receiveIndex_A0] = MAP_UART_receiveData(EUSCI_A0_BASE); //put the character in the receive array
            receiveIndex_A0++; //Increment the array
    
            if(receiveIndex_A0 >= MAX_RECEIVE_LEN){ //dont let long transmissions give an error.
                printf("UART OVERRUN - A0\r\n");
                UARTOverRun = true;
                receiveIndex_A0 = 0;
            }
        }
    
    }

  • > MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status); //not sure what this line does...

    I recommend that you remove this line. It's superfluous, since the RXIFG will be cleared by UART_receiveData(), and doing this invites a read-modify-write race which can clear a nascent TXIFG.
  • Bruce,

    Thank you so much for the reply. I implemented it, and I will let it run over night to see if the problem is solved. I can't tell you how much I appreciate it. This bug has been plaguing me for weeks.

**Attention** This is a public forum