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.

[参考译文] CC2652R7:在一个连接间隔内发送多个数据包

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1435366/cc2652r7-sending-multiple-packets-within-one-connection-interval

器件型号:CC2652R7

工具与软件:

你(们)好

我有两个基于 Multi_Role 示例的器件和我自己的项目。
一个器件充当主器件、另一个器件充当从器件。 在两种器件上、init_PHYPARAM_MIN_CONN_INT/init_PHYPARAM_MAX_CONN_INT 等于80 (即80*1.25ms = 100ms)

DEFAULT_INIT_PHY = INIT_PHY_1M
MAX_NUM_PDU = 5
MAX_PDU_SIZE = 255

主器件连接到另一个器件并开始使用 GATT_WriteCharValue 将数据发送到特征。 我使用 GATT 中的 ATT_WRITE_REQ 事件监控成功发送的结果。 根据执行时间判断、在发送和确认之间大约经过了165ms (+-)。

看起来数据包在一个连接间隔上发送、在另一个连接间隔上发送确认。
研究完这些信息后、我知道从理论上讲 BLE 应该能够在一个连接间隔内发送多个数据包。 这反过来又增加了汇率。
我应该采取哪些措施来观察速度的提升?
如果我降低连接间隔值、汇率将会增加。 如果我在没有确认的情况下使用录制、速度将会增加。
我感兴趣的是如何通过在一个间隔内发送多个数据包来提高汇率(不更改间隔时间并确认成功记录)

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

    您好、Nick。

    感谢您的咨询。 我想您已经介绍了各种可能性。 您是否能够看到您的写入数据包实际上就是您想要的大小(没有标头时大约为251)? 我还建议您看看 GATT_WriteLongCharDesc ()函数,该函数将为您执行数据包的分段,但支持的最大 PDU 大小为255字节(对于 数据长度扩展)。 您也可以使用您提到的 GATT_WriteNoResponse ()函数,并在所有数据传输完毕后,通过使用通知向中心提供某种确认。

    BR、

    David。

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

    遗憾的是、我对具有后续响应的写函数感兴趣、没有响应的选项不起作用。 在我看来、使用通知确认收到的数据包似乎需要更长的时间。
    我是否正确理解、可以如映像#1中所示在两个设备之间交换数据包(我将数据包大小从251字节减少到32字节、但交换也需要大约160-200ms、相当于2个连接间隔)? 而且、如果没有额外操作(通知或类似操作)、就不可能仅使用提供的堆栈实现映像2中的交换?

    照片#1

    照片#2

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

    您好、Nick。

    对于延迟、我们深表歉意。

    如果设置了更多数据标志(由堆栈本身执行)、则中央设备可以发送多个 TX 数据包。 您可以查看第4.5.6节"关闭 BLE 5.0核心规范中的连接事件"。 数据通道 PDU 标头的 MD 位用于指示
    有更多数据要发送。 如果两个器件都未在其数据包中设置 MD 位、则来自从器件的数据包关闭连接事件。 如果任一器件或两个器件都设置了 MD 位、则主器件可以通过发送另一个数据包来继续连接事件、而从器件应在发送其数据包后侦听。

    BR、

    David。

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

    你(们)好

    您会说"这是由堆栈本身处理的"

    我可以通过什么方法跟踪该位是否已设置? 是否可以通过任何方法配置(中央设备和外围设备)以确保在可能的情况下设置该位? 您提供的文档内容如下:

    数据物理通道 PDU 标头的 MD 位用于指示
    以便器件发送更多数据。 如果两个器件均未设置中的 MD 位
    外设的数据包、关闭连接事件。 If
    任一器件或两个器件已设置 MD 位、中心设备可以继续
    发送另一个数据包来触发连接事件、外设应侦听
    加密数据

    器件如何确定更多数据? 我在源库中找到了 MD 位的定义、但不在任何位置使用。

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

    您好、Nick。

    对于延迟、我们深表歉意。 您是否具有低功耗蓝牙监听器? MD 位在链路层设置。 此位将根据 MTU 数据包大小、请求发送的数据量以及在连接间隔期间剩余的传输时间来设置。 我可以问一下您的目标吞吐量是多少吗?

    BR、

    David。

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

    你(们)好

    我用两个器件交换数据包。 一个器件(主器件)向该特性发送数据包、另一个器件(从器件)只是接收数据包。 在主器件侧、我记录从发送消息到确认其发送之间的时间(在调用 GATT_WriteCharValue 函数后开始倒计时、在应用级别的 GATT msg 中接收 ATT_WRITE_RSP 事件时、倒计时结束)。 根据计算结果、我得到大约185ms。

    在主器件设置中、连接间隔(最大值/最小值)为80 (80 * 1.25 = 100ms)。 也就是说、好像我在一个间隔内发送数据、在另一个间隔内接收数据(这就是我通常不超过2 *间隔的原因)。 我发送的数据大小是32字节、但我尝试了250、结果是相同的。

    我尝试扫描数据交换、跟踪从器件的数据包。 我看到我的数据正在从主器件发送到从器件。 之后,两个空的 PDU 数据包随之出现(我还不明白为什么),只有在这之后,从机似乎会向主机发送成功记录的确认。 由分析仪时间判断、时间差值为100ms。 同时、并非所有数据包中的 MD 位都设置为1。 出于某种原因、测量中的数据存在差异。

    1.为什么分析器和应用程序内部的时间计算会相差近两倍? 此时间是否可能花在堆栈内部的内部操作上?

    2.为什么 MD 位没有设置?

    3.为什么发送和确认之间还有更多的数据包?

    以 packet master --> slave 为例

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

    你(们)好

    我关于在应用程序中通过监听器测量的奇怪时间的问题可能可以通过实时系统和任务来解释。 我试图排除一些任务(较低的优先级),并在应用中再次测量时间。 我看到现在阶跃中的时间发生了变化。 也就是说、在第一次传输和确认时、我测量了190ms、在下一次迭代183ms 等、最多100ms、然后再次测量了190ms、依此类推。

    如果我将所有必要任务返回到代码中、时间就变为稳定的183ms。

    但这仍然不能解释为什么堆栈没有设置 MD 位?

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

    您好、Nick。

    两台设备同意使用的 MTU 大小是多少?

    我构建了该示例、您可以在其中查看如何设置 MD 位。 我将以11.25ms 的连接间隔以及125字节的 MTU 大小传输音频数据。 在第一个通知中、我们发送整个 MTU 大小、您可以看到 MD 位未设置、并且在1个连接事件期间发送整个数据包。

    一段时间后、您可以看到 MD 位开始被设置、并且在一个连接间隔内发送了多个数据包。 这是因为 BLE 堆栈会对其他可能具有更高优先级的任务进行排队、并优先于通知任务以在正确的时间执行和传输数据包、因此链路层会通过这种方式尝试保持吞吐量。

    BR、

    David。

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

    你(们)好

    我在两台设备上都有最大 PDU 值(255)、即最大 MTU 值为251。 但我曾尝试发送30字节和251字节数据包、但在任何一种情况下都设置了 MD 位。

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

    您好、Nick。

    我建议在保持相同连接间隔的同时、使更多 GATT 操作(通知/写入)排队。

    BR、

    David。

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

    你好

    您的短语是什么意思?

    "我建议在保持相同连接间隔的同时、对更多 GATT 操作(通知/写入)进行排队。"

    我试图通过在应用程序中创建我自己的测试事件并连续调用 multi_role_doGattWrite 函数两次来对此进行仿真、这是从多角色示例中获取的、并且实际写入到另一个器件。 在实践中、我看到第一次写入操作立即成功、但当调用第二个函数时、我需要进行多次尝试、因为堆栈会返回 BLE 挂起位。 还可以在 NRF 的 BLE 分析仪上看到、消息已发送、在100ms 后收到确认、在另一个100ms 后、我发送了第二条消息、在另一个100ms 后、我再次收到确认。 因此、我仍然看不到 MD 位已设置以及数据包在一个连接间隔内传输的情况。

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

    您好、Nick。

    通过使更多 GATT 操作排队、我是指执行更多 GATT 写入或 GATT 通知背靠背。 在我的应用中、我要从以16 KHz 采样的模拟麦克风传输音频。 为此、我使用 ADCBuff 驱动程序、如下所示:

    uint8_t Audio_enable(void)
    {
        ADCBuf_init();
        
        //Configure & Open ADC Buffer driver
        adcBufParams.callbackFxn = adcBufCallback;
        adcBufParams.recurrenceMode = ADCBuf_RECURRENCE_MODE_CONTINUOUS;
        adcBufParams.returnMode = ADCBuf_RETURN_MODE_CALLBACK;
        adcBufParams.samplingFrequency = 16000;
        adcBuf = ADCBuf_open(CONFIG_ADCBUF_0, &adcBufParams);
    
        //Configure the conversion struct
        continuousConversion.arg = NULL;
        continuousConversion.adcChannel = CONFIG_ADCBUF_0;
        continuousConversion.sampleBuffer = sampleBufferOne;
        continuousConversion.sampleBufferTwo = sampleBufferTwo;
        continuousConversion.samplesRequestedCount = ADCSAMPLESIZE;
    
        if (ADCBuf_convert(adcBuf, &continuousConversion, 1) != 0) {
                uint8_t retVal = 1;
        }
    
        return retVal;
    }

    然后,每次 DMA 完成用 ADC 数据填充其缓冲区时,它将生成一个中断 ,将触发回调函数,在此我们使用 BLEAppUtil_invokeFunctionNoData ()函数从中断更改为任务上下文。

    void adcBufCallback(ADCBuf_Handle handle, ADCBuf_Conversion *conversion, void *completedADCBuffer, uint32_t completedChannel, int_fast16_t status)
    {
        memcpy(fullBuffer, completedADCBuffer, ADCSAMPLESIZE*sizeof(int16_t));
        BLEAppUtil_invokeFunctionNoData(Audio_sendBufferOverBLE);
    }

    在 Audio_sendBufferOverBLE 函数中、我们按如下方式发送通知:

    bStatus_t Audio_sendBufferOverBLE(uint16_t connHandle, void *data, uint16_t len)
    {
    
        bStatus_t ret = SUCCESS;
        attHandleValueNoti_t noti;
        linkDBInfo_t connInfo;
    
            uint16_t allocLen = len;
    
            noti.len = 0;
            noti.pValue = (uint8 *)GATT_bm_alloc( connHandle, ATT_HANDLE_VALUE_NOTI,
                                                  allocLen, &noti.len );
            notificationAllocationsAttempted++;
    
            // If allocation was successful, copy out data out of the buffer and send it
            if (noti.pValue)
            {
                notificationAllocationsSuccess++;
    
                memcpy(noti.pValue, (void *) ((uint8_t *) data), noti.len);
    
                lengthOfNotification = noti.len;
                payloadNotification = noti.pValue;
    
                noti.handle = (GATTServApp_FindAttr(audioProfileAttrTbl, GATT_NUM_ATTRS(audioProfileAttrTbl), audioProfileRead))->handle;
     
                ret = GATT_Notification( connHandle, &noti, FALSE );
                totalNotificationsAttempted++;
    
                // If unable to send the message, free allocated buffers and return
                if ( ret != SUCCESS )
                {
                    GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
                    notificationsFailed++;
                }
                else
                {
                    notificationsSent++;
                }
            }
            else
            {
                // Unable to allocate space for a notification, return failure
                ret = bleMemAllocError;
                notificationAllocationsFailed++;
            }
    
        return ret;
    
    }

    缓冲区长度为129字节、这意味着每8ms 传输一个缓冲区都将就绪、而且我的连接间隔为30ms。 如果连接间隔足够长、使链路层计算出在 CONn 间隔期间有足够的时间发送多个数据包、那么我们更有可能通过堆栈将 MD 位设置为1。

    BR、

    David。

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

    你好。

    很抱歉这么长时间的沉默。

    我看到您在使用通知、而我使用带确认的写入操作。 我尝试对我的应用程序进行类似的实验、当一个设备订阅通知时、第二个设备开始连续发送大量数据。 但是、我仍然看不到任何有关 MD 位已设置的提示、并且我无法在每个连接周期发送多个数据包。 在任何情况下、我都无法解决此问题、并且不知道如何使该器件报告它可以在一个连接周期内发送更多数据。