LP-CC1352P7: CC1352P7 - TX-RX Chain Command Not Receiving Data in Proprietary Mode (868 MHz)

Part Number: LP-CC1352P7
Other Parts Discussed in Thread: CC1352P7

Tool/software:

Environment

  • Device: CC1352P7
  • SDK: SimpleLink SDK 8.30
  • RF Mode: Proprietary Sub-1 GHz (868 MHz)
  • Configuration: 1 Mbps, 350 kHz Deviation, 2-GFSK, 2.2 MHz RX Bandwidth

We're having issues with TX-RX command chains. The TX-only and RX-only operations work perfectly, but when chaining TX->RX commands, the RX portion never receives data, even though we know the remote device is transmitting. Our protocol requires the RX window to open shortly(with small delay) after TX completes.

Test Scenario

  1. Device A : Sends a request packet, then immediately listens for response packet using TX-RX chain
  2. Device B : Receives packet correctly, immediately sends response packet
  3. Issue: Device A completes the chain (EVT_CHAIN_DONE) but never receives the connection request packet


static int radio_start_tx_rx_chain(void) {
    /* Reset command status */
    RF_cmdPropTx.status = 0;
    RF_cmdPropRx.status = 0;

    /* Configure TX */
    RF_cmdPropTx.pPkt = g_radio.current_op.tx_data;
    RF_cmdPropTx.pktLen = g_radio.current_op.tx_length;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
    RF_cmdPropTx.startTrigger.pastTrig = 1;
    RF_cmdPropTx.pNextOp = (RF_Op*)&RF_cmdPropRx;
    RF_cmdPropTx.condition.rule = COND_ALWAYS;

    /* Configure RX */
    RF_cmdPropRx.maxPktLen = RADIO_MAX_PACKET_LEN;
    RF_cmdPropRx.pQueue = &g_radio.rx_data_queue;
    RF_cmdPropRx.startTrigger.triggerType = TRIG_NOW;
    RF_cmdPropRx.startTrigger.pastTrig = 1;
    RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
    RF_cmdPropRx.endTime = 8000;  // 2ms window
    RF_cmdPropRx.pNextOp = NULL;
    RF_cmdPropRx.condition.rule = COND_NEVER;

    /* Reset RX queue */
    g_radio.rx_data_entry.status = DATA_ENTRY_PENDING;

    /* Post chain */
    g_radio.cmd_handle = RF_postCmd(g_radio.rf_handle,
                                    (RF_Op*)&RF_cmdPropTx,
                                    RF_PriorityNormal,
                                    radio_rf_callback,
                                    RF_EventLastCmdDone);

    return (g_radio.cmd_handle >= 0) ? 0 : -1;
}



static int radio_start_rx(void) {
    /* Reset RX data entry */
    g_radio.rx_data_entry.status = DATA_ENTRY_PENDING;

    /* Use global RF_cmdPropRx, not cmd_rx_adv */
    RF_cmdPropRx.status = 0;
    RF_cmdPropRx.maxPktLen = RADIO_MAX_PACKET_LEN;
    RF_cmdPropRx.pQueue = &g_radio.rx_data_queue;

    /* Configure what gets appended */
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
    RF_cmdPropRx.rxConf.bIncludeHdr = 1;      /* Include length byte */
    RF_cmdPropRx.rxConf.bIncludeCrc = 0;      /* Don't include CRC */
    RF_cmdPropRx.rxConf.bAppendRssi = 1;      /* Append RSSI */
    RF_cmdPropRx.rxConf.bAppendTimestamp = 1; /* Append timestamp */
    RF_cmdPropRx.rxConf.bAppendStatus = 1;    /* Append status */

    /* Keep RX on for multiple packets */
    RF_cmdPropRx.pktConf.bRepeatOk = 1;
    RF_cmdPropRx.pktConf.bRepeatNok = 1;

    if (g_radio.current_op.rx_timeout_rat > 0) {
        RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
        RF_cmdPropRx.endTime = g_radio.current_op.rx_timeout_rat;
    } else {
        RF_cmdPropRx.endTrigger.triggerType = TRIG_NEVER;
    }

    /* Post RX command directly (no chaining) */
    g_radio.cmd_handle = RF_postCmd(g_radio.rf_handle,
                                    (RF_Op*)&RF_cmdPropRx,
                                    RF_PriorityNormal,
                                    radio_rf_callback,
                                    RF_EventRxEntryDone | RF_EventLastCmdDone);

    if (g_radio.cmd_handle < 0) {
        g_radio.state = RADIO_STATE_IDLE;
        return -1;
    }

    return 0;
}



