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.

[参考译文] CC2340R5:与 RCL 中的多缓冲器相关的问题

Guru**** 2393695 points


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

https://e2e.ti.com/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1477571/cc2340r5-questions-related-to-multibuffer-in-rcl

器件型号:CC2340R5

工具与软件:

我对 Multibuffer 的使用有一些问题。

1)在文件 IEEE-rxtx_handler.html (RX 多缓冲区的内部数据包格式)中、它将时间戳列为4字节。 "IEEE 802.15.4 Rx 帧条目示例"图中时间戳的具体顺序是什么?

2)时间戳是否使用与 RCL_Scheduler_getCurrentTime ()和 RCL_Scheduler_delta ()相同的格式? (SYSTIM、使用0.25us 阶跃)

3)在文件 rcl_buffer_management.html 中、Rx 的示例为多个数据包声明一个多缓冲区。

#define MULTI_BUF_SZ 2048
uint32_t multiBufferArray[MULTI_BUF_SZ / 4];
List_List multiBuffers = { 0 };
RCL_MultiBuffer *multiBuffer;
RCL_MultiBuffer *multiBuffer = (RCL_MultiBuffer *) multiBufferArray;

但是、清除已消耗缓冲区的示例似乎依赖于声明的多个 Multibuffers。

List_List finishedBuffers;
/* Prepare list of RX buffers that are done */
List_clearList(&finishedBuffers);
/* Read out received packet */
RCL_Buffer_DataEntry *rxPkt = RCL_MultiBuffer_RxEntry_get(&rxCmd->rxBuffers, &finishedBuffers);

/* Make finished buffers available to RCL command */
while ((multiBuffer = RCL_MultiBuffer_get(&finishedBuffers)) != NULL)
{
    RCL_MultiBuffer_clear(multiBuffer);
    RCL_MultiBuffer_put(&multiBuffers, multiBuffer);
}

我尝试了单缓冲区方法、并收到了多个数据包。 但是、我从未进入 while 循环以清除缓冲区。 我没有填满单个多缓冲器。 为了让 while 循环获取/清除缓冲区、它是否假设"multibuffers"列表中有多个 Multibuffer? 例如、声明要放置在"多缓冲区"中的64个32字节多缓冲区对象、而不是单个2048字节多缓冲区中。

4) 4)假设我创建了多个32字节的 MultiBuffer、如果数据包对于单个缓冲区来说太大、会发生什么情况? 它是否自动跨越多个 MultiBuffer?

