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.

MSP432P4111: UART communication

Part Number: MSP432P4111

Hi,

I try to communicate over UART_A2 with a modem on pins 3.2 and 3.3.

My target is that it runs on a FreeRTOS applicatoin with a system clock of 48MHz. But now for testing I have reduced it to a simple programm (which I found on several places).

/*
 * Communication with Modem Mikroelektronika LTE IO CLICK
 *
 **********************************************************************************************/

#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOMSP432.h>
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <string.h>

#define UART2   GPIO_PORT_P3, GPIO_PIN2 | GPIO_PIN3
#define MODEMSTART   GPIO_PORT_P4, GPIO_PIN6

const eUSCI_UART_Config uartConfig =
{
    EUSCI_A_UART_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
    78,                                      // BRDIV = 78
    2,                                       // UCxBRF = 2
    0,                                       // UCxBRS = 0
    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
};

void EUSCIA2_IRQHandler(void)
{
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A2_BASE);
//    char receiveByte = EUSCI_A2->RXBUF; //UCA2RXBUF;  //This is the address where the received byte is stored
    char receiveByte = MAP_UART_receiveData(EUSCI_A2_BASE);

    MAP_UART_clearInterruptFlag(EUSCI_A2_BASE, status);

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)
    {
        MAP_UART_transmitData(EUSCI_A2_BASE, receiveByte);
        printf("\nEUSCIA2_IRQHandler: %c",  receiveByte);
    }
}

int main(void)
{
    /* Halting WDT  */
    WDT_A_holdTimer();

    printf("\nCS_getDCOFrequency=%d", CS_getDCOFrequency());
    printf("\nCS_getMCLK=%d", CS_getMCLK());
    printf("\nCS_getSMCLK=%d\n", CS_getSMCLK());

    /* Set pins 2 and 3 of port 3 to the primary module function (UART) */
    GPIO_setAsPeripheralModuleFunctionInputPin(UART2, GPIO_PRIMARY_MODULE_FUNCTION);

    /* Setting DCO to 12MHz */
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);

    UART_initModule(EUSCI_A2_BASE, &uartConfig);
    UART_enableModule(EUSCI_A2_BASE);
    /* Enabling UART interrupts */
    MAP_UART_enableInterrupt(EUSCI_A2_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    MAP_Interrupt_enableInterrupt(INT_EUSCIA2);
    MAP_Interrupt_enableSleepOnIsrExit();
    MAP_Interrupt_enableMaster();

    MAP_GPIO_setAsOutputPin(MODEMSTART);

    /* reset Modem */
    MAP_GPIO_setOutputHighOnPin(MODEMSTART);
    for (int var = 0; var < 2400000; ++var) {    } // 50ms
    MAP_GPIO_setOutputLowOnPin(MODEMSTART);
    for (int var = 0; var < 2400000; ++var) {    } // 50ms
    for (int var = 0; var < 2400000; ++var) {    } // 50ms
    for (int var = 0; var < 2400000; ++var) {    } // 50ms
    for (int var = 0; var < 2400000; ++var) {    } // 50ms
    MAP_GPIO_setOutputHighOnPin(MODEMSTART);

    for (int var = 0; var < 2400000; ++var) {    }

    //    UART_transmitData(EUSCI_A2_BASE, "AT");
    MAP_UART_transmitData(EUSCI_A2_BASE, 'A');
    MAP_UART_transmitData(EUSCI_A2_BASE, 'T');

    while (1)
    {
        MAP_PCM_gotoLPM0();
    }
}


The current issue is that the ISR is entered continuously and put out:

EUSCIA2_IRQHandler: A
EUSCIA2_IRQHandler: A
EUSCIA2_IRQHandler: A
...

1. It looks like the ISR Flag isn't resetted...?

2. Is it possible to transmit a char[] e.g. transmit 'AT' instead of 'A' and then 'T' ?

3. What are the settings for BRDIV, UCxBRF and UCxBRS if SMCLK has 48MHz? From the Technical Reference Manual I found this table but I can't find a setup for 48MHz.