static int radio_start_tx(void) {
    /* Prepare TX packet with length byte */
    g_radio.tx_packet[0] = g_radio.current_op.tx_length;
    memcpy(&g_radio.tx_packet[1], g_radio.current_op.tx_data,
           g_radio.current_op.tx_length);

    /* Reset global commands */
    RF_cmdPropTx.status = 0;
    RF_cmdPropRx.status = 0;

    RF_cmdPropTx.pPkt = g_radio.current_op.tx_data;
    RF_cmdPropTx.pktLen = g_radio.current_op.tx_length;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
    RF_cmdPropTx.startTrigger.pastTrig = 1;
    RF_cmdPropTx.pNextOp = NULL;
    RF_cmdPropTx.condition.rule = COND_ALWAYS;

    /* Post chain */
    g_radio.cmd_handle = RF_postCmd(g_radio.rf_handle,
                                    (RF_Op*)&RF_cmdPropTx,
                                    RF_PriorityNormal,
                                    radio_rf_callback,
                                    RF_EventLastCmdDone);

    return (g_radio.cmd_handle >= 0) ? 0 : -1;
}



Questions

  1. Is there a specific configuration required for TX-RX chains in proprietary mode that differs from the examples?
  2. Are there timing constraints between TX end and RX start that we should be aware of?
  3. Should we be using CMD_PROP_TX_ADV/CMD_PROP_RX_ADV instead of the basic commands?
  4. Is there a minimum or maximum gap required between TX and RX in a chain?
  5. Most importantly: Are there any reference examples of TX->RX command chains in proprietary mode? We've searched the SDK but only found TX-only chains and RX-only operations.

