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:从 RF_postCmd ()意外过早返回回调事件 RF_EventTxEntryDone

Guru**** 2473270 points
Other Parts Discussed in Thread: CC1310

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

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1381337/cc1310-unexpected-premature-return-from-rf_postcmd-for-callback-event-rf_eventtxentrydone

器件型号:CC1310

工具与软件:

嗨、团队:

我在 CC1310中的代码定期(以11ms 的间隔)将18字节数据包发布到要传输的射频内核。 通常、我会按预期完成–我看到 RF_EventTxEntryDone 在 RF_postCmd ()之后大约350us、紧接着是 RF_EventLastCmdDone。 在大约20到大约800秒之间的任意位置(即、 在先前成功的事务发生之前的1/11ms * 800 = 73k 之后)后、射频内核会作出响应 更早  (大约145us 后)并发送 RF_EventLastCmdDone 事件 之间的比较 实际传输数据包或触发 RF_EventTxEntryDone 事件。 据我所知、在所有情况下、射频内核中断前对射频内核的最新指令为:

rfPostCmdResult = RF_postCmd(

Cc1310_CcRf_RfHandle_g,

TxOperation,

RF_PriorityNormal,

&TxBlocksCallback,

RF_EventTxEntryDone);

我的 TxOperation 传输准备代码如下:

