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.

[参考译文] CC1310:成功接收到射频数据包后发送 ACK 数据包

Guru**** 2465890 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1535072/cc1310-sending-ack-packet-after-receiving-a-rf-packet-successfully

器件型号:CC1310

工具/软件:

我有一个需要在 2 个器件之间进行双向通信的应用。 该代码应在接收到有效数据包之后发送 ACK 数据包、但出于某种原因、未传输 ACK 数据包。 我找不到问题所在、配置对我来说是正确的、我是否遗漏了一些内容?

下面是初始化射频驱动程序及其所用函数的任务。 如果我使用 RF_runCmd 启动命令来启动命令、接收和发送数据包可以正常工作、但 RF_cmdPropTxAck 命令在 RF_cmdPropRxSniff 命令之后不运行

static void rf_init_task(UArg arg0, UArg arg1) {
    // Initialize the radio
    RF_Params rfParams;
    RF_Params_init(&rfParams);

    // Create queue and data entries
    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);
    }

    // Get address
    rf_generate_addr();

    initializeTxAdvCmdFromTxCmd(&RF_cmdPropTxAck, &RF_cmdPropTx);
    RF_cmdPropTxAck.commandNo = CMD_PROP_TX_ADV;
    RF_cmdPropTxAck.startTrigger.triggerType = TRIG_NOW;
    RF_cmdPropTxAck.pPkt = (uint8_t*)&ACK;
    RF_cmdPropTxAck.pktLen = PAYLOAD_LENGTH;

    ACK.dst_addr = *(uint64_t *)filter_address;
    ACK.data.raw = 0;
    ACK.cmd = RF_CMD_ACK;

    initializeSniffCmdFromRxCmd(&RF_cmdPropRxSniff, &RF_cmdPropRx);
    RF_cmdPropRxSniff.condition.rule = COND_STOP_ON_FALSE;
    RF_cmdPropRxSniff.pNextOp = (RF_Op*)&RF_cmdPropTxAck; // Run TxAck command after a valid packet received on RxSniff

    // Configure RX part of RX_SNIFF command
    RF_cmdPropRxSniff.pQueue = &dataQueue;
    RF_cmdPropRxSniff.pOutput = (uint8_t*) &rx_statistics;
    RF_cmdPropRxSniff.maxPktLen = MAX_LENGTH;

    // Discard ignored packets and CRC errors from Rx queue
    RF_cmdPropRxSniff.rxConf.bAutoFlushIgnored = 1;
    RF_cmdPropRxSniff.rxConf.bAutoFlushCrcErr = 1;

    RF_cmdPropRxSniff.pktConf.bRepeatOk = 0; // (default: 1)
  	RF_cmdPropRxSniff.pktConf.bRepeatNok = 1;

    // Calculate datarate from prescaler and rate word
    uint32_t datarate = calculateSymbolRate(RF_cmdPropRadioDivSetup.symbolRate.preScale, RF_cmdPropRadioDivSetup.symbolRate.rateWord);

    // Configure Sniff-mode part of the RX_SNIFF command
    configureSniffCmd(&RF_cmdPropRxSniff, datarate, WOR_WAKEUPS_PER_SECOND(sensor.settings.autotest));

    // Configure TX
    rf_config_tx();

    // Open RF
    rf_handle = RF_open(&rf_object, &RF_prop, (RF_RadioSetup*) &RF_cmdPropRadioDivSetup, &rfParams);

    // Set the frequency
    rf_set_frequency(0);

    // Set TX power
    if (rf_handle != NULL) {
        RF_TxPowerTable_Value tx_power = RF_TxPowerTable_findValue((RF_TxPowerTable_Entry*) RF_PROP_txPowerTable, 14);
        if (tx_power.rawValue != RF_TxPowerTable_INVALID_VALUE) {
            RF_setTxPower(rf_handle, tx_power);
        }
    }

    // Send callback to inform that radio is ready
    ready_callback(true);

    // Terminate the task
    Task_exit();
}

static void initializeTxAdvCmdFromTxCmd(rfc_CMD_PROP_TX_ADV_t *RF_cmdPropTxAdv, rfc_CMD_PROP_TX_t *RF_cmdPropTx) {
#define RADIO_OP_HEADER_SIZE 14

	/* Copy general radio operation header from TX commmand to TX_ADV */
	memcpy(RF_cmdPropTxAdv, RF_cmdPropTx, RADIO_OP_HEADER_SIZE);

	/* Set command to CMD_PROP_TX_ADV */
	RF_cmdPropTxAdv->commandNo = CMD_PROP_TX_ADV;

	/* Copy over relevant parameters */
	RF_cmdPropTxAdv->pktConf.bFsOff = RF_cmdPropTx->pktConf.bFsOff;
	RF_cmdPropTxAdv->pktConf.bUseCrc = RF_cmdPropTx->pktConf.bUseCrc;
	RF_cmdPropTxAdv->syncWord = RF_cmdPropTx->syncWord;
}

