WT32-ETH01板卡BLE与ETH同时启用频繁复位问题求助
WT32-ETH01同时启用ETH与BLE时频繁复位的解决方案
问题现象
WT32-ETH01板卡单独使用以太网(ETH)或BLE功能均正常,但同时编译启用两者时会频繁复位。经排查确认ETH.begin()与BLEDevice::init()存在冲突:BLEDevice::init()基于FreeRTOS使用vTaskDelay进行延时,而ETH.begin()使用Arduino标准的阻塞式delay(),两者的延时机制不兼容是问题的核心原因。
复现代码
#include <ETH.h> #include <WiFi.h> #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> /* * ETH_CLOCK_GPIO0_IN - 默认:外部晶振时钟 * ETH_CLOCK_GPIO0_OUT - 内部APLL输出50MHz时钟到GPIO0 - LAN8720可能需要反相器 * ETH_CLOCK_GPIO16_OUT - 内部APLL输出50MHz时钟到GPIO16 - LAN8720可能需要反相器 * ETH_CLOCK_GPIO17_OUT - 内部APLL反相输出50MHz时钟到GPIO17 - 已在LAN8720上测试通过 */ #define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT // 外部晶振使能引脚(-1表示禁用,使用内部APLL源) #define ETH_POWER_PIN 16 // GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT // 以太网PHY类型(LAN8720或TLK110) #define ETH_TYPE ETH_PHY_LAN8720 // 以太网PHY的I²C地址(LAN8720为0或1,TLK110为31) #define ETH_ADDR 1 // 以太网PHY的I²C时钟引脚 #define ETH_MDC_PIN 23 // GPIO23, VSPID, HS1_STROBE // 以太网PHY的I²C IO引脚 #define ETH_MDIO_PIN 18 // GPIO18, VSPICLK, HS1_DATA7 void setup() { Serial.begin(115200); // 创建并命名BLE设备 BLEDevice::init("DEVICE_NAME"); Serial.println("DEBUG_1"); // 调试输出 ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); Serial.println("DEBUG_2"); // 调试输出 } void loop() {}
解决方法
方案1:调整初始化顺序
先完成ETH的初始化(阻塞式操作),再启动BLE设备。这样ETH初始化时的delay()不会干扰已经启动的FreeRTOS BLE任务,避免调度冲突。修改后的setup函数如下:
void setup() { Serial.begin(115200); // 先初始化ETH ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); Serial.println("ETH initialized"); // 再初始化BLE BLEDevice::init("DEVICE_NAME"); Serial.println("BLE initialized"); }
方案2:替换ETH库中的阻塞延时为FreeRTOS延时
如果允许修改ETH库源码,找到ETH.begin()内部使用delay()的位置,将其替换为FreeRTOS的vTaskDelay(pdMS_TO_TICKS(延时毫秒数))。这样ETH初始化也使用FreeRTOS的非阻塞延时,与BLE的调度机制保持一致,从根源解决冲突。
方案3:将ETH初始化放入独立FreeRTOS任务
创建一个单独的FreeRTOS任务来执行ETH初始化,让ETH和BLE的任务在操作系统调度下并行运行,避免阻塞式延时影响BLE任务的执行:
void ethInitTask(void *pvParameters) { ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE); Serial.println("ETH initialized in task"); // 初始化完成后可以删除任务 vTaskDelete(NULL); } void setup() { Serial.begin(115200); // 先初始化BLE BLEDevice::init("DEVICE_NAME"); Serial.println("BLE initialized"); // 创建ETH初始化任务,优先级与BLE任务相当 xTaskCreate(ethInitTask, "ETH_Init", 2048, NULL, 5, NULL); }
内容的提问来源于stack exchange,提问作者Nic
相关产品推荐
相关产品推荐

