拓冰建站拓冰建站
首页 / 资讯中心 / 正文

ESP-IDF 5.2 IEEE 802.15.4 迁移指南:接收帧处理完成后必须调用 esp_ieee802154_receive_handle_done

ESP-IDF 5.2 IEEE 802.15.4 迁移指南接收帧处理完成后必须调用 esp_ieee802154_receive_handle_done【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf本文基于 ESP-IDF 官方迁移文档 5.2 IEEE 802.15.4 变更说明讲解从 IDF 5.2 起 802.15.4 驱动引入的接收处理完成通知机制上层处理完收到的帧含 ACK 帧后必须调用 esp_ieee802154_receive_handle_done否则接收帧缓冲不会被归还。结合驱动源码你将理解底层接收缓冲池、process标志位与 stub 缓冲的丢弃机制并拿到一份可直接复用的回调示例与调优方法。一、迁移变更内容5.2 迁移指南 对 IEEE 802.15.4 子系统的变更只有一条但属于强制性行为变更breaking change上层必须在处理完接收到的帧之后调用esp_ieee802154_receive_done()回调中传入帧对应的esp_ieee802154_receive_handle_done()以通知 802.15.4 驱动。否则该帧占用的缓冲不会被释放以供后续复用。API 声明及官方注释见 esp_ieee802154.h/** * brief Notify the IEEE 802.15.4 Radio that the frame is handled done by upper layer. * * param[in] frame The pointer to the frame which was passed from the function esp_ieee802154_receive_done() * or ack frame from esp_ieee802154_transmit_done(). * * return * - ESP_OK on success * - ESP_FAIL if frame is invalid. * */ esp_err_t esp_ieee802154_receive_handle_done(const uint8_t *frame);两个关键点参数必须原样传回传入的frame必须是esp_ieee802154_receive_done()回调中收到的原始指针或esp_ieee802154_transmit_done()回调中收到的非 NULL ACK 帧指针不能是上层复制后的缓冲区地址原因见下节两类帧都适用普通接收帧、以及带 ARAck Request位发送成功后收到的 ACK 帧都需要通知释放。二、为什么必须通知接收缓冲池与 stub 缓冲机制从源码结构看这条 API 约定背后是一套静态接收缓冲池设计。驱动在 esp_ieee802154_dev.c 中维护了一个由CONFIG_IEEE802154_RX_BUFFER_SIZE决定的缓冲数组外加一块 STUB 缓冲// 1: for the stub buffer when the valid buffers are full. // // |--------------------VB[0]--------------------| // |--------------------VB[1]--------------------| // |--------------------VB[2]--------------------| // |--------------------VB[3]--------------------| // |--------------------.....--------------------| // |-----VB[CONFIG_IEEE802154_RX_BUFFER_SIZE]----| // |---------------------STUB--------------------| // // VB: Valid buffer, used for storing the frame received by HW. // STUB : Stub buffer, used when all valid buffers are under processing, the received frame will be dropped. static uint8_t s_rx_frame[CONFIG_IEEE802154_RX_BUFFER_SIZE 1][IEEE802154_RX_FRAME_SIZE]; static esp_ieee802154_frame_info_t s_rx_frame_info[CONFIG_IEEE802154_RX_BUFFER_SIZE 1];配套的 Kconfig 选项IEEE802154_RX_BUFFER_SIZE定义在 Kconfig默认值20取值范围2 ~ 100help 中明确增大该值可缓存更多帧但消耗更多内存。这套机制的运行逻辑可以归纳为三步帧落池并标记process。每次 RX 完成后ISR 通过ieee802154_receive_done()esp_ieee802154_dev.c#L89-L100把该缓冲标记为frame_info-process true并投递给上层回调。process字段的含义在 esp_ieee802154_types.h 的esp_ieee802154_frame_info_t中定义The frame needs to be processed by the upper layer。分配下一块空闲缓冲。在set_next_rx_buffer()esp_ieee802154_dev.c#L268-L299中驱动从当前索引起循环寻找process false的缓冲交给硬件。若所有有效缓冲都处于process true状态即上层一直不调用 handle done硬件接收地址会被指向 STUB 缓冲并在开启CONFIG_IEEE802154_DEBUG时打印Rx buffer full.警告。写入 STUB 的帧被静默丢弃。ieee802154_receive_done()开头检查s_rx_index ! CONFIG_IEEE802154_RX_BUFFER_SIZE若帧落在 STUB 位置则直接丢弃、不回调上层。也就是说漏调 handle done 的最终后果不是报错而是后续帧被无声丢弃。esp_ieee802154_receive_handle_done()的实现esp_ieee802154_dev.c#L117-L127经 esp_ieee802154.c#L441-L443 对外暴露也解释了指针必须原样传回的原因——它靠指针算术反推缓冲索引esp_err_t ieee802154_receive_handle_done(const uint8_t *data) { uint16_t size data - s_rx_frame[0][0]; if ((size % IEEE802154_RX_FRAME_SIZE) ! 0 || (size / IEEE802154_RX_FRAME_SIZE) CONFIG_IEEE802154_RX_BUFFER_SIZE) { return ESP_FAIL; } s_rx_frame_info[size / IEEE802154_RX_FRAME_SIZE].process false; IEEE802154_RX_BUFFER_STAT_IS_FREE(true); return ESP_OK; }即指针相对缓冲池起始地址的偏移必须是单块缓冲大小127 1长度字节的整数倍且索引落在有效缓冲范围内否则返回ESP_FAIL且缓冲不会释放。随后将对应process清位该缓冲即重新进入可分配状态。另外注意ACK 帧同样占用接收池。在ieee802154_transmit_done()esp_ieee802154_dev.c#L102-L115中收到 ACK 时同样执行IEEE802154_RX_BUFFER_STAT_IS_FREE(false)并置ack_frame_info-process true因此 API 文档 特别注明esp_ieee802154_transmit_done()中若ack非 NULL上层处理完 ACK 后也必须调用esp_ieee802154_receive_handle_done()。三、在哪里调用两个必须覆盖的回调802.15.4 子系统的事件回调均在 ISR 上下文产生见 esp_ieee802154.h 中 which are in ISR context 的注释。需要配对 handle done 的回调有两个1.esp_ieee802154_receive_done()帧接收完成回调esp_ieee802154.h#L540-L556。帧格式为|--------------------------| | Len | MHR | MAC Payload (no FCS) | |--------------------------|官方注释同时说明接收期间硬件自行计算 FCSFCS 不匹配时帧会被硬件丢弃只有合法帧才会触发本回调且帧尾的 FCS 字段位置被 RSSI 与 LQI 数值替换分别位于frame[len-1]与frame[len]见 ieee802154_rx_frame_info_update()。frame_info中的rssi/lqi/channel/timestamp/pending/mpf_index等字段由驱动填充esp_ieee802154_types.h#L78-L86。2.esp_ieee802154_transmit_done()ack 非 NULL 时发送成功回调esp_ieee802154.h#L564-L575。若被发送帧的 AR 位为 1ack参数指向驱动缓冲池中的一块 ACK 帧处理完后需同样调用esp_ieee802154_receive_handle_done(ack)。四、示例代码官方 ieee802154_cli 的合规写法仓库中的 ieee802154_cli 示例给出了两种回调场景的完整处理模式ieee802154_cmd.c#L818-L835void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) { ESP_EARLY_LOGI(TAG, Tx Done %d bytes, frame[0]); esp_ieee802154_frame_print(frame); if (ack ! NULL) { ESP_EARLY_LOGI(TAG, Rx ack %d bytes, ack[0]); esp_ieee802154_frame_print(ack); esp_ieee802154_receive_handle_done(ack); /* ACK 帧处理完立即归还缓冲 */ } } void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) { ESP_EARLY_LOGI(TAG, Rx Done %d bytes, frame[0]); esp_ieee802154_frame_print(frame); esp_ieee802154_receive_handle_done(frame); /* 接收帧处理完立即归还缓冲 */ }要点本例中上层只是打印帧内容因此回调内同步完成 handle done。若你的协议栈如 OpenThread、Zigbee 协议层需要异步处理必须在上层真正释放该帧内存之前调用此函数且传入原始指针帧首字节frame[0]为长度字段驱动侧会屏蔽第 8 位见 esp_ieee802154_dev.c#L96 的data[0] 0x7f可直接用作字节数。五、如何观测缓冲池压力迁移到 5.2 后的核心风险是缓冲耗尽导致静默丢帧仓库提供了两类观测手段RX 缓冲统计 API。开启IEEE802154_RX_BUFFER_STATISTICKconfig#L135后可通过 esp_ieee802154_rx_buffer_statistic_print() / esp_ieee802154_rx_buffer_statistic_clear() 查看/清零统计。从源码结构看process置位与清位路径esp_ieee802154_dev.c#L92、L105、L125都会经由IEEE802154_RX_BUFFER_STAT_IS_FREE宏汇入统计esp_ieee802154_util.h#L350-L366因此该统计同时反映缓冲被占用与被 handle done 归还两侧的状态变化。Debug 日志。开启CONFIG_IEEE802154_DEBUG后缓冲池满时会在 set_next_rx_buffer() 中打印Rx buffer full.警告可作为漏调 handle done 的直接信号。若日志频繁出现满池警告可从两个方向调整确认上层回调确实及时调用了esp_ieee802154_receive_handle_done()或在内存允许时调大CONFIG_IEEE802154_RX_BUFFER_SIZE默认 20范围 2~100每块缓冲约 128 字节。六、迁移核对清单将下表作为升级 checklist 使用每一项都有对应的仓库内证据路径检查项要求参考位置esp_ieee802154_receive_done()回调帧处理完成后调用esp_ieee802154_receive_handle_done(frame)且传入回调原始指针esp_ieee802154.h#L540-L556esp_ieee802154_transmit_done()回调当ack非 NULL 时ACK 帧处理完成后调用esp_ieee802154_receive_handle_done(ack)esp_ieee802154.h#L564-L575返回值处理ESP_FAIL表示指针非法非缓冲池成员缓冲不会释放需排查是否误传了拷贝地址esp_ieee802154_dev.c#L117-L127缓冲池容量CONFIG_IEEE802154_RX_BUFFER_SIZE默认 20、范围 2~100按上层处理时延权衡Kconfig#L8-L16运行观测开启IEEE802154_RX_BUFFER_STATISTIC/CONFIG_IEEE802154_DEBUG监控丢帧与满池告警esp_ieee802154.h#L708-L714、esp_ieee802154_dev.c#L294-L296适用前提以上内容基于当前仓库ESP-IDF 主线含 5.2 之后的 802.15.4 驱动实现核对。若你的项目仍停留在 5.1 及更早版本该接收缓冲池机制尚未引入esp_ieee802154_receive_handle_done()不是必需调用升级到 5.2 或之后版本时按本指南修改上层回调即可改动面仅限于两处接收/ACK 回调函数。【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门