static void initializeSniffCmdFromRxCmd(rfc_CMD_PROP_RX_SNIFF_t *rxSniffCmd, rfc_CMD_PROP_RX_t *rxCmd) {
    /* Copy RX configuration from RX command */
    memcpy(rxSniffCmd, rxCmd, sizeof(rfc_CMD_PROP_RX_t));

    /* Change to RX_SNIFF command from RX command */
    rxSniffCmd->commandNo = CMD_PROP_RX_SNIFF;
}

static uint32_t calculateSymbolRate(uint8_t prescaler, uint32_t rateWord) {
    /* Calculate datarate according to TRM Section 23.7.5.2:
     * f_baudrate = (R * f_ref)/(p * 2^20)
     *   - R = rateWord
     *   - f_ref = 24Mhz
     *   - p = prescaler */
    uint64_t numerator = rateWord * 24000000ULL;
    uint64_t denominator = prescaler * 1048576ULL;
    uint32_t result = (uint32_t) (numerator / denominator);
    return result;
}

static void rf_config_tx(void) {
    // Packet length
    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    // Pointer to packet
    RF_cmdPropTx.pPkt = (uint8_t*) &tx_payload;

#if ACK_MODE == true
    RF_cmdPropTx.pNextOp = (rfc_radioOp_t*) &RF_cmdPropRxAdv;
    // Only run the RX command if TX is successful
    RF_cmdPropTx.condition.rule = COND_STOP_ON_FALSE;

    RF_cmdPropRxAdv = RF_cmdPropRxAdv_preDef;
    // RX to wait for ACK
    RF_cmdPropRxAdv.pQueue = &dataQueue;
    // Discard ignored packets from Rx queue
    RF_cmdPropRxAdv.rxConf.bAutoFlushIgnored = 1;
    // Discard packets with CRC error from Rx queue
    RF_cmdPropRxAdv.rxConf.bAutoFlushCrcErr = 1;
    // Implement packet length filtering to avoid PROP_ERROR_RXBUF
    RF_cmdPropRxAdv.maxPktLen = MAX_LENGTH;
    RF_cmdPropRxAdv.pktConf.bRepeatOk = 0;
    RF_cmdPropRxAdv.pktConf.bRepeatNok = 0;
    RF_cmdPropRxAdv.pOutput = (uint8_t*) &rx_statistics;
    // Receive operation will end RX_TIMEOUT ms after command starts
    RF_cmdPropRxAdv.endTrigger.triggerType = TRIG_REL_PREVEND;
    RF_cmdPropRxAdv.endTime = RADIO_WAIT_IN_MS(ACK_TIMEOUT_MS);
    // Filter address to only MR14
    RF_cmdPropRxAdv.pktConf.filterOp = 1;
    RF_cmdPropRxAdv.addrConf.addrSize = 8;
    RF_cmdPropRxAdv.addrConf.numAddr = 1;
    RF_cmdPropRxAdv.pAddr = filter_address;
#endif

    // Listen before talk (rfListenBeforeTalk.c)
    RF_cmdNop.startTrigger.triggerType = TRIG_ABSTIME;
    RF_cmdNop.startTrigger.pastTrig = 1;

    // Set up the next pointers for the command chain
    RF_cmdNop.pNextOp = (rfc_radioOp_t*) &RF_cmdPropCs;
    RF_cmdPropCs.pNextOp = (rfc_radioOp_t*) &RF_cmdCountBranch;
    RF_cmdCountBranch.pNextOp = (rfc_radioOp_t*) &RF_cmdPropTx;
    RF_cmdCountBranch.pNextOpIfOk = (rfc_radioOp_t*) &RF_cmdPropCs;

    // Customize the API commands with application specific defines
    RF_cmdPropCs.rssiThr = RSSI_THRESHOLD_DBM;
    RF_cmdPropCs.csEndTime = (IDLE_TIME_US + 150) * 4; /* Add some margin */
    RF_cmdCountBranch.counter = CS_RETRIES_WHEN_BUSY;
}

