ESP32 中的 Byte Buffer Ring Buffer 类型

问题描述 投票:0回答:1

这是我第一次尝试使用环形缓冲区。在我的项目中,我通过 loRa 模块(特别是 Reyax RYLR998)接收数据,并将收到的每条消息推送到环形缓冲区。

我为从 LoRa 模块接收的数据定义了一个结构体:

typedef struct LoraData {
  char *Address;
  char *DataLength;
  char *Data;
  char *SignalStrength;
  char *SignalNoise;
} Lora_Data_t;

我对梯级缓冲区的定义:

#define RINGBUFFER_SIZE 4096
#define RINGBUFFER_TYPE RINGBUF_TYPE_BYTEBUF
...
...
...
void app_main(void) {
// ring buffer init
  data_in_rbuf_handle = xRingbufferCreate(RINGBUFFER_SIZE, RINGBUFFER_TYPE);
  if (data_in_rbuf_handle == NULL) {
    ESP_LOGE(TAG, "Failed to create ring buffer\n");
  } else {
    ESP_LOGI(TAG, "Ring Buffer 'data_in_rbuf_handle' !!!CREATED!!!");
  }
  ...
  ...
}

当我收到数据时,我将其推送到缓冲区:

// send the received block to ring buffer
   UBaseType_t res_send_rbuf =
       xRingbufferSend(data_in_rbuf_handle, Lora_data.Data,
                       strlen(Lora_data.Data), pdMS_TO_TICKS(DELAY / 10));
   if (res_send_rbuf != pdTRUE) {
     ESP_LOGE(TAG, "Failed to send item");
   } else {
     ESP_LOGI(TAG, "Item sent to ring buffer");
     ESP_LOGI(TAG, "Ring Buffer free space: <%zu>",
              xRingbufferGetCurFreeSize(data_in_rbuf_handle));
   }

我可能没有以有效的方式使用环形缓冲区功能,因为我没有同时运行两个任务,接收数据的 tasl 将其推送到缓冲区,当接收到所有数据时,我通知另一个任务开始处理该数据。

所以在处理任务中,我从环形缓冲区中检索数据:

size_t item_size;
size_t item_max_size = hex_block_size;

char *item = (char *)xRingbufferReceiveUpTo(data_in_rbuf_handle, &item_size,
                                      pdMS_TO_TICKS(1000), item_max_size);
//
// Check received data
if (item != NULL) {
  //  Print item
  ESP_LOGW(TAG,
           "***DEBUGGING*** Ring Buffer -> maximum amount of bytes to "
           "retrieve: <%zu> ",
           item_max_size);
  ESP_LOGW(TAG, "***DEBUGGING*** Ring Buffer -> item: <%s> ", item);
  ESP_LOGW(TAG,
           "***DEBUGGING*** Ring Buffer -> size of the retrieved item: "
           "<%zu\n> ",
           item_size);
  // Return item
  vRingbufferReturnItem(data_in_rbuf_handle, (void *)item);
} else {
  // Failed to receive item
  ESP_LOGE(TAG, "Failed to receive item\n");
}

举个例子,

