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.

LAUNCHXL-CC26X2R1: Uart interrupt

Part Number: LAUNCHXL-CC26X2R1

Hi,

i need to read a GPS nmea format with UART rx and need to tirgger the message with carriege return every second at 9600 baud.

Is it possible to add an interrupt on Uart RX?

Every message received should be going to a interrupt service routine i think.

Now i implemented the uart Rx with callback, so i check the receive circular buffer size and if it is bigger than an 80 bytes i send the read command.

I have changed the circular buffer size to 160 and set a timer clock with 250ms so i can get the message if it is over 80 bytes.

The callback function is then called and i send a Event_Post to parse the value in NMEA format.

But at the moment i dont get the right sequence and i think i am missing or losing values due to time clock event not been so quick as expected.

so here is the code:

#include "YIC71513PGMGG.h"

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART2.h>

/* Driver configuration */
#include "ti_drivers_config.h"

#include "simple_peripheral.h"

#include "nmea0183.h"

#include <string.h>
#include <xdc/std.h>
#include <stdbool.h>

#include <ti/sysbios/knl/Event.h>



UART2_Handle uart;
UART2_Params uartParams;

size_t numBytesRead;
size_t bytesRead;
size_t byteAvailable=0;
char line[MINMEA_MAX_SENTENCE_LENGTH * 2];
char input;
bool isReading = false;
bool isReadingClear = false;
/*
 *  ======== callbackFxn ========
 */
void callbackFxn(UART2_Handle handle, void *buffer, size_t count, void *userArg, int_fast16_t status)
{
    if (status != UART2_STATUS_SUCCESS)
    {
        /* RX error occured in UART2_read() */
    }
    else {
        if(!isReadingClear) {
            memcpy(line, buffer, count);
            numBytesRead = count;
            OPENWIND_Event(OW_WIND_GPS_READ);
        }
    }
    isReading=false;
    isReadingClear=false;
}


void YIC71513PGMGG_uart_open() {


    GPIO_resetConfig(CONFIG_GPIO_UART2_0_TX);
    GPIO_resetConfig(CONFIG_GPIO_UART2_0_RX);

    UART2_Params_init(&uartParams);
    uartParams.baudRate     = 9600;
    uartParams.readReturnMode = UART2_ReadReturnMode_PARTIAL;//UART2_ReadReturnMode_FULL;
    uartParams.dataLength = UART2_DataLen_8;
    uartParams.stopBits = UART2_StopBits_1;
    uartParams.readMode = UART2_Mode_CALLBACK;
    uartParams.readCallback = callbackFxn;

    uart = UART2_open(CONFIG_UART2_0, &uartParams);



    if (uart == NULL)
    {
       /* UART2_open() failed */
    }
    else
        UART2_rxEnable(uart);

}