5)在文件 rcl_buffer_management.html 的 transmit buffers 部分中、它引用宏 rcl_TxBuffer_len_u32。 如果将其与非通用 PHY 一起使用、SDK 中定义的 NUM_PAD 和 HDR_LEN 的相应值是否为(例如、与 ieee.h 或 ble5.h 相关的文件)?

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

    您好、Russell:

    我们最近更新了 IEEE 文档: 无线电控制层(RCL):IEEE 802.15.4 Rx 和 Tx 命令处理程序、您是否已经引用了本文档、因为它在查看 IEEE 命令标头和信息时应该会很有用。

    谢谢!
    Alex F

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

    是的、我的前2个问题与该文档图中所示的时间戳格式相关。   我没有看到有关时间戳字节排序或单位的详细信息。  我有兴趣将它们与当前系统时间进行比较。

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

    您好、Russell:

    我可以联系开发 PHY 的内部团队、看看他们是否对字节排序和时间戳有更多详细信息。 (我认为对于时间戳、RX 现在正常工作、而不是 TX)。

    谢谢!
    Alex F

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

    如果我的雇主希望直接与我联系、则与 TI 签订了 NDA。

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

    您好、Russell:

    我会询问单位,因为它不清楚,但他们应该存储在统计部分。  

    [quote userid="613487" url="~/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1477571/cc2340r5-questions-related-to-multibuffer-in-rcl 假设我创建了多个32字节的 MultiBuffers、如果一个数据包对于单个缓冲来说太大、会发生什么情况? 它是否自动跨多个多缓冲区?

    -参考下面的代码示例,我们可以接收许多数据包(即使使用 PartialPacket_read),并在需要时清除缓冲区。  

    以下是 IEEE Rx 的一些代码:

    #define PKT_LEN 64 //
    #define ACK_LEN 12 //
    #ifdef REPEATED_TX
    #define NUM_PKT 1
    #else
    #define NUM_PKT 4
    #endif
    #define HDR_LEN 2 //
    #define NUM_PAD 0 //
    #define PKT_TYPE_PKT 1
    #define PKT_TYPE_ACK 2
    #define NUM_RX_BUF 2
    #define MULTI_BUF_SZ 512
    #define FREQUENCY 2404000000
    
    void ieeeCallback(RCL_Command *cmd, LRF_Events lrfEvents, RCL_Events rclEvents)
    {
        static bool ackInProgress = false;
        RCL_CmdIeeeRxTx *rxTxCmd = (RCL_CmdIeeeRxTx *)cmd;
    
        if (lrfEvents.rxCtrlAck)
        {
            uint32_t rxBuffer[RCL_Buffer_bytesToWords(RCL_Buffer_entryLen(NUM_PAD, HDR_LEN, PKT_LEN))];
            RCL_Buffer_DataEntry *rxEntry = (RCL_Buffer_DataEntry *)rxBuffer;
            /* Ack is under reception. Look at the packet received so far */
            RCL_IEEE_readPartialFrame(rxTxCmd, rxEntry, sizeof(rxBuffer));
            if (rxEntry->length >= 4)
            {
                /* We should at this point at least have the type and sequence number. If not, we need to wait and call it again */
                /* Check the received type */
                uint8_t rxType = rxEntry->data[0];
                uint8_t rxSeqNo = rxEntry->data[1];
                if (rxType == PKT_TYPE_PKT)
                {
                    /* Packet looks OK. Prepare ACK */
                    uint32_t txBuffer[RCL_TxBuffer_len_u32(NUM_PAD, HDR_LEN, ACK_LEN)];
                    RCL_Buffer_TxBuffer *ackBuffer = (RCL_Buffer_TxBuffer *)txBuffer;
                    generatePacketBmack(ackBuffer, ACK_LEN, PKT_TYPE_ACK, rxSeqNo);
                    RCL_IEEE_AckEntryResult ackResult = RCL_IEEE_enterAck(rxTxCmd, (uint32_t *)(&ackBuffer->length),
                        RCL_Buffer_bytesToWords(RCL_Buffer_entryLen(NUM_PAD, HDR_LEN, ACK_LEN)));
                    if (ackResult != RCL_IEEE_AckOk)
                    {
                        /* Error: Entering ACK failed */
                        /* If only part of the ACK is entered here, the result will be RCL_IEEE_AckPartial,
                           and the rest of the ACK must be entered when available. But this code enters the
                           whole ACK */
                        while(1);
                    }
                    else
                    {
                        ackInProgress = true;
                    }
                }
                else
                {
                    /* Packet looks not OK. Cancel ACK */
                    RCL_IEEE_cancelAck(rxTxCmd);
                    ackInProgress = false;
                }
            }
        }
    
        if (rclEvents.rxEntryAvail)
        {
            /* Packet received */
            List_List finishedBuffers;
            RCL_MultiBuffer *multiBuffer;
            /* Prepare list of RX buffers that are done */
            List_clearList(&finishedBuffers);
            RCL_Buffer_DataEntry *rxPkt = RCL_MultiBuffer_RxEntry_get(&rxTxCmd->rxAction->rxBuffers, &finishedBuffers);
            /* Make finished buffers available to RCL command */
            while ((multiBuffer = RCL_MultiBuffer_get(&finishedBuffers)) != NULL)
            {
                RCL_MultiBuffer_clear(multiBuffer);
                RCL_MultiBuffer_put(&rxTxCmd->rxAction->rxBuffers, multiBuffer);
            }
    
            bool pktOk = false;
            if (rxPkt != NULL)
            {
                /* Check contents of packet */
                if (rxPkt->length > 8)
                {
                    /* Note that the length as received over the air is in the pad0 field, and the data starts at the packet type */
                    if (rxPkt->data[0] == PKT_TYPE_PKT)
                    {
                        /* Developer TODO: Further check of the packet (address, CRC, ... ) */
                        pktOk = true;
                    }
                }
            }
            if (pktOk)
            {
                numPktOk++;
                GPIO_toggle(14);
            }
            else
            {
                if (ackInProgress)
                {
                    /* Packet not OK, cancel ACK */
                    RCL_IEEE_cancelAck(rxTxCmd);
                }
            }
            ackInProgress = false;
    #ifndef REPEATED_TX
            if (numPktOk == NUM_PKT)
            {
                /* All packets sent; stop command */
                RCL_Command_stop(cmd, RCL_StopType_Graceful);
            }
    #endif
        }
    
        if (rclEvents.lastCmdDone)
        {
            /* command finished */
            ackInProgress = false;
        }
    }
    
    void runRx(void)
    {
        RCL_init();
    
        RCL_Handle h = RCL_open(&rclClient, &LRF_configBmack);
    
        /* Prepare command */
        RCL_CmdIeeeRxTx cmd = RCL_CmdIeeeRxTx_DefaultRuntime();
        RCL_CmdIeee_RxAction rxAction = RCL_CmdIeee_RxAction_DefaultRuntime();
        uint32_t rxMultiBuffer[NUM_RX_BUF][MULTI_BUF_SZ / 4];
    
        cmd.rfFrequency = FREQUENCY;
        /* Start command immediately */
        cmd.common.scheduling = RCL_Schedule_Now;
        cmd.common.allowDelay = true;
        cmd.txPower = (RCL_Command_TxPower) {.dBm = 0, .fraction = 0}; /* Send with 0 dBm */
        /* Set the command to run for up to 20 seconds */
        /* If relGracefulStopTime is set to 0, the RX command will run until stopped or until it gets an error */
        cmd.common.timing.relGracefulStopTime = RCL_SCHEDULER_SYSTIM_MS(20000);
        cmd.rxAction = &rxAction;
        cmd.common.runtime.callback = bmackCallback;
        /* Set up callback on packet under reception; trigger for ACK generation */
        cmd.common.runtime.lrfCallbackMask.value = LRF_EventRxCtrlAck.value;
        /* Set up callbacks on packet fully received and command done */
        cmd.common.runtime.rclCallbackMask.value =
            RCL_EventLastCmdDone.value | RCL_EventRxEntryAvail.value;
    
        /* Set up RX action */
        rxAction = RCL_CmdIeee_RxAction_DefaultRuntime();
        rxAction.numPan = 1;
        rxAction.panConfig[0] = RCL_CmdIeee_PanConfig_DefaultRuntime();
        /* Enable ACK of received packets */
        rxAction.panConfig[0].autoAckMode = RCL_CmdIeee_AutoAck_ImmAckProvidedFrame;
    
        /* Set up Rx (multi)buffer */
        for (int i = 0; i < NUM_RX_BUF; i++)
        {
            RCL_MultiBuffer *multiBuffer = (RCL_MultiBuffer *) rxMultiBuffer[i];
            RCL_MultiBuffer_init(multiBuffer, MULTI_BUF_SZ);
            RCL_MultiBuffer_put(&rxAction.rxBuffers, multiBuffer);
        }
    
        while(1)
        {
            /* Submit command */
            RCL_Command_submit(h, &cmd);
            //GPIO_write(CONFIG_GPIO_RLED, 1);
            sleep(1);
            LRF_sendHardStop();
            //RCL_Command_stop(rclHandle, RCL_StopType_Hard);
            //GPIO_write(CONFIG_GPIO_RLED, 0);
            sleep(1);
        }
    
        /* Wait for command to finish. Alternatively, the callback on lastCmdDone may be used */
        RCL_Command_pend(&cmd);
    
        /* Record command status, may be checked to look for errors */
        lastStatus = cmd.common.status;
    }

    [报价 userid="613487" url="~/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1477571/cc2340r5-questions-related-to-multibuffer-in-rcl "]在文件 rcl_buffer_management.html 的发送缓冲区部分、它引用了宏 rcl_TxBuffer_len_u32。 如果将其与非通用 PHY 一起使用、SDK 中定义的 NUM_PAD 和 HDR_LEN 的相应值是否为(例如、与 ieee.h 或 ble5.h 相关的文件)?[/QUOT]

    -虽然通用 RCL 命令和 IEEE 之间存在交叉,但如果您使用 IEEE ,我建议您使用 IEEE 命令,也请参阅我的定义以获得帮助,因为您可以根据需要配置您的数据包。  

    谢谢!
    Alex F

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

    我使用 IEEE。

    参考以下代码示例、我们可以接收许多数据包(即使使用 PartialPacket_Read)并在需要时清除缓冲区。  [报价]

    我基于本示例创建了代码、从未观察到在读取数据包后缓冲区被清除。  我将使用一个非常大的缓冲区。  我认为我已经解决了这一问题、但想仿效这些例子、避免意外后果或不受支持的行为。

    [报价 userid="567427" url="~/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1477571/cc2340r5-questions-related-to-multibuffer-in-rcl/5689323 #5689323"]-通用 RCL 命令与 IEEE 之间存在交叉点、如果您使用的是 IEEE、我建议您使用 IEEE 命令、另请参阅上文我的定义以获取帮助、因为您可以根据需要配置数据包。  [报价]

    数据包的 TX 示例使用类似于的调用  

    txData = RCL_TxBuffer_init(txPacket, NUM_PAD_BYTES, HDR_LEN, MAX_LENGTH);

    我在文档中没有看到任何内容表示这仅适用于通用 PHY。  如果可以、也是可以的。  我已经解决了这一问题、但试图仿效这个例子、避免任何意外后果 或不受支持的行为。

    由于商品不清楚、我将询问这些商品、但它们应存储在统计信息部分。  [报价]

    它们能否与当前系统时间(RCL 调度程序时间)或 类似计时器甚至相互进行比较?

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

    您好、Russell:

    我收到 rnd 的回复:

    是的、时间戳以0.25us 为单位、字节顺序为(与芯片的其余部分类似)小端字节序。

    谢谢!

    Alex F