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.

RTOS/MSP432E401Y: Receive data interrupt not triggering for UART

Part Number: MSP432E401Y

Tool/software: TI-RTOS

Hi,

I am using MSP432E401 launchpad.

I have configured UART2 and UART3 for sending and receiving data at 9600 baud

I am able to send data and could see it on connector pin using signal analyzer.

I have then looped back RX -- TX in my connector to loop the character sent back to rx.

Again, I could see my signal analyzer showing the plot.

Here, I have enabled the interrupt for receiving any data on my UART but it does not get trigger until I call UART_read();

Isn't the interrupt expected without even calling UART_read since I have enabled it?

Attached is the code, if I comment UART_read in function "testGsmUart" it does not callback my uartDataReadCallBack function.

Is there anything wrong in I configuring the UART?

Appreciate any pointers to resolve the problem.

#include <ti/drivers/UART.h>
#include <ti/sysbios/knl/Queue.h>

#include <Board.h>


#include "GSMModule.h"

static UART_Handle gsmUARTHandle;

static void uartDataReadCallBack(UART_Handle handle, void *buf, size_t count);
static void uartDataWriteCallBack(UART_Handle handle, void *buf, size_t count);

static void processGsmResponse();
static void initGsmModule();

Queue_Handle rxDataQ;

typedef struct gsmRxDataStruct{
    Queue_Elem elem;
    char data;
}gsmRxDataStruct;

gsmRxDataStruct gsmRxData;


/*
 *  ======== GSM Module thread ========
 *  This thread processes all the request and response from the gsm module
 */
void *GsmModuleThread()
{
    initGsmModule();

    //sleep(2);

    while (1) {

        processGsmResponse();

    }

}


void initGsmModule()
{

    rxDataQ = Queue_create(NULL, NULL);

    UART_init();

// Initialize UART parameters
    UART_Params params;
    UART_Params_init(&params);
    params.baudRate = 9600;
    //params.readMode = UART_MODE_BLOCKING;
    //params.writeMode = UART_MODE_BLOCKING;
    params.readMode = UART_MODE_CALLBACK;
    params.writeMode = UART_MODE_CALLBACK;
    params.readTimeout = UART_WAIT_FOREVER;
    params.writeTimeout = UART_WAIT_FOREVER;
    params.readEcho = UART_ECHO_OFF;

    params.readCallback = uartDataReadCallBack;
    params.writeCallback = uartDataWriteCallBack;

    // Open the UART
    gsmUARTHandle = UART_open(Board_UART2, &params);
    //gsmUARTHandle = UART_open(Board_UART3, &params);

    if(gsmUARTHandle == NULL)
    {
        //Failed to open UART
        while(1);
    }
}

void processGsmResponse()
{
    gsmRxDataStruct *d;

    if(!Queue_empty(rxDataQ))
    {
        d = Queue_get(rxDataQ);
        if(d)
        {
            char c = d->data;
        }
    }
}

void testGsmUart()
{
    char buffer = 'A';

    UART_write(gsmUARTHandle, &buffer, 1);

#if 1
    char* rd;
    /* SP_DEBUG: Needs this line else data receive interrupt is not triggering */
    UART_read(gsmUARTHandle, rd, 1);
#endif
}

void uartDataReadCallBack(UART_Handle handle, void *buf, size_t count)
{
    char *rxBuf = (char*) buf;

    gsmRxDataStruct rData;
    rData.data = rxBuf[0];

    Queue_put(rxDataQ, &(rData.elem));
}

void uartDataWriteCallBack(UART_Handle handle, void *buf, size_t count)
{

}

My UART configuration as follows

/* UART configuration structure */
const UARTMSP432E4_HWAttrs uartMSP432E4HWAttrs[MSP_EXP432E401Y_UARTCOUNT] = {
    {
        .baseAddr = UART3_BASE,
        .intNum = INT_UART3,
        .intPriority = (~0),
        .flowControl = UARTMSP432E4_FLOWCTRL_NONE,
        .ringBufPtr  = uartMSP432E4RingBuffer[MSP_EXP432E401Y_UART3],
        .ringBufSize = sizeof(uartMSP432E4RingBuffer[MSP_EXP432E401Y_UART3]),
        .rxPin = UARTMSP432E4_PA4_U3RX,
        .txPin = UARTMSP432E4_PA5_U3TX,
        .ctsPin = UARTMSP432E4_PIN_UNASSIGNED,
        .rtsPin = UARTMSP432E4_PIN_UNASSIGNED,
        .errorFxn = NULL
    },
    {
        .baseAddr = UART2_BASE,
        .intNum = INT_UART2,
        .intPriority = (~0),
        .flowControl = UARTMSP432E4_FLOWCTRL_NONE,
        .ringBufPtr  = uartMSP432E4RingBuffer[MSP_EXP432E401Y_UART2],
        .ringBufSize = sizeof(uartMSP432E4RingBuffer[MSP_EXP432E401Y_UART2]),
        .rxPin = UARTMSP432E4_PD4_U2RX,
        .txPin = UARTMSP432E4_PD5_U2TX,
        .ctsPin = UARTMSP432E4_PIN_UNASSIGNED,
        .rtsPin = UARTMSP432E4_PIN_UNASSIGNED,
        .errorFxn = NULL
    }
};