Thanks for help

  • You cannot transmit 'AT' since the single quotes indicate a single character. "AT" is a string with 'A', 'T' and '\0' to signal the end. You would have to write your own wrapper to send each individual character in the string.
  • Maybe there is a problem with EUSCI_A2->RXBUF or UCA2RXBUF, what should be used?
    I found both in different examples.
  • Hi,

    now it's possible to send and receive from the modem:

    1. It looks like the ISR Flag isn't resetted...? => In the ISR there was a transmit command which always send back the received command:

    MAP_UART_transmitData(EUSCI_A2_BASE, receiveByte);

    This was from an example and I missed it to remove.

    2. ok

    3. ok

    Now I try that it works with FreeRTOS. Please don't close this thread. I'll give feedback shortly.

  • After a long time trying to use it with FreeRTOS I need support from the forum. I realized that the previous approach doesn't work with (Free)RTOS.

    I mixed the example "display_MSP_EXP432P4111_freertos_ccs" and "uartecho_MSP_EXP432P4111_freertos_ccs" from the msp sdk 3.10.00.08.

    Then I changed the uartParams to read and write uart without blocking the task. Furthermore, I set the read mode to "UART_MODE_CALLBACK" because I want to get the incoming datas when all are completely transfered. With every ISR call I set a flag. In the while loop I only print this data when the flag ist set:

    #include <stdint.h>
    #include <stddef.h>
    #include <unistd.h>
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/UART.h>
    /* Example/Board Header files */
    #include "Board.h"
    /* Display Header files */
    #include <ti/display/Display.h>
    #include <ti/display/DisplayUart.h>
    /* RTOS header files */
    #include <FreeRTOS.h>
    #include <task.h>
    
    uint8_t flag;
    char RxBuf[100];
    
    static void uartRxFinished(UART_Handle handle, void *buf, size_t count)
    {
        memcpy((char*)(RxBuf), (char*)buf, count);
        flag = 1;
    }
    
    
    void *mainThread(void *arg0)
    {
        const char  TxBuf[] = "AT+CCLK?\r\n";
    
        UART_Handle uart;
        UART_Params uartParams;
    
        /* Call driver init functions */
        GPIO_init();
        Display_init();
        UART_init();
    
        /* Initialize display and try to open UART display. */
        Display_Params params;
        Display_Params_init(&params);
        params.lineClearMode = DISPLAY_CLEAR_BOTH;
        Display_Handle hSerial = Display_open(Display_Type_UART, &params);
        if (hSerial == NULL) {
            /* Failed to open a display */
            while (1) {}
        }
        /* Check if the selected Display type was found and successfully opened */
        if (hSerial) {
            Display_printf(hSerial, 0, 0, "Hello Serial!");
        }
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.writeMode = UART_MODE_CALLBACK;
        uartParams.readDataMode = UART_DATA_TEXT;
        uartParams.writeDataMode = UART_DATA_TEXT;
        uartParams.readCallback = uartRxFinished;
        uartParams.readReturnMode = UART_RETURN_NEWLINE;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
    
        uart = UART_open(Board_UART1, &uartParams);
        if (uart == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        UART_write(uart, TxBuf, sizeof(TxBuf));
    
        while (1) {
    
            if (flag == 1)
            {
                flag = 0;
                /* Print to UART0 */
                Display_printf(hSerial, 0, 0, "Rx: %s", RxBuf);
            }
            vTaskDelay(100);
        }
    }
    

    But it doesn't work right. After UART_write() it ends in the faultISR() function.

    Does anyone know why?

  • One issue I found. I missed to declare the write callback function. Normally I do not need a write callback but then the write function work in "UART_MODE_BLOCKING". I don't want that this uart task can block because in the application there are other important task. Now I tried both:

    Variant: callback

    ...
        uartParams.writeMode = UART_MODE_CALLBACK;
        uartParams.writeCallback = uartTxFinished;
    ...
    // dummy ISR
    static void uartTxFinished(UART_Handle handle, void *buf, size_t count)
    {
    }

    and variant: blocking

       uartParams.writeMode = UART_MODE_BLOCKING;
    

    But both variants ended now in the cpu_wfi() function. What could be the reason for this?

    To exclude an issue from the modem I shorted pin 3.2 (Rx) with pin 3.3 (Tx).

  • Now I have worked out two possible ways to send and read data via UART and RTOS. But for both ways I need again (final) support.

    The procedure is like this, sending 2 commands:

        const char  TxBuf0[] = "ATE0\r\n";
        const char  TxBuf1[]  = "AT+CCLK?\r\n";

    and the received anwer from the external decive is correct. I could proved it with another termial: This is the correct answer:

    1. read via callback function:


    The mainThread initializes the display console and the uart. It also includes the read callback function. With every read it sends the data with a queue to another task. Then with a sempahore and the UART_read(uart, RxBuf, sizeof(RxBuf)) the next incoming data can be received:

    char RxBuf[100];
    char lineBuffer[100];
    
    SemaphoreHandle_t xSemaphoreReadLine = NULL;
    extern QueueHandle_t xQueueRx;
    Display_Handle hSerial;
    UART_Handle uart;
    
    static void uartRxFinished(UART_Handle handle, void *buf, size_t count)
    {
        static BaseType_t xHigherPriorityTaskWoken = 0;
    
        memcpy(lineBuffer, buf, count);
    
        if( xQueueRx != 0 ) 
        {
           BaseType_t xHigherPriorityTaskWoken;
           xHigherPriorityTaskWoken = pdFALSE;
           xQueueSendFromISR( xQueueRx, lineBuffer, &xHigherPriorityTaskWoken );
    
           if( xHigherPriorityTaskWoken )
           {
               portYIELD_FROM_ISR (xHigherPriorityTaskWoken);
           }
        }
    
        if (xSemaphoreReadLine != NULL)
            xSemaphoreGiveFromISR(xSemaphoreReadLine, &xHigherPriorityTaskWoken);
    
        if (xHigherPriorityTaskWoken){
            taskYIELD(); 
        }
    }
    static void uartTxFinished(UART_Handle handle, void *buf, size_t count)
    {
    }
    
    void *mainThread(void *arg0)
    {
        UART_Params uartParams;
    
        /* Call driver init functions */
        GPIO_init();
        Display_init();
        UART_init();
    
        /* Initialize display and try to open UART display. */
        Display_Params params;
        Display_Params_init(&params);
        params.lineClearMode = DISPLAY_CLEAR_BOTH;
        hSerial = Display_open(Display_Type_UART, &params);
    
        if (hSerial == NULL) {
            /* Failed to open a display */
            while (1) {}
        }
        /* Check if the selected Display type was found and successfully opened */
        if (hSerial) {
            Display_printf(hSerial, 0, 0, "\n\n ===== Hello Serial! =======\n");
        }
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.writeMode = UART_MODE_CALLBACK;
        uartParams.readDataMode = UART_DATA_TEXT;
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readCallback = uartRxFinished;
        uartParams.writeCallback = uartTxFinished;
        uartParams.readReturnMode = UART_RETURN_NEWLINE;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
        uartParams.dataLength = UART_LEN_8;
        uartParams.parityType = UART_PAR_NONE;
        uartParams.stopBits = UART_STOP_ONE;
    
        uart = UART_open(Board_UART1, &uartParams);
        if (uart == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        xSemaphoreReadLine = xSemaphoreCreateBinary();
        xSemaphoreGive(xSemaphoreReadLine);
        xSemaphoreTake( xSemaphoreReadLine, portMAX_DELAY );
    
        UART_read(uart, RxBuf, sizeof(RxBuf));
    
        while (1) {
    
            if( xSemaphoreTake( xSemaphoreReadLine, portMAX_DELAY ) == pdTRUE )
            {
                UART_read(uart, RxBuf, sizeof(RxBuf));
            }
        }
    }
    
    
    
    

    The txThread only sends the two commands:

    char lineBuffer[100];
    
    void *txThread(void *arg0)
    {
        const char  TxBuf0[] = "ATE0\r\n";
        const char  TxBuf1[]  = "AT+CCLK?\r\n";
    
        while (1) {
    
            vTaskDelay(2000 / portTICK_PERIOD_MS);
    
            UART_write(uart, TxBuf0, sizeof(TxBuf0));
            Display_printf(hSerial, 0, 0, "Tx: %s", TxBuf0);
    
            while(1){
                vTaskDelay(2000 / portTICK_PERIOD_MS);
                UART_write(uart, TxBuf1, sizeof(TxBuf1));
                Display_printf(hSerial, 0, 0, "Tx: %s", TxBuf1);
    
                while(1){
                    vTaskDelay(2000 / portTICK_PERIOD_MS);
                }
            }
        }
    }

    And the rxThread only displays the asyncronous incoming data:

    char lineBuffer[100];
    
    void *rxThread(void *arg0)
    {
        while (1) {
            if( xQueueRx != 0 )
            {
                if( xQueueReceive( xQueueRx, &lineBuffer, ( TickType_t ) -1 ) )
                {
                    Display_printf(hSerial, 0, 0, "\n%s", lineBuffer);
                }
            }
        }
    }

    But the display output via putty is:

    What I have to change to only send data with queue until the termination \r\n? The sent data should afterwards be deleted or never send again the next time.

    2. read polling 1 byte:


    With this solution I tried to read only 1 byte without a callback function. Afterward I would handle myself the finished command at \r\n.

    char RxBuf[100];
    
    Display_Handle hSerial;
    UART_Handle uart;
    
    static void uartRxFinished(UART_Handle handle, void *buf, size_t count)
    {
    
    }
    static void uartTxFinished(UART_Handle handle, void *buf, size_t count)
    {
    }
    
    void *mainThread(void *arg0)
    {
        const char  TxBuf0[] = "ATE0\r\n";
        const char  TxBuf1[]  = "AT+CCLK?\r\n";
    
        UART_Params uartParams;
    
        /* Call driver init functions */
        GPIO_init();
        Display_init();
        UART_init();
    
        /* Initialize display and try to open UART display. */
        Display_Params params;
        Display_Params_init(&params);
        params.lineClearMode = DISPLAY_CLEAR_BOTH;
        hSerial = Display_open(Display_Type_UART, &params);
    
        if (hSerial == NULL) {
            /* Failed to open a display */
            while (1) {}
        }
        /* Check if the selected Display type was found and successfully opened */
        if (hSerial) {
            Display_printf(hSerial, 0, 0, "\n\n ===== Hello Serial! =======\n");
        }
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.readMode = UART_MODE_CALLBACK;
        uartParams.writeMode = UART_MODE_CALLBACK;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readCallback = uartRxFinished;
        uartParams.writeCallback = uartTxFinished;
        uartParams.readReturnMode = UART_RETURN_NEWLINE;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
        uartParams.dataLength = UART_LEN_8;
        uartParams.parityType = UART_PAR_NONE;
        uartParams.stopBits = UART_STOP_ONE;
    
        uart = UART_open(Board_UART1, &uartParams);
        if (uart == NULL) {
            /* UART_open() failed */
            while (1);
        }
    
        vTaskDelay(1);
        memset(&RxBuf[0], 0, sizeof(RxBuf)); 
    
        while (1) {
            int i=0;
            UART_write(uart, TxBuf0, sizeof(TxBuf0));
            Display_printf(hSerial, 0, 0, "Tx: %s", TxBuf0);
            vTaskDelay(500 / portTICK_PERIOD_MS);
    
            UART_readPolling(uart, &RxBuf[i], 1); i++;
            vTaskDelay(10 / portTICK_PERIOD_MS);
            UART_readPolling(uart, &RxBuf[i], 1); i++;
            vTaskDelay(10 / portTICK_PERIOD_MS);
            UART_readPolling(uart, &RxBuf[i], 1); i++;
            vTaskDelay(10 / portTICK_PERIOD_MS);
            UART_readPolling(uart, &RxBuf[i], 1); i++;
            vTaskDelay(10 / portTICK_PERIOD_MS);
            Display_printf(hSerial, 0, 0, "Rx: %s", RxBuf);
            i=0;
            memset(&RxBuf[0], 0, sizeof(RxBuf));
    
            UART_write(uart, TxBuf8, sizeof(TxBuf8));
            Display_printf(hSerial, 0, 0, "Tx: %s", TxBuf8);
            vTaskDelay(500 / portTICK_PERIOD_MS);
    
            while(1){
                vTaskDelay(10 / portTICK_PERIOD_MS);
                UART_readPolling(uart, &RxBuf[i], 1); i++;
                Display_printf(hSerial, 0, 0, "Rx%d: %s", i, RxBuf);
            }
    
            while(1){
                vTaskDelay(2000 / portTICK_PERIOD_MS);
            }
        }
    }
    
    

    But with this approach I can't read all incoming data.

    What is the reason for this?

    Thank you in advance for any help?

     

  • Hello,

    I see that you are using two different methods to achieve the same result. If yes then I would recommend using one method and try to make it work. Using two methods is a distraction for any one trying to help.

    In the "read via callback function":
    * I don't understand why you are releasing a Queue and a Semaphore from "uartRxFinished".
    * It is not clear what is the expected output is.

    As a debug step, place a breakpoint in the "rxThread" function when using "Display_printf" and see if the buffer being displayed has the necessary data. If it does not have the right data, then you can trace back to the section of code that is responsible for not sending the right data to the queue.

    Hope this helps!

    Thanks,
    Sai
  • Sai Reddy said:

    In the "read via callback function":
    * I don't understand why you are releasing a Queue and a Semaphore from "uartRxFinished".
    * It is not clear what is the expected output is.

    Hello,

    all right, let's focus on the callback method.

    As far as I understand, I have to "reactivate" after every finished callback function the uart read that it can receive new incoming data. After releasing of the semaphore in the  while(){} section of the mainThread it "reactivates" it with the UART_read(). In the manual I have read that this is not allowed in the callback function.

    The enqueue in the callback function sends data to the rxThread. I do this, that the callback function blocks not to long.

    The expected output would be the same like this:

    I want to get a line after every \r\n is received.

    I hope it is clear what I try to achieve.


    As a debug step, place a breakpoint in the "rxThread" function when using "Display_printf" and see if the buffer being displayed has the necessary data. If it does not have the right data, then you can trace back to the section of code that is responsible for not sending the right data to the queue.

    If I set a breakpoint in the "rxThread" function when using "Display_printf" then I can see any data in buffer or at the ouput. If I would enqueue the char Array by reference this would be this error pattern. But I enqueue it by value, is this correct? But why it is time dependent?

    Thanks !

  • user5841294 said:
            while(1){
                vTaskDelay(10 / portTICK_PERIOD_MS);
                UART_readPolling(uart, &RxBuf[i], 1); i++;
                Display_printf(hSerial, 0, 0, "Rx%d: %s", i, RxBuf);
            }

    These lines look suspect to me. One byte is being read at a time with "UART_readPolling", but the whole string is being printed with "Display_printf". A better way is to use "UART_write" API as shown in the example ./examples/rtos/MSP_EXP432P4111/drivers/uartecho

    Thanks,

    Sai

  • Hi,

    now it looks that "read via callback function" is ok.

    The problem was that the ISR was blocked to0 long because of sending by queue. Now I reduced the sending by queue. Only if "enough and correct" data are available. Also I start to implement a flow control. After that, only new data can be send to MCU when then MCU is ready.

    Thanks for support!

**Attention** This is a public forum