hex_block_size
是230。 环形缓冲区应该包含所有这些数据:
80011AD87641F29CD1529B3F3409EF544B01324C6D59115BFEBC193F82342ED8336D48BEC7ED987D5046114F192251186AE32E756845DA74C06CB7B4D203117D5DB681195F88943411EF7EEA9149355955868643D22FBB2151D73B37F6B9D21C9C0427365A467F3D967330812D80D9D789EC9B80021E4D86C232DD175D3E753551A37462CC23505DFE41B527B71FB71B55411187204FA4425800CC636BAC74FAADD3D7FCBBA3046C3CBE4E58ECB08767361FAE6030962C209C974F68E94CF83A45957EF4ECD9D9D26C66415626B538B18193C64E70461A49CB9D5825769FB31B2E3FB480B36180031B155371F703DD5356BD1663572076A68B53A7D30DE1101122E7C8F5C8425339045B8422A03CAF742343EE6150490CCF0C19AC65C2C7506AFFB3D1BA608E3879B5293F3116D540B7813D33096074C58DAEF658205F81C020E34A3D4EBCF2A684F07B0EE7D75519E2C1A72305EEF5CD6C51800429F1C4330B201B81103E73A7F20C43E9FB4B3FDE77C953324653B8EBA695E5C724CE8E72E58A64C22AD9508971D633214DE4753644E5007471B2D34A5E25430FE617701E53E232091DFBFD822CF11C5C4434A2EC48E2889C036B76ADF8CA3E44A3442E5B0C304DA5F1D01E9C15151244F780051085EB4132ED8332D808A4D80C5C59F56E4EE7991DE2C1D52305B955CD75039532CF0AD2F81DCB144EDC45A7C20D0CED56FE1D539F6FD8434A694B25D7E8E40FDA108BB192BDC84555874C0634BB1D07281364F4BDC2AE6FDB71B6BDB644E49C747297D34A793D70B4B51ABFF5B46E9527800600000000000000000000074763CC87322D5665C66D7484111B0666747A471150C68085DC2374F8904AF558EA13DEE601A426E6C344257C3CA9694A0D3AD63C4B8129861DF6E0F10F250F1C82B045607207D9146E68C17B72133EDE81F7209350845E04D5EE66DECCBF6E34009DD89D5E1D8007016CB0201A69630463CE49005228A730BE5BB2B6947F885409401FD188708FA02CF1CB9F3415ECDAC5DC2A5FF20B1C1F56AABA5BC28D5CDA68FC642FA1A18781621C678494B4B9837EEA3649357E5D8684DD5F5C278246753D607EFB54C8C54858DC0ECEB89E8DEC760223BAA435EB498D8008156195018D151741CB2C38CA4224A341FE5B0C4C847054B20824B47159AA659D53BE8B6A2515E4162D5FD5B3724F3D1361F563D8ABDB44A10CA85AAEB00DCFBD8021A520B592FD47576DAC0657C1750D06D4ED81E4834D3E738C07BBC576D930657A9350D04F15C08A0A208A0C756423DF8009192EB351D3B3754D7D25D6979C187A6CC254492E2EAE4CDE31CAF7F83FD3AB455E9905086E04D578D95E694BC234D3055D933D750C57B05DC0104F88D9ADF043ED2400F6D5F70159AB0E3C0C6938B60E55C4585CF1B1C483594AF8F176A02AC87B0F69546337BDDD427522A108B5BC8509800A0446B3C04F66010D2851D980C184B082B8DD3DBB5CC5AA780E56E2926039C500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

而且我只想一次检索

hex_block_size
字节(即 230),所以变量
item
我期望有:
80011AD87641F29CD1529B3F3409EF544B01324C6D59115BFEBC193F82342ED8336D48BEC7ED987D5046114F192251186AE32E756845DA74C06CB7B4D203117D5DB681195F88943411EF7EEA9149355955868643D22FBB2151D73B37F6B9D21C9C0427365A467F3D967330812D80D9D789EC9B
但取而代之的是,
item
拥有环形缓冲区的全部内容。

所以我在这里遗漏了一些东西。创建、发送和接收函数都是从文档中提取的。

c esp32 esp-idf circular-buffer lora
1个回答
0
投票

文档并不明确,但界面表明

xRingbufferReceiveUpTo()
使用 零复制 语义。这意味着返回的指针是指向环形缓冲区位置的指针,而不是此类数据的副本。

接收函数将修改环形缓冲区的状态,以便后续检索将返回的指针移动到下一个块。

无论如何,如果您观察返回指针处的内存,您将在环形缓冲区中看到不属于当前检索数据的其他数据(它保留在缓冲区中以供以后检索)。

您在通话后应处理的唯一有效数据是从

item[0]
item[item_size-1]
。通常,您可能希望在异步接收任务覆盖数据之前将数据存入缓冲区。
总而言之,如果您的消息块始终具有相同的固定大小,则消息队列而不是字节缓冲区可能更合适。这样您就不需要单独的任务信号。您只需等待完整的 230 字节消息被发布即可。

© www.soinside.com 2019 - 2024. All rights reserved.