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/LAUNCHXL-CC1350: Help on UART please

Part Number: LAUNCHXL-CC1350
Other Parts Discussed in Thread: CC1310, CC1350

Tool/software: TI-RTOS

Hi TI,

I would like to know how to UART my rxPacket everytime a packet is received. Here are my files, I have tried out many ways but still can't get it right. I have commented out the various UART segments that I tried since I am also not sure which would work. The code is currently a working one which doesn't get stuck anywhere.

6406.rfEchoTx.c

4848.main_5F00_tirtos.c

I have checked out several other posts (listed below) but couldn't understand how to do my simple UART..

https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/t/469335

https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/p/586620/2155171

https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/p/572298/2100093#pi319532=1

My project deadline is almost up, I hope someone can help. Thanks in advance!

Regards,

Adrian

  • I don't get the impression that you have read in detail the code I pointed you to.

    As an example you should post a semaphore around line 439 which you pend on after line 330 in rfEchoTx (change to RF_postCmd)
  • Thanks for the reply TER,
    Can I get an understanding on how this Semaphore works?
    I understand semaphore is like a trigger/control switch. Wikipedia isn’t helping much either
  • Hi TER,

    I have added the semaphores as per your code, but now it is not doing it's tx-rx sequence. 

    Updated code: rfEchoTx.c

  • /*
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /* Board Header files */
    #include "Board.h"
    
    /* Application Header files */
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    
    /***** Defines *****/
    /* Packet TX/RX Configuration */
    #define PAYLOAD_LENGTH      30
    /* Set packet interval to 1000ms */
    #define PACKET_INTERVAL     (uint32_t)(4000000*1.0f)
    /* Set Receive timeout to 500ms */
    #define RX_TIMEOUT          (uint32_t)(4000000*0.5f)
    /* NOTE: Only two data entries supported at the moment */
    #define NUM_DATA_ENTRIES    2
    /* The Data Entries data field will contain:
     * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
     * Max 30 payload bytes
     * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */
    #define NUM_APPENDED_BYTES  2
    
    /* Log radio events in the callback */
    //#define LOG_RADIO_EVENTS
    
    /***** Prototypes *****/
    static void echoCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is aligned to a 4 byte boundary
     * (requirement from the RF core)
     */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(rxDataEntryBuffer, 4)
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      PAYLOAD_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      PAYLOAD_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      PAYLOAD_LENGTH,
                                                      NUM_APPENDED_BYTES)]
                                                      __attribute__((aligned(4)));
    #else
    #error This compiler is not supported
    #endif //defined(__TI_COMPILER_VERSION__)
    
    /* Receive Statistics */
    static rfc_propRxOutput_t rxStatistics;
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t packetLength;
    static uint8_t* packetDataPointer;
    
    static uint8_t txPacket[PAYLOAD_LENGTH];
    static uint8_t rxPacket[PAYLOAD_LENGTH + NUM_APPENDED_BYTES - 1];
    static uint16_t seqNumber;
    
    static volatile bool bRxSuccess = false;
    
    #ifdef LOG_RADIO_EVENTS
    static volatile RF_EventMask eventLog[32];
    static volatile uint8_t evIndex = 0;
    #endif // LOG_RADIO_EVENTS
    
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config pinTable[] =
    {
    #if defined(__CC1352R1_LAUNCHXL_BOARD_H__)
     Board_DIO30_RFSW | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    #endif
    #if defined(__CC1350_LAUNCHXL_BOARD_H__)
     Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    #endif
     Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
     Board_PIN_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
     PIN_TERMINATE
    };
    
    /* semaphore object definitions */
    Semaphore_Struct semStruct;
    Semaphore_Handle semHandle;
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        Semaphore_Params semParams;
        /* Construct a Semaphore object to be use as a resource lock, inital count 1 */
        Semaphore_Params_init(&semParams);
        Semaphore_construct(&semStruct, 0, &semParams);
        /* Obtain instance handle */
        semHandle = Semaphore_handle(&semStruct);
    
        /* Init UART */
        const char  startPrompt[] = "Opening UART and RF:\r\n";
        const char  packetRxPromt[] = "Packet received \r\n";
        UART_Handle uart;
        UART_Params uartParams;
    
        UART_init();
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
    
        uart = UART_open(Board_UART0, &uartParams);
    
        if (uart == NULL) {
             /* UART_open() failed */
              while (1);
        }
    
        UART_write(uart, startPrompt, sizeof(startPrompt));
    
        uint32_t curtime;
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, pinTable);
        if (ledPinHandle == NULL)
        {
            while(1);
        }
    
        if(RFQueue_defineQueue(&dataQueue,
                               rxDataEntryBuffer,
                               sizeof(rxDataEntryBuffer),
                               NUM_DATA_ENTRIES,
                               PAYLOAD_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 1);
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 1);
            while(1);
        }
        
        /* Modify CMD_PROP_TX and CMD_PROP_RX commands for application needs */
        RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
        RF_cmdPropTx.pPkt = txPacket;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
        RF_cmdPropTx.startTrigger.pastTrig = 1;
        RF_cmdPropTx.startTime = 0;
        RF_cmdPropTx.pNextOp = (rfc_radioOp_t *)&RF_cmdPropRx;
        /* Only run the RX command if TX is successful */
        RF_cmdPropTx.condition.rule = COND_STOP_ON_FALSE;
    
        /* Set the Data Entity queue for received data */
        RF_cmdPropRx.pQueue = &dataQueue;
        /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
        /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.maxPktLen = PAYLOAD_LENGTH;
        RF_cmdPropRx.pktConf.bRepeatOk = 0;
        RF_cmdPropRx.pktConf.bRepeatNok = 0;
        RF_cmdPropRx.pOutput = (uint8_t *)&rxStatistics;
        /* Receive operation will end RX_TIMEOUT ms after command starts */
        RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_PREVEND;
        RF_cmdPropRx.endTime = RX_TIMEOUT;
    
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop,
                           (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        /* Get current time */
        curtime = RF_getCurrentTime();
        
        while(1)
        {
            /* Create packet with incrementing sequence number and random payload */
            txPacket[0] = (uint8_t)(seqNumber >> 8);
            txPacket[1] = (uint8_t)(seqNumber++);
            uint8_t i;
            for (i = 2; i < PAYLOAD_LENGTH; i++)
            {
                txPacket[i] = rand();
            }
    
            /* Set absolute TX time to utilize automatic power management */
            curtime += PACKET_INTERVAL;
            RF_cmdPropTx.startTime = curtime;
    
            /* Transmit a packet and wait for its echo.
             * - When the first of the two chained commands (TX) completes, the
             * RF_EventCmdDone event is raised but not RF_EventLastCmdDone
             * - The RF_EventLastCmdDone in addition to the RF_EventCmdDone events
             * are raised when the second, and therefore last, command (RX) in the
             * chain completes
             * -- If the RF core successfully receives the echo it will also raise
             * the RF_EventRxEntryDone event
             * -- If the RF core times out while waiting for the echo it does not
             * raise the RF_EventRxEntryDone event
             */
            RF_EventMask terminationReason =
                    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal,
                              echoCallback, (RF_EventCmdDone | RF_EventRxEntryDone |
                              RF_EventLastCmdDone));
    
            Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
    
            UART_write(uart, &rxPacket, packetLength);
    
            switch(terminationReason)
            {
                case RF_EventCmdDone:
                    // A radio operation command in a chain finished
                    break;
                case RF_EventLastCmdDone:            
                    // A stand-alone radio operation command or the last radio 
                    // operation command in a chain finished.
                    break;         
                case RF_EventCmdCancelled:
                    // Command cancelled before it was started; it can be caused
                // by RF_cancelCmd() or RF_flushCmd().
                    break;
                case RF_EventCmdAborted:
                    // Abrupt command termination caused by RF_cancelCmd() or 
                    // RF_flushCmd().
                    break;  
                case RF_EventCmdStopped:
                    // Graceful command termination caused by RF_cancelCmd() or 
                    // RF_flushCmd().
                    break;  
                default:
                    // Uncaught error event
                    while(1);
            }
            
            uint32_t cmdStatus = ((volatile RF_Op*)&RF_cmdPropTx)->status;
            switch(cmdStatus)
            {
                case PROP_DONE_OK:
                    // Packet transmitted successfully
                    break;
                case PROP_DONE_STOPPED:
                    // received CMD_STOP while transmitting packet and finished
                    // transmitting packet
                    break;
                case PROP_DONE_ABORT:
                    // Received CMD_ABORT while transmitting packet
                    break;
                case PROP_ERROR_PAR:
                    // Observed illegal parameter
                    break;
                case PROP_ERROR_NO_SETUP:
                    // Command sent without setting up the radio in a supported
                    // mode using CMD_PROP_RADIO_SETUP or CMD_RADIO_SETUP
                    break;
                case PROP_ERROR_NO_FS:
                    // Command sent without the synthesizer being programmed
                    break;
                case PROP_ERROR_TXUNF:
                    // TX underflow observed during operation
                    break;
                default:
                    // Uncaught error event - these could come from the
                    // pool of states defined in rf_mailbox.h
                    while(1);
            }
        }
    }
    
    static void echoCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    #ifdef LOG_RADIO_EVENTS
        eventLog[evIndex++ & 0x1F] = e;
    #endif// LOG_RADIO_EVENTS
    
        if((e & RF_EventCmdDone) && !(e & RF_EventLastCmdDone))
        {
            /* Successful TX */
            /* Toggle LED1, clear LED2 to indicate TX */
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED1,
                               !PIN_getOutputValue(Board_PIN_LED1));
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 0);
        }
        else if(e & RF_EventRxEntryDone)
        {
            /* Successful RX */
            bRxSuccess = true;
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &(currentDataEntry->data):
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte
             */
            packetLength      = *(uint8_t *)(&(currentDataEntry->data));
            packetDataPointer = (uint8_t *)(&(currentDataEntry->data) + 1);
    
            /* Copy the payload + status byte to the rxPacket variable */
            memcpy(rxPacket, packetDataPointer, (packetLength + 1));
    
            //Semaphore_post(semHandle);
    
            /* Check the packet against what was transmitted */
            int16_t status = memcmp(txPacket, rxPacket, packetLength);
    
            if(status == 0)
            {
    
                /* Toggle LED1, clear LED2 to indicate RX */
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED1,
                                   !PIN_getOutputValue(Board_PIN_LED1));
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 0);
                Semaphore_post(semHandle);
            }
            else
            {
                /* Error Condition: set both LEDs */
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 1);
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 1);
            }
    
            RFQueue_nextEntry();
        }
        else if((e & RF_EventLastCmdDone) && !(e & RF_EventRxEntryDone))
        {
            if(bRxSuccess == true)
            {
                /* Received packet successfully but RX command didn't complete at
                 * the same time RX_ENTRY_DONE event was raised. Reset the flag
                 */
                bRxSuccess = false;
            }
            else
            {
                /* RX timed out */
                /* Set LED2, clear LED1 to indicate TX */
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 0);
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 1);
            }
        }
        else
        {
            /* Error Condition: set both LEDs */
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, 1);
            PIN_setOutputValue(ledPinHandle, Board_PIN_LED2, 1);
        }
    }
    

    This which looks very similar seems to be working on my end. 

    In this case it's possible to skip the semaphore and do:

    RF_EventMask terminationReason =
    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal,
    echoCallback, (RF_EventCmdDone | RF_EventRxEntryDone |
    RF_EventLastCmdDone));

    UART_write(uart, &rxPacket, packetLength);

    since the RX times out after a 0.5 second and the next tx event is scheduled after 1 second. 

  • Hi TER,

    Thanks for the help! I have updated my parameters into your code, and it works fine until I use lines 145 & 181. 

    rfEchoTx_5F00_ByTER.c

    From what I learnt from a colleague, UART uses TXD port. But I don't have a connector for that port. Is it possible to change to another pin for UART_open? I tried changing with lines 145 & 181 but it stops working then. 

  • The Launchpad has the UART pins on CC1310 connected to the UART pins to the Tiva used as XDS110 and then as a channel over USB.

    You are free to map the UART pins to whatever pins you like (See CC1310_LAUNCHPAD.h) and attached a UART interface from a different chip to these pins.
  • CC1350 is same as CC1310?
    From CC1350_LAUNCHPAD.h and the pin mapping found in the original launchpad box, IOID3 is for UART tx. But I don’t see why my lines 145 & 181 don’t work?
  • Because CC1310_LAUNCHXL_UART_TX is defined in the BoardGpioInitTable called from Board_initGeneral(); in main.
  • In that case, Is it right for me to comment out line180 and uncomment line 181?

    I did this and it did not work
  • Why do you want to do that when the pins already are defined?
  • Oh no, Sorry my bad. I think my problems might be on the other end. Thanks for the help TER!

    Thank you for your patience!