Any guidance on proper TX-RX chain configuration for proprietary mode would be greatly appreciated. We specifically need the RX to start immediately after TX completes to implement our protocol correctly.



  • Hi Sharan,

    When switching from Tx to Rx there is a certain delay for the radio, I believe a couple of hundred uS. What's your requirement here? 

    Cheers,

    Marie

  • You should output the LNA and Pa signals on some pins for debugging (both on your transmitter and receiver) to make sure that your receiver is in RX while you are transmitting:

    Routing RF Core Signals to Physical Pins — SimpleLinkTm CC13XX/CC26XX SDK Proprietary RF User's Guide 7.30.00 documentation

    It might also be a good idea to avoid having a timeout on the chained RX while debugging, to make sure that your time in RX is not too short.

    below is a modified version of the rfPacketRX example that uses a TX/RX command chain.

    The example was tested towards SmartRF Studio, so I did not test with a timeout in RX, as I had to change window in Studio from RX to TX when testing this.

    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/GPIO.h>
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /* Board Header files */
    #include "ti_drivers_config.h"
    
    /* Application Header files */
    #include "RFQueue.h"
    #include <ti_radio_config.h>
    
    /***** Defines *****/
    
    /* Packet RX Configuration */
    #define DATA_ENTRY_HEADER_SIZE  8  /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH              255 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES        2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES      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 PAYLOAD_LENGTH          5
    
    
    /***** Prototypes *****/
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is 4 byte aligned (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,
                                                      MAX_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,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)]
                                                      __attribute__((aligned(4)));
    #else
    #error This compiler is not supported.
    #endif
    
    /* 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 uint16_t seqNumber;
    
    
    static uint8_t rxPacket[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
    static uint8_t txPacket[PAYLOAD_LENGTH];
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_setConfigAndMux(CONFIG_GPIO_RLED, GPIO_CFG_OUT_STD, IOC_PORT_RFC_GPO0);
        GPIO_setConfigAndMux(CONFIG_GPIO_GLED, GPIO_CFG_OUT_STD, IOC_PORT_RFC_GPO1);
    
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
    
        /* Modify CMD_PROP_RX command for application needs */
        /* 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 = MAX_LENGTH;
    
        //RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
        //RF_cmdPropRx.endTime = 8000;  // 2ms window
    
        RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
        RF_cmdPropTx.pPkt = txPacket;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
    
        RF_cmdPropTx.pNextOp = (rfc_radioOp_t*)&RF_cmdPropRx;
        RF_cmdPropTx.condition.rule = COND_ALWAYS;
    
        /* 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);
    
        while(1)
        {
            txPacket[0] = (uint8_t)(seqNumber >> 8);
            txPacket[1] = (uint8_t)(seqNumber++);
            uint8_t i;
            for (i = 2; i < PAYLOAD_LENGTH; i++)
            {
                txPacket[i] = rand();
            }
            RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            //GPIO_toggle(CONFIG_GPIO_RLED);
    
            /* 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 + the status byte to the packet variable */
            memcpy(rxPacket, packetDataPointer, (packetLength + 1));
    
            RFQueue_nextEntry();
        }
    }

    Siri

  • Hi Marie,

    I tested with a ~2 ms delay for now, but we’re flexible to adjust it based on the radio configuration. My main goal is to get the TX-RX chain command working.

    Could you please review and confirm whether the function radio_start_tx_rx_chain() looks correct?

    For reference, when I split the TX and RX into separate commands, it works as expected. It would also be very helpful if you could point me to any example implementations of a chain command.


     */
    static int radio_start_tx_rx_chain(void) {
        /* Run FS first */
        RF_cmdFs.frequency = radio_channel_to_frequency(g_radio.current_op.channel);
        RF_cmdFs.fractFreq = 0;
    
        RF_EventMask fsResult = RF_runCmd(g_radio.rf_handle,
                                         (RF_Op*)&RF_cmdFs,
                                         RF_PriorityNormal,
                                         NULL, 0);
    
        if (!(fsResult & RF_EventLastCmdDone)) {
            return -1;
        }
    
        /* Step 1: Execute TX synchronously with runCmd */
        RF_cmdPropTx.status = 0;
        RF_cmdPropTx.pPkt = g_radio.current_op.tx_data;
        RF_cmdPropTx.pktLen = g_radio.current_op.tx_length;
        RF_cmdPropTx.pktConf.bFsOff = 0;  /* Keep FS on for RX */
        RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropTx.startTrigger.pastTrig = 1;
        RF_cmdPropTx.pNextOp = NULL;  /* No chaining */
        RF_cmdPropTx.condition.rule = COND_NEVER;
    
        /* Synchronous TX - blocks until complete */
        RF_EventMask txResult = RF_runCmd(g_radio.rf_handle,
                                          (RF_Op*)&RF_cmdPropTx,
                                          RF_PriorityNormal,
                                          NULL, 0);
    
        log_printf("TX complete: status=0x%04X, events=0x%08X",
                   RF_cmdPropTx.status, txResult);
    
        /* Check TX success */
        if (!(txResult & RF_EventLastCmdDone) ||
            RF_cmdPropTx.status != PROP_DONE_OK) {
            log_printf("TX failed in chain");
            g_radio.state = RADIO_STATE_IDLE;
            return -1;
        }
    
        /* Call TX callback */
        if (g_radio.current_op.on_tx_done) {
            g_radio.current_op.on_tx_done(RADIO_RESULT_OK);
        }
        g_radio.stats.tx_count++;
    
        /* Step 2: Start RX asynchronously with postCmd */
        RF_cmdPropRx.status = 0;
        RF_cmdPropRx.pktConf.bFsOff = 1;  /* Can turn off FS after RX */
        RF_cmdPropRx.pktConf.bRepeatOk = 0;
        RF_cmdPropRx.pktConf.bRepeatNok = 0;
        RF_cmdPropRx.pktConf.bUseCrc = 1;
        RF_cmdPropRx.pktConf.bVarLen = 1;
    
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
        RF_cmdPropRx.rxConf.bIncludeHdr = 1;
        RF_cmdPropRx.rxConf.bIncludeCrc = 0;
        RF_cmdPropRx.rxConf.bAppendRssi = 1;
        RF_cmdPropRx.rxConf.bAppendTimestamp = 0;
        RF_cmdPropRx.rxConf.bAppendStatus = 1;
    
        RF_cmdPropRx.maxPktLen = RADIO_MAX_PACKET_LEN;
        RF_cmdPropRx.pQueue = &g_radio.rx_data_queue;
    
        /* RX starts immediately */
        RF_cmdPropRx.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropRx.startTrigger.pastTrig = 1;
        RF_cmdPropRx.startTime = 0;
    
        /* RX window */
        RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
        RF_cmdPropRx.endTime = g_radio.current_op.rx_timeout_rat ?: 8000;
    
        RF_cmdPropRx.pNextOp = NULL;
        RF_cmdPropRx.condition.rule = COND_NEVER;
    
        /* Reset RX queue */
        g_radio.rx_data_entry.status = DATA_ENTRY_PENDING;
    
        log_printf("Starting RX after TX, timeout=%d RAT", RF_cmdPropRx.endTime);
    
        /* Post RX command asynchronously */
        g_radio.cmd_handle = RF_postCmd(g_radio.rf_handle,
                                        (RF_Op*)&RF_cmdPropRx,
                                        RF_PriorityNormal,
                                        radio_rf_callback,
                                        RF_EventRxEntryDone | RF_EventLastCmdDone);
    
        if (g_radio.cmd_handle < 0) {
            log_printf("RX post failed");
            g_radio.state = RADIO_STATE_IDLE;
            return -1;
        }
    
        /* State is now waiting for RX */
        g_radio.state = RADIO_STATE_RX;  /* Treat as RX-only for callback */
    
        return 0;
    }

  • Please look at the code example I just posted and compare your code with it.

    It has been tested and works as expected with the 1 Mbps PHY from SmartRF Studio.

    Siri

  • Hi Siri, Thanks. I'll check it.

    Regards,
    Sharan

  • Hi Siri,

    Thanks again for the example, it really helped. With a few timing/delay tweaks, I was able to get the TX-RX chain command working. I've pasted the working function below.

    Now, I'm trying to make the reverse role(RX-TX) work. I followed the TX-RX syntax and adapted it for RX-TX, but it doesn't seems to work. I've included the function below for your reference. 

    Could you please review the command configuration? I'll adjust the timings as needed for our test setup.

    Now, I want to make the reverse role work. I followed the syntax of the TX-RX and modified for reverse but it doesn't work. Pasting the function below for you reference, please check the command configuration, timings I'll tweak according to our test setup.

    Appreciate your help with this!

    static int radio_start_rx_tx_chain(void) {
        /* Reset commands */
        RF_cmdPropRx.status = 0;
        RF_cmdPropTx.status = 0;
    
        /* Setup RX first (slave receives first) */
        RF_cmdPropRx.commandNo = CMD_PROP_RX;
        RF_cmdPropRx.pQueue = &g_radio.rx_data_queue;
        RF_cmdPropRx.maxPktLen = RADIO_MAX_PACKET_LEN;
        RF_cmdPropRx.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropRx.startTrigger.pastTrig = 1;
    
        RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
        RF_cmdPropRx.endTime = 40000;
    
        /* RX configuration */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
        RF_cmdPropRx.rxConf.bIncludeHdr = 1;
        RF_cmdPropRx.rxConf.bAppendRssi = 1;
        RF_cmdPropRx.rxConf.bAppendStatus = 1;
    
        /* Chain to TX after RX completes */
        RF_cmdPropRx.pNextOp = (rfc_radioOp_t*)&RF_cmdPropTx;
        RF_cmdPropRx.condition.rule = COND_ALWAYS;  /* Always go to TX even if RX times out */
    
        /* Setup TX to follow RX */
        RF_cmdPropTx.pPkt = g_radio.current_op.tx_data;
        RF_cmdPropTx.pktLen = g_radio.current_op.tx_length;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_REL_PREVEND;
        RF_cmdPropTx.startTrigger.pastTrig = 1;
        RF_cmdPropTx.startTime = 7000;
    
        /* TX is end of chain */
        RF_cmdPropTx.pNextOp = NULL;
        RF_cmdPropTx.condition.rule = COND_NEVER;
    
        /* Reset RX queue */
        g_radio.rx_data_entry.status = DATA_ENTRY_PENDING;
    
        /* Post the chain starting with RX */
        g_radio.cmd_handle = RF_postCmd(g_radio.rf_handle,
                                        (RF_Op*)&RF_cmdPropRx,  /* Start with RX! */
                                        RF_PriorityNormal,
                                        radio_rf_callback,
                                        RF_EventRxEntryDone | RF_EventLastCmdDone);
    
        return (g_radio.cmd_handle >= 0) ? 0 : -1;
    }



    static int radio_start_rx_tx_chain(void) {
        /* Reset commands */
        RF_cmdPropRx.status = 0;
        RF_cmdPropTx.status = 0;
    
        /* Setup RX first */
        RF_cmdPropRx.commandNo = CMD_PROP_RX;
        RF_cmdPropRx.pQueue = &g_radio.rx_data_queue;
        RF_cmdPropRx.maxPktLen = RADIO_MAX_PACKET_LEN;
        RF_cmdPropRx.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropRx.startTrigger.pastTrig = 1;
        
        /* RX window from request */
        if (g_radio.current_op.rx_timeout_rat > 0) {
            RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
            RF_cmdPropRx.endTime = g_radio.current_op.rx_timeout_rat;
        } else {
            RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;
            RF_cmdPropRx.endTime = 40000;
        }
        
        /* RX configuration */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
        RF_cmdPropRx.rxConf.bIncludeHdr = 1;
        RF_cmdPropRx.rxConf.bAppendRssi = 1;
        RF_cmdPropRx.rxConf.bAppendStatus = 1;
        
        RF_cmdPropRx.pNextOp = (rfc_radioOp_t*)&RF_cmdPropTx;
        RF_cmdPropRx.condition.rule = COND_STOP_ON_TRUE;  /* Stop after receiving packet */
    
        /* Setup TX to follow */
        RF_cmdPropTx.commandNo = CMD_PROP_TX;
        RF_cmdPropTx.pPkt = g_radio.current_op.tx_data;
        RF_cmdPropTx.pktLen = g_radio.current_op.tx_length;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_REL_PREVEND;
        RF_cmdPropTx.startTrigger.pastTrig = 1;
        RF_cmdPropTx.startTime = 7000;
        RF_cmdPropTx.pNextOp = NULL;  /* End of chain */
        RF_cmdPropTx.condition.rule = COND_NEVER;  /* Always execute if reached */
    
        /* Reset RX queue */
        g_radio.rx_data_entry.status = DATA_ENTRY_PENDING;
    
        log_printf("radio_start_rx_tx_chain");
    
        /* Post the chain starting with RX */
        g_radio.cmd_handle = RF_postCmd(g_radio.rf_handle,
                                        (RF_Op*)&RF_cmdPropRx,  /* Start with RX! */
                                        RF_PriorityNormal,
                                        radio_rf_callback,
                                        RF_EventRxEntryDone | RF_EventLastCmdDone);
    
        return (g_radio.cmd_handle >= 0) ? 0 : -1;
    }