const UART_Config UART_config[MSP_EXP432E401Y_UARTCOUNT] = {
    {
        .fxnTablePtr = &UARTMSP432E4_fxnTable,
        .object = &uartMSP432E4Objects[MSP_EXP432E401Y_UART3],
        .hwAttrs = &uartMSP432E4HWAttrs[MSP_EXP432E401Y_UART3]
    },
    {
        .fxnTablePtr = &UARTMSP432E4_fxnTable,
        .object = &uartMSP432E4Objects[MSP_EXP432E401Y_UART2],
        .hwAttrs = &uartMSP432E4HWAttrs[MSP_EXP432E401Y_UART2]
    }
};

const uint_least8_t UART_count = MSP_EXP432E401Y_UARTCOUNT;

  • Hello,

        I think there is a misunderstanding of the function.  Please refer to the definition.  Also, the driver is open source, so you can see how the interrupt is enabled in the driver APIs.  

    /*
     *  ======== readTaskCallback ========
     *  This function is called the first time by the UART_read task and tries to
     *  get all the data it can get from the ringBuffer. If it finished, it will
     *  perform the user supplied callback. If it didn't finish, the ISR must handle
     *  the remaining data. By setting the drainByISR flag, the UART_read function
     *  handed over the responsibility to get the remaining data to the ISR.
     */

    Regards,

    Chris

  • Hi Crhis,

    Some more questions,

    1. We are talking about read callback mechanism, should I worry about interrupt or it will be internally managed by driver?

    2. While my callback is called, it sends me buffer ptr and size to read, here do I need to copy data to my local buffer and explicitly free the buffer ptr received?

    3. what is the size of ring buffer? can I set it to custom value?

    Thanks

    /Hp

  • (1) Yes, that is correct.  The interrupt is handled by the driver.  You can configure the callback with the return mode parameter.

    /*!
     *  @brief      UART return mode settings
     *
     *  This enumeration defines the return modes for UART_read() and
     *  UART_readPolling(). This mode only functions when in #UART_DATA_TEXT mode.
     *
     *  #UART_RETURN_FULL unblocks or performs a callback when the read buffer has
     *  been filled.
     *  #UART_RETURN_NEWLINE unblocks or performs a callback whenever a newline
     *  character has been received.
     *
     *  UART operation | UART_RETURN_FULL | UART_RETURN_NEWLINE |
     *  -------------- | ---------------- | ------------------- |
     *  UART_read()    | Returns when buffer is full | Returns when buffer is full or newline was read |
     *  UART_write()   | Sends data as is | Sends data with an additional newline at the end |
     *
     *  @pre        UART driver must be used in #UART_DATA_TEXT mode.
     */
    typedef enum UART_ReturnMode_ {
        /*! Unblock/callback when buffer is full. */
        UART_RETURN_FULL,
    
        /*! Unblock/callback when newline character is received. */
        UART_RETURN_NEWLINE
    } UART_ReturnMode;

    (2) You do not need to free the pointer, just move the data to your local buffer.

    (3) You can edit the ring buffer size in MSP_EXP432E401Y.c

    /*
     *  =============================== UART ===============================
     */
    #include <ti/drivers/UART.h>
    #include <ti/drivers/uart/UARTMSP432E4.h>
    
    UARTMSP432E4_Object uartMSP432E4Objects[MSP_EXP432E401Y_UARTCOUNT];
    unsigned char uartMSP432E4RingBuffer[MSP_EXP432E401Y_UARTCOUNT][32];

    Regards,

    Chris

  • Thanks Chris for clarifying the points.

    One more clarification,

    I am interfacing GSM module with my controller. When I send a command "AT", it responds with some data.

    The response varies in size and I do not know in advance how many bytes I should be receiving.

    1. How to handle this situation?

    2. As I look at the functions, after writing a command when shall I call read?

    3. How do I make sure that my ring buffer does not get overflow and I receive all the bytes in my local buffer?

    4. If we have configured the callback mode, what is the significance of buf ptr while calling UART_read() function? Is it ok to pass NULL?

    Normally for all microcontroller, we receive interrupt and we typically store the data in local buffer. Here its callback mechanism and that too I have to provide number of bytes it should wait and then call my read callback.

    Thanks

    /Hp

  • Hello,

    I have looked at the documentation online and so please refer to this is you want to know where I got my information from.

    (1) You do need to set the ring buffer size.  I would recommend setting the ring buffer to the maximum size possible.  Ideally, you would use the UART_read command to read the minimum number of bytes sent, and then from the content of this first read you could determine how much more to read from the ring buffer.

    (2)  You can call the read at any time.  The ring buffer will fill up with the UART traffic.  If the data is not ready, then the driver will wait until the data is ready before returning.  

    "The UART driver allows full duplex data transfers. Therefore, it is possible to call UART_read() and UART_write() at the same time (for either blocking or callback modes). It is not possible, however, to issue multiple concurrent operations in the same direction. For example, if one thread calls UART_read(uart0, buffer0...), any other thread attempting UART_read(uart0, buffer1...) will result in an error of UART_STATUS_ERROR, until all the data from the first UART_read() has been transferred to buffer0. This applies to both blocking and and callback modes. So applications must either synchronize UART_read() (or UART_write()) calls that use the same UART handle, or check for the UART_STATUS_ERROR return code indicating that a transfer is still ongoing."

    (3) You will need to size your buffer appropriately.  How often does the GSM send data, how quickly can your system respond?  Answering these questions should help you determine the needed size.

    (4) The buffer pointer is what is passed in the configuration.  

    // Read from the UART
    int32_t readCount;
    uint8_t buffer[BUFSIZE];
    readCount = UART_read(uart, buffer, BUFSIZE);

    If you use the null pointer then you will lose the data.  The ring buffer is not intended to be accessed, so please pass a pointer to a buffer.

    Regards,

    Chris

**Attention** This is a public forum