static void PrepareRfTransmission(uint8_t numBlocks, boolean_t highSpeed)
{
    RF_EventMask result;

    SetupBlockQueue(numBlocks, highSpeed);

    TxEntryCurrent = (rfc_dataEntryPointer_t *)TxEntryQueue;

    // RF_cmdTxHS and RF_cmdPropTxAdv must be configured differently.
    if(Cc1310_RfSettings_IsHighSpeedMode() || Cc1310_RfSettings_Is4fskMode())
    {
        /* Address filtering feature has been leveraged to effectively extend the SYNC word, thereby preventing
         * adverse behaviour arising from false syncs, which were occurring approx. once per minute. This is implemented 
         * on the TX side by simply lengthening the user data buffer by two bytes - the first two byte being the address
         * - not by configuring the PHY differently in any way.
         */

        /* Configure high speed TX command */
        /* See e2e.ti.com/.../cc13
         * 10-rf_cmdtxhs-behaves-differently-to-rf_cmdproptxadv-in-an-unexpected-way/3797148#3797148
         * For advice provided by TI to get the HS working.
         */
        RF_cmdTxHS.pQueue = &TxQueue;
        RF_cmdTxHS.pktConf.bUseCrc = 1;
        RF_cmdTxHS.startTrigger.triggerType = TRIG_NOW;
        RF_cmdTxHS.startTrigger.pastTrig = 1;
        RF_cmdTxHS.startTime = 0;
        RF_cmdTxHS.pktConf.bCheckQAtEnd = 1;
        RF_cmdTxHS.condition.rule = COND_STOP_ON_FALSE;
        TxOperation = (RF_Op*)&RF_cmdTxHS;
    }
    else // "Regular" speed command
    {
        /* Configure CMD_PROP_TX_ADV */
        RF_cmdPropTxAdv.pPkt = (uint8_t*)&TxQueue;
        RF_cmdPropTxAdv.pktLen = 0; // CRITICAL. #### TODO - or else?
        RF_cmdPropTxAdv.pktConf.bUseCrc = 0;
        RF_cmdPropTxAdv.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropTxAdv.startTrigger.pastTrig = 1;
        RF_cmdPropTxAdv.startTime = 0;
        
        TxOperation = (RF_Op*)&RF_cmdPropTxAdv;
    }

    TiDrv_TiGpio_SetGreenLed(1);

    /* Set the TX frequency */
    RF_cmdFs.frequency = Cc1310_CcRf_Frequency_g;
    RF_cmdFs.fractFreq = Cc1310_CcRf_FractFreq_g;
    RF_InfoVal info;
    RF_Stat stat = RF_getInfo(Cc1310_CcRf_RfHandle_g, RF_GET_CURR_CMD, &info);
                        TiDrv_TiGpio_TestPointsWriteData(3, TIDRV_GPIO_TESTPIN_DEBUG_RAW, 
                                         TIDRV_GPIO_TESTPIN_DEBUG_NO_FRAMING, TIDRV_GPIO_DO_REENABLE_INTERRUPTS);
    if(info.ch >= 0)
    {
        RF_flushCmd(Cc1310_CcRf_RfHandle_g, info.ch, 0);
                            TiDrv_TiGpio_TestPointsWriteData(4, TIDRV_GPIO_TESTPIN_DEBUG_RAW, 
                                         TIDRV_GPIO_TESTPIN_DEBUG_NO_FRAMING, TIDRV_GPIO_DO_REENABLE_INTERRUPTS);
        CmdFlushes++;
    }
    result = RF_runCmd(Cc1310_CcRf_RfHandle_g, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
                        TiDrv_TiGpio_TestPointsWriteData(5, TIDRV_GPIO_TESTPIN_DEBUG_RAW, 
                                         TIDRV_GPIO_TESTPIN_DEBUG_NO_FRAMING, TIDRV_GPIO_DO_REENABLE_INTERRUPTS);

    TiDrv_TiGpio_MyValidateAssert(RF_EventLastCmdDone == result, 35);

    /* We always send something, whether it's Pipelined data, Regular-Speed (i.e. ACK this slot) data, or Slot Control 
     * Headers only. In the case of the latter, this could even be one of several Retry Slot Control Headers, as it 
     * takes two slots to depart from High-Speed mode.
     */

    // Don't request SPI data until the main slot transmission is underway
    TiDrv_TiGpio_SetGreenLed(0);    
}

使用 SetupBlockQueue()、如下所示:

static void SetupBlockQueue(uint8_t numBlocks, boolean_t highSpeed)
{
    rfc_dataEntryPointer_t* dataEntryPtr;
    uint8_t i;
    uint8_t dataEntryCounter;
    uint8_t dataEntryCounterMax;
    uint16_t length;
    uint16_t spiBlockBytes;
    
    spiBlockBytes = VolShare_RegMap_GetReg(VOLSHARE_REGMAP_REG_SPI_BYTES);

    // Re-interpretation of simple byte array
    dataEntryPtr = (rfc_dataEntryPointer_t*)TxEntryQueue;
    
    /* We must use TxQueue and Data Entry queues as they were intended, here. This is because, although RF_cmdTxHS will 
     * not send queue entries back-to-back, RF_cmdPropTxAdv will, so the linked list must be established for the latter.
     */

    // We do not yet know whether we'll receive more or fewer data blocks than there are entries available.
    TxQueue.pLastEntry = NULL;

    // High-speed mode can only send one transmission in a single Tx Operation (i.e. single preamble, key-up/down etc.)
    dataEntryCounterMax = highSpeed ? 1 : NUM_DATA_ENTRIES;

    if(CCRF_SETUP_BLOCK_QUEUE_ONE_BLOCK_TXN == numBlocks)
    {
        length = VOLSHARE_DEVCC1310_HEADER_LEN + CCRF_NUM_ADDRESS_BYTES;        
    }
    else
    {
        length =   highSpeed 
                 ? numBlocks * (spiBlockBytes + CCRF_NUM_ADDRESS_BYTES) 
                 : 1         * (spiBlockBytes + CCRF_NUM_ADDRESS_BYTES);
    }
 
    // Create the linked-list of transmit entries.
    for(dataEntryCounter = 0; dataEntryCounter < dataEntryCounterMax; dataEntryCounter++)
    {
        // Configuration of generic data entry header
        dataEntryPtr->status = DATA_ENTRY_PENDING;
        dataEntryPtr->config.type = DATA_ENTRY_TYPE_PTR;
        dataEntryPtr->length = length;
        dataEntryPtr->pNextEntry = &TxEntryQueue[(dataEntryCounter + 1) * RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(1)];
        if((dataEntryCounterMax - 1) == dataEntryCounter)
        {
            dataEntryPtr->pNextEntry = TxEntryQueue;
        }
        dataEntryPtr = (rfc_dataEntryPointer_t*)(dataEntryPtr->pNextEntry);
    }
    TxQueue.pCurrEntry = TxEntryQueue; // Current entry is the first in the queue

    // Determination of final entry is more involved, since that may not yet be possible.
    if(highSpeed || (numBlocks <= 1))
    {
        TxQueue.pLastEntry = TxQueue.pCurrEntry;
    }
    else if(numBlocks <= dataEntryCounterMax) // Traverse the linked-list to find the final Tx entry.
    {
        dataEntryPtr = (rfc_dataEntryPointer_t*)TxEntryQueue;
        for(i = 0; i < numBlocks - 1; i++)
        {
            dataEntryPtr = (rfc_dataEntryPointer_t*)(dataEntryPtr->pNextEntry);
        }
        TxQueue.pLastEntry = (uint8_t*)dataEntryPtr;
    }
    /* else ... last block is at least one full wrap of the circular block queue - must defer assignment until 
     * we're on the last wrap.
     */
    LastEntrySet = TxQueue.pLastEntry != NULL;
}

我有:

  • 验证(立即) rfPostCmdResult!= rf_ALLOC_ERROR (-2、在\simplelink_cc13x0_sdk_4_20_02_07\source\ti\drivers\rf\rf.h 中定义)
  • 已验证、当 EventLastCmdDone 事件发生并在回调 TxBlocksCallback()中被识别为该事件时、TxEntryCurrent->length 是我预期的值(16 + 2个地址[过滤]字节)。
  • 虽然在准备 TxOperation 和实际使用 RF_postCmd ()()发布 TxOperation 之间存在射频内核命令,但我不明白这些命令会如何导致将来的 RF_postCmd ()失败。

它就像 TxOperation 被准备和发布它之间的某种事情破坏了一样、然而 TxEntryCurrent -> length 字段既不为零、也不是我预期的值(16 + 2 = 18)。

这可能是什么原因造成的? 我可以执行哪些调试来(帮助)对此进行诊断?

请参阅随附的图片、了解更多详细信息。

TIA 提供任何帮助。

此致、

Sean。

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

    你好、Sean、

    感谢您发送编修。

    发生这种情况时、您可以检查 Tx 命令的状态字段吗?

    谢谢、

    Marie H.

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

    尊敬的 Marie:

    感谢您的及时响应。

    我可能误解了您的请求、但当我检查 RF_cmdTxHS.status 时、刚好在  RF_postCmd (Cc1310_C387l_g Rf_Rf、TxOperation、...)之前 当事情正常工作时、我会看到0x3443、并且我在输入 EventLastCmdDone 事件导致的回调时看到相同的值。 如果事情不能正常工作,我会在  rf_postCmd ()之前看到0x3443 ,但我会看到0x3 8. 43调用该函数。

    请注意、虽然我将 TxOperation 传递给 RF_postCmd ()、但我也 在 PrepareRfTransmission ()内执行 TxOperation =(RF_Op*)&RF_cmdTxHS、而 RF_cmdTxHS 是 我直接配置的。

    请告诉我,如果我 误解了你想要什么。

    TIA、

    Sean。

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

    尊敬的 Marie:

    此外、我无法确定0x3443或0x3843的含义、因为我找不到 RF_cmdTxHS.status 字段的值/位字段的定义-文档中未提供有关这方面的详细信息。 我是否可以访问一些描述这些内容的最终参考源?

    TIA、

    Sean。

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

    尊敬的 Marie:

    我发现了一个奇怪的症状,我几乎肯定是与问题有关,因为它从来没有发生在"良好"的传输,总是发生在"不良"。

    我已将 IOID_27配置为由配套微控制器(在本设计中为主器件)触发的下降沿敏感异步中断:

    #define RFCSZPIN1               IOID_27
    
    static PIN_Handle RfCszPinHandle;
    static PIN_State RfCszPinState;
    static PIN_Config RfCszPinTable[] = {
        RFCSZPIN1  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        PIN_TERMINATE
    };
    
    RfCszPinHandle = PIN_open(&RfCszPinState, RfCszPinTable);
    TiDrv_TiGpio_MyValidateAssert(RfCszPinHandle != NULL, 112);
    
    /* Setup callback for button pins */
    if (PIN_registerIntCb(RfCszPinHandle, RfCszIsr) != 0) {
        /* Error registering button callback function */
        TiDrv_TiGpio_MyValidateAssert(FALSE, 113);
    }

    由于中断是通过异步过程(即另一个微控制器)触发的、因此、它在准备和发布 TxOperation 时出现的时间性情况意味着、在发布 TxOperation 后(50us)偶尔会将中断引脚"拉至低电平:

    rfPostCmdResult = RF_postCmd(Cc1310_CcRf_RfHandle_g,
                                                TxOperation,
                                                RF_PriorityNormal,
                                                &TxBlocksCallback,
                                                RF_EventTxEntryDone
                                                );   

    发生这种情况时、射频内核立即使用 RF_EventLastCmdDone 返回。

    这就好像中断导致射频内核中止传输一样。

    在  IOID_27中断处理程序中,我切换 GPIO 测试引脚 作为调试辅助工具,这确实涉及调用 CPUcpsid ()和 CPUcpsie (),以防止测试引脚活动被中断而失真,这使得我的示波器分析器(寻找特定的脉冲计数和宽度)无用。  我无法轻易理解为什么 GPIO、GPIO 中断和射频内核会相互作用、但此处或许有一些底层机制会导致此问题。

    TIA、

    Sean。

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

    你好、Sean、

    由于您使用高速模式、因此状态在 rf_hs_mailbox.h 中定义  

    /// \name Radio operation status
    ///@{
    /// \name Operation finished normally
    ///@{
    #define HS_DONE_OK            0x3440  ///< Operation ended normally
    #define HS_DONE_RXTIMEOUT     0x3441  ///< Operation stopped after end trigger while waiting for sync
    #define HS_DONE_RXERR         0x3442  ///< Operation ended after CRC error
    #define HS_DONE_TXBUF         0x3443  ///< Tx queue was empty at start of operation
    #define HS_DONE_ENDED         0x3444  ///< Operation stopped after end trigger during reception
    #define HS_DONE_STOPPED       0x3445  ///< Operation stopped after stop command
    #define HS_DONE_ABORT         0x3446  ///< Operation aborted by abort command
    ///@}
    /// \name Operation finished with error
    ///@{
    #define HS_ERROR_PAR          0x3840  ///< Illegal parameter
    #define HS_ERROR_RXBUF        0x3841  ///< No available Rx buffer at the start of a packet
    #define HS_ERROR_NO_SETUP     0x3842  ///< Radio was not set up in a compatible mode
    #define HS_ERROR_NO_FS        0x3843  ///< Synth was not programmed when running Rx or Tx
    #define HS_ERROR_RXOVF        0x3844  ///< Rx overflow observed during operation
    #define HS_ERROR_TXUNF        0x3845  ///< Tx underflow observed during operation
    ///@}
    ///@}

    您的错误消息对应于"No FS (无错误)"。 那么、或许也检查 FS 命令的状态吗?

    谢谢、

    Marie H.

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

    尊敬的 Marie:

    感谢您提供指导-我确实看到 rf_cmdfs.status 中与 rf_runCmd (Cc1310_C307C307CLF452-le_g Rf_Rf、(RF_Op*)和 rf_cmdFs…后面不同的值 该操作将在行为发生故障时与成功时进行比较。

    成功时、 RF_cmdFs.status = 0x0400。 失败时、我看到0x0809。 此值的含义是什么、状态字段值定义在哪里、您如何知道它、以便我以后可以自行查找此信息?

    TIA、

    Sean。

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

    你好、Sean、

    状态在您可以在 driverlib 文件夹(C:\ti\simplelink_cc13x0_sdk_4_20_02_07\source\ti\devices\cc13x0\driverlib)中找到的邮箱文件中定义。 (它们也包含在应用程序源文件的顶部。)

    这个在 rf_mailbox.h 中定义:

    /// \name Operation finished with error
    ///@{
    #define ERROR_PAST_START 0x0800   ///< The start trigger occurred in the past
    #define ERROR_START_TRIG 0x0801   ///< Illegal start trigger parameter
    #define ERROR_CONDITION  0x0802   ///< Illegal condition for next operation
    #define ERROR_PAR        0x0803   ///< Error in a command specific parameter
    #define ERROR_POINTER    0x0804   ///< Invalid pointer to next operation
    #define ERROR_CMDID      0x0805   ///< Next operation has a command ID that is undefined or not a radio
                                      ///< operation command
    #define ERROR_WRONG_BG   0x0806   ///< FG level command not compatible with running BG level command
    #define ERROR_NO_SETUP   0x0807   ///< Operation using Rx or Tx attemted without CMD_RADIO_SETUP
    #define ERROR_NO_FS      0x0808   ///< Operation using Rx or Tx attemted without frequency synth configured
    #define ERROR_SYNTH_PROG 0x0809   ///< Synthesizer calibration failed
    #define ERROR_TXUNF      0x080A   ///< Tx underflow observed
    #define ERROR_RXOVF      0x080B   ///< Rx overflow observed
    #define ERROR_NO_RX      0x080C   ///< Attempted to access data from Rx when no such data was yet received
    #define ERROR_PENDING    0x080D   ///< Command submitted in the future with another command at different level pending
    ///@}
    ///@}

    因此、在这些情况下、您的合成校准似乎失败了。  

    谢谢、

    Marie H.

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

    尊敬的 Marie:

    感谢您 再次及时回复并提供指导。

    您知道合成校准可能失败的原因吗? 我是否需要在我的应用程序中处理此行为、或者是否有办法防止此行为发生?

    由于我可以在发生合成校准故障时识别该故障、因此我当然可以重试、直到成功。 但是、由于我不知道导致这种情况的原因、因此我不知道这种方法是否有效-可能合成校准将持续失败、直到执行"某些操作"。

    TIA、

    Sean。