void rf_set_frequency(uint8_t position) {
    // Change settings to new frequency
    RF_cmdFs.frequency = RF_FREQUENCY[position];
    RF_cmdFs.fractFreq = RF_FREQUENCY_FRACT[position];
    RF_cmdPropRadioDivSetup.centerFreq = RF_FREQUENCY[position];

    // Set the frequency
    if (rf_handle != NULL) {
        RF_runCmd(rf_handle, (RF_Op*) &RF_cmdFs, RF_PriorityNormal, NULL, 0);
    }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当我没有完整的 RX 和 TX 代码并且无法自己进行一些测试时、很难说会发生什么。

    检查 sniff 命令和 tx 命令的状态可能会提示您出现了什么问题。

    我有一个 CC13x4 的小嗅探模式示例、其中添加了一个在每次接收到数据包时传输数据包的链。

    此示例效果很好、您可以查看该示例以供参考:

    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_setConfig(CONFIG_GPIO_CRC_OK, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        // Debug signals coming from the RF Core.
        // Require the following overrides:
        // HW_REG_OVERRIDE(0x5378,0x1800),
        //
        // HW_REG_OVERRIDE(0x1110, RFC_DBELL_SYSGPOCTL_GPOCTL0_CPEGPO0 |
        //                         RFC_DBELL_SYSGPOCTL_GPOCTL1_MCEGPO1 |
        //                         RFC_DBELL_SYSGPOCTL_GPOCTL2_MCEGPO2 |
        //                         RFC_DBELL_SYSGPOCTL_GPOCTL0_CPEGPO1),
    
        GPIO_setConfigAndMux(CONFIG_GPIO_DEBUG_RX,        GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW, IOC_PORT_RFC_GPO0);
        GPIO_setConfigAndMux(CONFIG_GPIO_DEBUG_CORR_PEAK, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW, IOC_PORT_RFC_GPO1);
        GPIO_setConfigAndMux(CONFIG_GPIO_DEBUG_RXDATA,    GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW | GPIO_CFG_INVERT_ON, IOC_PORT_RFC_GPO2);
        GPIO_setConfigAndMux(CONFIG_GPIO_DEBUG_PA,        GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW, IOC_PORT_RFC_GPO3);
    
        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);
        }
    
        RF_cmdPropTx.pktLen = MAX_LENGTH;
        RF_cmdPropTx.pPkt = txPacket;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
    
        // Copy RX configuration from RX command
        memcpy(&RF_cmdPropRxSniff, &RF_cmdPropRx, sizeof(rfc_CMD_PROP_RX_t));
    
        // Change to RX_SNIFF command from RX command
        RF_cmdPropRxSniff.commandNo                 = CMD_PROP_RX_SNIFF;
        RF_cmdPropRxSniff.startTrigger.triggerType  = TRIG_ABSTIME;
        RF_cmdPropRxSniff.startTrigger.pastTrig     = 0;
        RF_cmdPropRxSniff.rxConf.bAutoFlushIgnored  = 1; // Discard ignored packets from Rx queue
        RF_cmdPropRxSniff.rxConf.bAutoFlushCrcErr   = 1; // Discard packets with CRC error from Rx queue
        RF_cmdPropRxSniff.maxPktLen                 = MAX_LENGTH; // Implement packet length filtering to avoid PROP_ERROR_RXBUF
        RF_cmdPropRxSniff.endTrigger.triggerType    = TRIG_REL_START;
        RF_cmdPropRxSniff.endTime                   = END_TIME;
        RF_cmdPropRxSniff.pQueue                    = &dataQueue; // Set the Data Entity queue for received data
        RF_cmdPropRxSniff.pOutput                   = (uint8_t*)&rxStatistics;
        RF_cmdPropRxSniff.csConf.bEnaRssi           = 1; // Use RSSI to monitor the channel
        RF_cmdPropRxSniff.csConf.bEnaCorr           = 1; // Use the correlator as well as RSSI, to prevent too many false BUSY channels
        RF_cmdPropRxSniff.csConf.operation          = 1; // Only declare the channel BUSY if both the RSSI and CS criterion are met
        RF_cmdPropRxSniff.csConf.busyOp             = 0; // Continuously monitor the channel so that we can exit as soon as the channel state is IDLE
        RF_cmdPropRxSniff.csConf.idleOp             = 1; // Exit RX as soon as an IDLE channel is detected
        RF_cmdPropRxSniff.csConf.timeoutRes         = 1;
        RF_cmdPropRxSniff.rssiThr                   = (-109); // Set 1 dB higher than the sensitivity level to avoid too many false detections
        RF_cmdPropRxSniff.numRssiIdle               = 1; // Minimize time in RX to reduce current consumption
        RF_cmdPropRxSniff.numRssiBusy               = 1;
        RF_cmdPropRxSniff.corrPeriod                = CORR_PERIOD;
        RF_cmdPropRxSniff.corrConfig.numCorrInv     = 1;
        RF_cmdPropRxSniff.corrConfig.numCorrBusy    = 1;
        RF_cmdPropRxSniff.csEndTrigger.triggerType  = TRIG_REL_START;
        RF_cmdPropRxSniff.csEndTime                 = CS_END_TIME;
    
    
        RF_cmdPropRxSniff.pNextOp = (rfc_radioOp_t*)&RF_cmdPropTx;
        RF_cmdPropRxSniff.condition.rule           = COND_SKIP_ON_FALSE;
        RF_cmdPropRxSniff.condition.nSkip          = 0x0;
    
    
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
    
        RF_cmdPropRxSniff.startTime = RF_getCurrentTime();
    
        while(1)
        {
            RF_cmdPropRxSniff.startTime += SNIFF_INTERVAL;
    
            RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRxSniff, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
            if (((volatile RF_Op*)&RF_cmdPropTx)->status == PROP_DONE_ENDED)
            {
                // Adjust timing when a packet has been sent
                RF_cmdPropRxSniff.startTime = RF_getCurrentTime();
            }
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            GPIO_toggle(CONFIG_GPIO_CRC_OK);
    
            currentDataEntry = RFQueue_getDataEntry();
    
            packetLength      = *(uint8_t*)(&currentDataEntry->data);
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            memcpy(rxPacket, packetDataPointer, (packetLength + 1));
    
            RFQueue_nextEntry();
        }
    }

    监视调试信号、您将看到器件在每个接收到的数据包之后进入 TX:

    BR

    Siri