void YIC71513PGMGG_uart_close() {

    UART2_rxDisable(uart);
    UART2_close(uart);

    GPIO_resetConfig(CONFIG_GPIO_UART2_0_TX);
    GPIO_resetConfig(CONFIG_GPIO_UART2_0_RX);

    GPIO_setConfig(CONFIG_GPIO_UART2_0_TX, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
    GPIO_setConfig(CONFIG_GPIO_UART2_0_RX, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);

    GPIO_write(CONFIG_GPIO_UART2_0_TX, 0);
    GPIO_write(CONFIG_GPIO_UART2_0_RX, 0);

}

void YIC71513PGMGG_uart_read() {

    if(isReading)
        return;
    byteAvailable = UART2_getRxCount(uart);
    if(byteAvailable >= MINMEA_MAX_SENTENCE_LENGTH) {
        if(!isReadingClear)
            YIC71513PGMGG_read(MINMEA_MAX_SENTENCE_LENGTH);
        else
            YIC71513PGMGG_read(byteAvailable);
    }
}

void YIC71513PGMGG_read(int lenght){
    isReading=true;
    UART2_read(uart, &input, lenght, &bytesRead);
}

void YIC71513PGMGG_uart_parse() {

    switch (minmea_sentence_id(line, false)) {
        case MINMEA_SENTENCE_RMC: {
            struct minmea_sentence_rmc frame;
            if (minmea_parse_rmc(&frame, line)) {
                /*printf(INDENT_SPACES "$xxRMC: raw coordinates and speed: (%d/%d,%d/%d) %d/%d\n",
                        frame.latitude.value, frame.latitude.scale,
                        frame.longitude.value, frame.longitude.scale,
                        frame.speed.value, frame.speed.scale);
                printf(INDENT_SPACES "$xxRMC fixed-point coordinates and speed scaled to three decimal places: (%d,%d) %d\n",
                        minmea_rescale(&frame.latitude, 1000),
                        minmea_rescale(&frame.longitude, 1000),
                        minmea_rescale(&frame.speed, 1000));
                printf(INDENT_SPACES "$xxRMC floating point degree coordinates and speed: (%f,%f) %f\n",
                        minmea_tocoord(&frame.latitude),
                        minmea_tocoord(&frame.longitude),
                        minmea_tofloat(&frame.speed));*/
            }
            else {
                //printf(INDENT_SPACES "$xxRMC sentence is not parsed\n");
            }
        } break;

        case MINMEA_SENTENCE_GGA: {
            struct minmea_sentence_gga frame;
            if (minmea_parse_gga(&frame, line)) {
                //printf(INDENT_SPACES "$xxGGA: fix quality: %d\n", frame.fix_quality);
            }
            else {
               // printf(INDENT_SPACES "$xxGGA sentence is not parsed\n");
            }
        } break;

        case MINMEA_SENTENCE_GST: {
            struct minmea_sentence_gst frame;
            if (minmea_parse_gst(&frame, line)) {
                /*printf(INDENT_SPACES "$xxGST: raw latitude,longitude and altitude error deviation: (%d/%d,%d/%d,%d/%d)\n",
                        frame.latitude_error_deviation.value, frame.latitude_error_deviation.scale,
                        frame.longitude_error_deviation.value, frame.longitude_error_deviation.scale,
                        frame.altitude_error_deviation.value, frame.altitude_error_deviation.scale);
                printf(INDENT_SPACES "$xxGST fixed point latitude,longitude and altitude error deviation"
                       " scaled to one decimal place: (%d,%d,%d)\n",
                        minmea_rescale(&frame.latitude_error_deviation, 10),
                        minmea_rescale(&frame.longitude_error_deviation, 10),
                        minmea_rescale(&frame.altitude_error_deviation, 10));
                printf(INDENT_SPACES "$xxGST floating point degree latitude, longitude and altitude error deviation: (%f,%f,%f)",
                        minmea_tofloat(&frame.latitude_error_deviation),
                        minmea_tofloat(&frame.longitude_error_deviation),
                        minmea_tofloat(&frame.altitude_error_deviation));*/
            }
            else {
               // printf(INDENT_SPACES "$xxGST sentence is not parsed\n");
            }
        } break;

        case MINMEA_SENTENCE_GSV: {
            struct minmea_sentence_gsv frame;
            if (minmea_parse_gsv(&frame, line)) {
             /*   printf(INDENT_SPACES "$xxGSV: message %d of %d\n", frame.msg_nr, frame.total_msgs);
                printf(INDENT_SPACES "$xxGSV: satellites in view: %d\n", frame.total_sats);
                for (int i = 0; i < 4; i++)
                    printf(INDENT_SPACES "$xxGSV: sat nr %d, elevation: %d, azimuth: %d, snr: %d dbm\n",
                        frame.sats[i].nr,
                        frame.sats[i].elevation,
                        frame.sats[i].azimuth,
                        frame.sats[i].snr);*/
            }
            else {
             //   printf(INDENT_SPACES "$xxGSV sentence is not parsed\n");
            }
        } break;

        case MINMEA_SENTENCE_VTG: {
           struct minmea_sentence_vtg frame;
           if (minmea_parse_vtg(&frame, line)) {
               /* printf(INDENT_SPACES "$xxVTG: true track degrees = %f\n",
                       minmea_tofloat(&frame.true_track_degrees));
                printf(INDENT_SPACES "        magnetic track degrees = %f\n",
                       minmea_tofloat(&frame.magnetic_track_degrees));
                printf(INDENT_SPACES "        speed knots = %f\n",
                        minmea_tofloat(&frame.speed_knots));
                printf(INDENT_SPACES "        speed kph = %f\n",
                        minmea_tofloat(&frame.speed_kph));*/
               OpenWind_SOG = (uint16_t)(minmea_tofloat(&frame.speed_knots) * 10);
               OpenWind_COG = (uint16_t)(minmea_tofloat(&frame.true_track_degrees));
           }
           else {
                //printf(INDENT_SPACES "$xxVTG sentence is not parsed\n");
           }
        } break;

        case MINMEA_SENTENCE_ZDA: {
            struct minmea_sentence_zda frame;
            if (minmea_parse_zda(&frame, line)) {
               /* printf(INDENT_SPACES "$xxZDA: %d:%d:%d %02d.%02d.%d UTC%+03d:%02d\n",
                       frame.time.hours,
                       frame.time.minutes,
                       frame.time.seconds,
                       frame.date.day,
                       frame.date.month,
                       frame.date.year,
                       frame.hour_offset,
                       frame.minute_offset);*/
            }
            else {
               // printf(INDENT_SPACES "$xxZDA sentence is not parsed\n");
            }
        } break;

        case MINMEA_INVALID: {
            //isReadingClear=true;
        } break;

        default: {

        } break;
    }
}

  • Hi Michael,

    You can receive full details concerning UART2 operation from the TI Drivers Runtime APIs.  There are not any other UART callbacks except for eventCallback.  You can use UART2_readTimeout if you would like to implement timeout capabilities to UART read functionality.  Otherwise, I recommend posting an event and exiting the UART hardware interrupt as soon as possible so that subsequent bytes can be read.

    Regards,
    Ryan

  • Hi Ryan,

    in will check, the problem i also have is that the bluetooth connection breaks and i dont know really the reason. I use simple_peripheral as base project and if i pause the debugger i see that the controller is stuck here:

    "Error_policy_D == Error_SPIN"

    Locking at the stack it doesnt give me the reason why.

    But if i dont use the GPS/UART RX everything works.

    This happens if i use the callback function and Uart_readTimeout.

    Maybe the GPS Event is taking to long? Or do you think my  circular buffer with 120 Bytes is too big? 

  • Have you already removed the UART2/Display module, or added another UART2 instance to avoid conflicting with the User Interface?  Does the spinlock error happen every time the Uart_readTimeout is called, during a specific status, or occasionally at what seems to be random?  Your UART callback should be serviced as quick as possible, preferably storing the buffer and immediately exiting without calling any application functions such as OPENWIND_Event.  You can reference the BLE5-Stack Debugging Guide for tips towards using the ROV or evaluating Heap Metrics.

    Regards,
    Ryan

  • Hi Ryan, thanks for the debugging guide

    I removed the UART2/Display and have only my instance. 

    So i tried 2 methods, one with call back and one with Uart2_Read_TimeOut.

    The callback method always crashed and the Uart2_Read_TimeOut seems to be a little more stable.

    OPENWIND_Event calls Event_Post() with my event ID inside the callback, this will only parse whats inside the receive buffer which i copied with memcpy().

    So the callback function is called from UART2 Driver right? If i dont serve that as quick as possible it will crash?

    Maybe i should whatch the state of each task to see the reason?

  • The UART2 driver triggers the callback function.  There could be an issue if the UART2 callback is not serviced before another UART2_read call or does not finish before the BLE stack requires servicing.  You can use the ROV to determine more about the existing task states.

    Regards,
    Ryan