调试以太网时卡死在while(ETH_GetSoftwareResetStatus()==SET)

问题描述

最近在调试一个项目的板子,用的STM32F407IGT6+DP83848,以太网例程用的安富莱的,在调试以太网功能时,初始化时老是卡死在while(ETH_GetSoftwareResetStatus()==SET) ,将这行换成if语句后还是执行不下去,仍然无法ping通。

解决过程

请教了了安富莱开发人员(不得不提安富莱的开发人员还是很耐心,8年前买过他家的开发板现在仍然有问必答),又在网上搜了很多大家遇到的结果,大部分人都说应该是时钟问题,在和硬件设计师确认后,确实是时钟原因,虽然板子用的是外部晶振做时钟,但是PHY的时钟还是需要连到STM的PA1脚。

/**
  * @brief  Configures the Ethernet Interface
  * @param  None
  * @retval None
  */
static void ETH_MACDMA_Config(void)
{
  /* 打印调试信息 */
  lwip_printf("LwIP Enter ETH_MACDMA_Config()\r\n");
	
  /* Enable ETHERNET clock  */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |
                        RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);

  /* Reset ETHERNET on AHB Bus */
  ETH_DeInit();

  /* Software reset */
  ETH_SoftwareReset();

  /* Wait for software reset */
  while (ETH_GetSoftwareResetStatus() == SET);

  /* ETHERNET Configuration --------------------------------------------------*/
  /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
  ETH_StructInit(&ETH_InitStructure);

  /* Fill ETH_InitStructure parametrs */
  /*------------------------   MAC   -----------------------------------*/
  ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
//  ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
//  ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
//  ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;

  ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
  ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
  ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
  ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
  ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
  ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
  ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
  ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
#ifdef CHECKSUM_BY_HARDWARE
  ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
#endif

  /*------------------------   DMA   -----------------------------------------*/
  /* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
  the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
  if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
  ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
  ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
  ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;

  ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
  ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
  ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
  ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
  ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
  ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
  ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
  ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
  
  /* 打印调试信息 */
  lwip_printf("LwIP Enter ETH_Init()\r\n");  
  
  /* Configure Ethernet */  
  EthStatus = ETH_Init(&ETH_InitStructure, DP83848_PHY_ADDRESS);
}

结论

将PHY的时钟连到STM的PA1脚。在解决此问题前,我搜了网上大量的回答,以下是一些结果分享,希望可以给后续遇到此问题的同学一点帮助。

分享

下面是分享一些关于网上大家对于“卡死在while(ETH_GetSoftwareResetStatus()==SET)”问题的一些回答或解决建议:

1.检查PHY芯片是否虚焊;
2.用示波器打一下晶振,确认晶振是否起振;
3.用示波器测试时钟和信号,确认是否正常;
4.用示波器检查STM32芯片的ETH时钟引脚,确认程序是否正常运行;
5.确认STM32芯片ETH的时钟引脚是否虚焊;
6.确认IO引脚初始化是否正确;
7.DP83848的34脚和PA1相连,使能PA1就好了;
8.我使用官方st的例程,结果原因是硬件和程序的网络模式不对,用的是MII,而我的硬件模式是RMII,把main.h内的#define RMII注释取消,#define MII注释就好了;
9.定义RMII_MODE,注释掉MII_MODE;
9.MII模式:“adding this line after the PA8 configuration ''GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_MCO) ;''
10.MII模式:找到原因了,他需要时钟同步才行,所以之前说的那两条时钟先都应该有25M才对;
11.我用的是STM32F107VCT6+DP83848,停在while (ETH_GetSoftwareResetStatus() == SET);的原因是由于PA8(MCO时钟输出脚),未进行复用推挽输出到PA1(RMII_REF_CLK脚)上。后来只要把PA8的时钟输出到PA1上就可以正常运行了;
12./* Enable the Ethernet Rx Interrupt */ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);
13.参考Nationstech.N32G45x_SNMP_V1.0 demo移植lwip,发现卡死在以下代码 while (ETH_GetSoftwareResetStatus() == SET),跳过这个while,往下配置phy可以正常配置,但是ping不通,怀疑还是这个SWR的问题,看手册发现SWR是自动清0的,请教各位大佬,啥情况下SWR位会一直为1。answer:时钟没有正确配置
14.正是由于时钟问题,不过我的是由于我MCO和外部50MHZ同时用造成外部有源,波形也不大好,所以我去掉有源了,初始化正常了;
15.今天,我也遇到这个问题,看了些网友说的,MCO有没有输出。我用的芯片DM9161,而芯片是DP83848,就没有问题。我重新修改驱动文件,发现
    GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII);
    在RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |RCC_AHB1Periph_ETH_MAC_Rx, ENABLE); 
    之前进行初始化,导致没有配置成功。还有DM9161,MAC,需要
    ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
    ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
    ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
    这样设置,不能自适应方式。才能成功。希望后面的同学,看了此贴绕过这个坑。    
16.#define PHY_SR                           17     /*!< Tranceiver Status Register */    
   #define PHY_Speed_Status            ((u16)0x3000)    /*!< Configured information of Speed: 10Mbps */
   #define PHY_Duplex_Status           ((u16)0xA000)    /*!< Configured information of Duplex: Full-duplex */
17.PA1应该连接到时钟源上面;

#include "nvs_flash.h" #include "esp_bt.h" #include "esp_bt_main.h" #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_netif.h" #include "esp_eth.h" #include "esp_event.h" #include "esp_log.h" #define TAG "ETHERNET" #define GATTS_SERVICE_UUID_TEST_A 0x00FF #define GATTS_CHAR_UUID_TEST_A 0xFF01 #define GATTS_NUM_HANDLE_TEST_A 4 // 全局错误标志 static bool global_error_flag = false; // 错误处理函数 void handle_error(const char *error_msg, esp_err_t err) { ESP_LOGE(TAG, "%s, error code = %x", error_msg, err); global_error_flag = true; } // 蓝牙天线与主控芯片的封装 static uint16_t service_handle, char_handle; static esp_gatts_attr_db_t test_gatt_db[GATTS_NUM_HANDLE_TEST_A] = { // 服务声明 [0] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_PRI_SERVICE}}, .perm = ESP_GATT_PERM_READ, .property = 0, .p_value = (uint8_t *)&GATTS_SERVICE_UUID_TEST_A, .value_len = 2, }, // 特征声明 [1] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_DECLARE}}, .perm = ESP_GATT_PERM_READ, .property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .p_value = (uint8_t *)&ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .value_len = 1, }, // 特征值 [2] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = GATTS_CHAR_UUID_TEST_A}}, .perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, .property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .p_value = NULL, .value_len = 0, }, // 客户端特征配置描述符 [3] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG}}, .perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, .property = 0, .p_value = NULL, .value_len = 2, }, }; static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { switch (event) { case ESP_GATTS_REG_EVT: { esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name("ESP32_BLE_Device"); if (set_dev_name_ret) { handle_error("set device name failed", set_dev_name_ret); } esp_ble_adv_params_t adv_params = { .adv_int_min = 0x20, .adv_int_max = 0x40, .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }; esp_err_t ret = esp_ble_gap_config_adv_data_raw((uint8_t *)"ESP32_BLE", 10); if (ret) { handle_error("config adv data failed", ret); } ret = esp_ble_gap_set_adv_params(&adv_params); if (ret) { handle_error("set adv params failed", ret); } esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(test_gatt_db, gatts_if, GATTS_NUM_HANDLE_TEST_A, 0); if (create_attr_ret) { handle_error("create attr table failed", create_attr_ret); esp_ble_gap_stop_adv(); return; } break; } case ESP_GATTS_CREATE_EVT: { service_handle = param->create.service_handle; break; } case ESP_GATTS_ADD_CHAR_EVT: { char_handle = param->add_char.attr_handle; break; } default: break; } } // 主控芯片与网口的通信 class EthernetManager { public: EthernetManager() { const int max_retries = 3; int retry_count = 0; esp_err_t err; do { err = esp_netif_init(); if (err) { handle_error("esp_netif_init failed", err); retry_count++; vTaskDelay(pdMS_TO_TICKS(1000)); continue; } err = esp_event_loop_create_default(); if (err) { handle_error("esp_event_loop_create_default failed", err); retry_count++; vTaskDelay(pdMS_TO_TICKS(1000)); continue; } esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_create_default_eth(&cfg); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = 0; phy_config.reset_gpio_num = -1; mac = esp_eth_mac_new_esp32(&mac_config); phy = esp_eth_phy_new_lan8720(&phy_config); esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); err = esp_eth_driver_install(&eth_config, &eth_handle); if (err) { handle_error("Failed to install Ethernet driver", err); retry_count++; vTaskDelay(pdMS_TO_TICKS(1000)); continue; } err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, this); if (err) { handle_error("esp_event_handler_register for ETH_EVENT failed", err); } err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &ip_event_handler, this); if (err) { handle_error("esp_event_handler_register for IP_EVENT failed", err); } break; } while (retry_count < max_retries); if (retry_count >= max_retries) { handle_error("Ethernet initialization failed after multiple retries", ESP_FAIL); } } ~EthernetManager() { esp_eth_stop(eth_handle); esp_eth_driver_uninstall(eth_handle); esp_eth_phy_del(phy); esp_eth_mac_del(mac); } void start() { esp_err_t err = esp_eth_start(eth_handle); if (err) { handle_error("Failed to start Ethernet", err); } } private: static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { EthernetManager *manager = static_cast<EthernetManager*>(arg); switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); break; case ETHERNET_EVENT_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); break; default: break; } } static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; const esp_netif_ip_info_t *ip_info = &event->ip_info; ESP_LOGI(TAG, "Ethernet Got IP Address"); ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); ESP_LOGI(TAG, "~~~~~~~~~~~"); } esp_eth_mac_t *mac; esp_eth_phy_t *phy; esp_eth_handle_t eth_handle; }; // 主程序运行 void app_main() { esp_err_t ret; // 初始化 NVS ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { esp_err_t erase_ret = nvs_flash_erase(); if (erase_ret) { handle_error("nvs flash erase failed", erase_ret); } ret = nvs_flash_init(); } if (ret) { handle_error("nvs flash init failed", ret); return; } // 初始化蓝牙控制器 esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); ret = esp_bt_controller_init(&bt_cfg); if (ret) { handle_error("initialize controller failed", ret); return; } // 启用蓝牙控制器 ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); if (ret) { handle_error("enable controller failed", ret); return; } // 初始化蓝牙协议栈 ret = esp_bluedroid_init(); if (ret) { handle_error("init bluetooth failed", ret); return; } ret = esp_bluedroid_enable(); if (ret) { handle_error("enable bluetooth failed", ret); return; } esp_ble_gatts_register_callback(gatts_event_handler); esp_ble_gatts_app_register(0); EthernetManager ethManager; ethManager.start(); while (1) { // 主循环可以添加其他任务 if (global_error_flag) { // 可以在这里添加错误处理逻辑,如重启等 } vTaskDelay(pdMS_TO_TICKS(1000)); } } 优化一下这串代码
09-25
//蓝牙接收端 #include "nvs_flash.h" #include "esp_bt.h" #include "esp_bt_main.h" #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_netif.h" #include "esp_eth.h" #include "esp_event.h" #include "esp_log.h" #define TAG "ETHERNET" #define GATTS_SERVICE_UUID_TEST_A 0x00FF #define GATTS_CHAR_UUID_TEST_A 0xFF01 #define GATTS_NUM_HANDLE_TEST_A 4 //蓝牙天线与主控芯片的封装 static uint16_t service_handle, char_handle; static esp_gatts_attr_db_t test_gatt_db[GATTS_NUM_HANDLE_TEST_A] = { // 服务声明 [0] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_PRI_SERVICE}}, .perm = ESP_GATT_PERM_READ, .property = 0, .p_value = (uint8_t *)&GATTS_SERVICE_UUID_TEST_A, .value_len = 2, }, // 特征声明 [1] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_DECLARE}}, .perm = ESP_GATT_PERM_READ, .property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .p_value = (uint8_t *)&ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .value_len = 1, }, // 特征值 [2] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = GATTS_CHAR_UUID_TEST_A}}, .perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, .property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .p_value = NULL, .value_len = 0, }, // 客户端特征配置描述符 [3] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG}}, .perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, .property = 0, .p_value = NULL, .value_len = 2, }, }; static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { switch (event) { case ESP_GATTS_REG_EVT: { esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name("ESP32_BLE_Device"); if (set_dev_name_ret) { printf("set device name failed, error code = %x\n", set_dev_name_ret); } esp_ble_adv_params_t adv_params = { .adv_int_min = 0x20, .adv_int_max = 0x40, .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }; esp_err_t ret = esp_ble_gap_config_adv_data_raw((uint8_t *)"ESP32_BLE", 10); if (ret) { printf("config adv data failed, error code = %x\n", ret); } ret = esp_ble_gap_set_adv_params(&adv_params); if (ret) { printf("set adv params failed, error code = %x\n", ret); } esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(test_gatt_db, gatts_if, GATTS_NUM_HANDLE_TEST_A, 0); if (create_attr_ret) { printf("create attr table failed, error code = %x\n", create_attr_ret); esp_ble_gap_stop_adv(); // 具体的资源释放代码 // 例如释放动态分配的内存等 static bool ble_attr_create_error = true; return; } } break; } case ESP_GATTS_CREATE_EVT: { service_handle = param->create.service_handle; break; } case ESP_GATTS_ADD_CHAR_EVT: { char_handle = param->add_char.attr_handle; break; } default: break; } } //主控芯片与网口的通信 class EthernetManager { public: EthernetManager() { esp_netif_init(); esp_event_loop_create_default(); esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_create_default_eth(&cfg); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = 0; phy_config.reset_gpio_num = -1; mac = esp_eth_mac_new_esp32(&mac_config); phy = esp_eth_phy_new_lan8720(&phy_config); esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); esp_err_t err = esp_eth_driver_install(&eth_config, &eth_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to install Ethernet driver: %s", esp_err_to_name(err)); return; } esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, this); esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &ip_event_handler, this); } ~EthernetManager() { esp_eth_stop(eth_handle); esp_eth_driver_uninstall(eth_handle); esp_eth_phy_del(phy); esp_eth_mac_del(mac); } void start() { esp_err_t err = esp_eth_start(eth_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to start Ethernet: %s", esp_err_to_name(err)); } } private: static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { EthernetManager *manager = static_cast<EthernetManager*>(arg); switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); break; case ETHERNET_EVENT_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); break; default: break; } } static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; const esp_netif_ip_info_t *ip_info = &event->ip_info; ESP_LOGI(TAG, "Ethernet Got IP Address"); ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); ESP_LOGI(TAG, "~~~~~~~~~~~"); } esp_eth_mac_t *mac; esp_eth_phy_t *phy; esp_eth_handle_t eth_handle; }; //主程序运行 void app_main() { esp_err_t ret; // 初始化 NVS ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { esp_err_t erase_ret = nvs_flash_erase(); if (erase_ret) { printf("nvs flash erase failed, error code = %x\n", erase_ret); } ret = nvs_flash_init(); } if (ret) { printf("nvs flash init failed, error code = %x\n", ret); return; } // 初始化蓝牙控制器 esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); ret = esp_bt_controller_init(&bt_cfg); if (ret) { printf("initialize controller failed, error code = %x\n", ret); return; } // 启用蓝牙控制器 ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); if (ret) { printf("enable controller failed, error code = %x\n", ret); return; } // 初始化蓝牙协议栈 ret = esp_bluedroid_init(); if (ret) { printf("init bluetooth failed, error code = %x\n", ret); return; } ret = esp_bluedroid_enable(); if (ret) { printf("enable bluetooth failed, error code = %x\n", ret); return; } esp_ble_gatts_register_callback(gatts_event_handler); esp_ble_gatts_app_register(0); EthernetManager ethManager; ethManager.start(); while (1) { // 主循环可以添加其他任务 vTaskDelay(pdMS_TO_TICKS(1000)); } }
09-25
#include "nvs_flash.h" #include "esp_bt.h" #include "esp_bt_main.h" #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_netif.h" #include "esp_eth.h" #include "esp_event.h" #include "esp_log.h" #define TAG "ETHERNET" #define GATTS_SERVICE_UUID_TEST_A 0x00FF #define GATTS_CHAR_UUID_TEST_A 0xFF01 #define GATTS_NUM_HANDLE_TEST_A 4 // 全局错误标志 static bool global_error_flag = false; // 错误处理函数 void handle_error(const char *error_msg, esp_err_t err) { ESP_LOGE(TAG, "%s, error code = %x", error_msg, err); global_error_flag = true; } // 蓝牙天线与主控芯片的封装 static uint16_t service_handle, char_handle; static esp_gatts_attr_db_t test_gatt_db[GATTS_NUM_HANDLE_TEST_A] = { // 服务声明 [0] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_PRI_SERVICE}}, .perm = ESP_GATT_PERM_READ, .property = 0, .p_value = (uint8_t *)&GATTS_SERVICE_UUID_TEST_A, .value_len = 2, }, // 特征声明 [1] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_DECLARE}}, .perm = ESP_GATT_PERM_READ, .property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .p_value = (uint8_t *)&ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .value_len = 1, }, // 特征值 [2] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = GATTS_CHAR_UUID_TEST_A}}, .perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, .property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE, .p_value = NULL, .value_len = 0, }, // 客户端特征配置描述符 [3] = { .attr_control = {.auto_rsp = ESP_GATT_AUTO_RSP}, .attr_uuid = {.len = ESP_UUID_LEN_16, .uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG}}, .perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, .property = 0, .p_value = NULL, .value_len = 2, }, }; static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { switch (event) { case ESP_GATTS_REG_EVT: { esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name("ESP32_BLE_Device"); if (set_dev_name_ret) { handle_error("set device name failed", set_dev_name_ret); } esp_ble_adv_params_t adv_params = { .adv_int_min = 0x20, .adv_int_max = 0x40, .adv_type = ADV_TYPE_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }; // 优化蓝牙广播数据,添加更多有用信息 esp_ble_adv_data_t adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, .min_interval = 0x0006, .max_interval = 0x0010, .appearance = 0x00, .manufacturer_len = 0, .p_manufacturer_data = NULL, .service_data_len = 0, .p_service_data = NULL, .service_uuid_len = sizeof(GATTS_SERVICE_UUID_TEST_A), .p_service_uuid = (uint8_t *)&GATTS_SERVICE_UUID_TEST_A, .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), }; esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data); if (ret) { handle_error("config adv data failed", ret); } ret = esp_ble_gap_set_adv_params(&adv_params); if (ret) { handle_error("set adv params failed", ret); } esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(test_gatt_db, gatts_if, GATTS_NUM_HANDLE_TEST_A, 0); if (create_attr_ret) { handle_error("create attr table failed", create_attr_ret); esp_ble_gap_stop_adv(); return; } break; } case ESP_GATTS_CREATE_EVT: { service_handle = param->create.service_handle; break; } case ESP_GATTS_ADD_CHAR_EVT: { char_handle = param->add_char.attr_handle; break; } default: break; } } // 主控芯片与网口的通信 class EthernetManager { public: EthernetManager() { const int max_retries = 3; int retry_count = 0; esp_err_t err; do { err = esp_netif_init(); if (err) { handle_error("esp_netif_init failed", err); retry_count++; vTaskDelay(pdMS_TO_TICKS(1000)); continue; } err = esp_event_loop_create_default(); if (err) { handle_error("esp_event_loop_create_default failed", err); retry_count++; vTaskDelay(pdMS_TO_TICKS(1000)); continue; } esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); esp_netif_create_default_eth(&cfg); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = 0; phy_config.reset_gpio_num = -1; mac = esp_eth_mac_new_esp32(&mac_config); phy = esp_eth_phy_new_lan8720(&phy_config); esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); err = esp_eth_driver_install(&eth_config, &eth_handle); if (err) { handle_error("Failed to install Ethernet driver", err); retry_count++; vTaskDelay(pdMS_TO_TICKS(1000)); continue; } err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, this); if (err) { handle_error("esp_event_handler_register for ETH_EVENT failed", err); } err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &ip_event_handler, this); if (err) { handle_error("esp_event_handler_register for IP_EVENT failed", err); } break; } while (retry_count < max_retries); if (retry_count >= max_retries) { handle_error("Ethernet initialization failed after multiple retries", ESP_FAIL); } } ~EthernetManager() { esp_eth_stop(eth_handle); esp_eth_driver_uninstall(eth_handle); esp_eth_phy_del(phy); esp_eth_mac_del(mac); } void start() { esp_err_t err = esp_eth_start(eth_handle); if (err) { handle_error("Failed to start Ethernet", err); } } private: static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { EthernetManager *manager = static_cast<EthernetManager*>(arg); switch (event_id) { case ETHERNET_EVENT_CONNECTED: ESP_LOGI(TAG, "Ethernet Link Up"); break; case ETHERNET_EVENT_DISCONNECTED: ESP_LOGI(TAG, "Ethernet Link Down"); break; default: break; } } static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; const esp_netif_ip_info_t *ip_info = &event->ip_info; ESP_LOGI(TAG, "Ethernet Got IP Address"); ESP_LOGI(TAG, "~~~~~~~~~~~"); ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); ESP_LOGI(TAG, "~~~~~~~~~~~"); } esp_eth_mac_t *mac; esp_eth_phy_t *phy; esp_eth_handle_t eth_handle; }; // 主程序运行 void app_main() { esp_err_t ret; // 初始化 NVS ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { esp_err_t erase_ret = nvs_flash_erase(); if (erase_ret) { handle_error("nvs flash erase failed", erase_ret); } ret = nvs_flash_init(); } if (ret) { handle_error("nvs flash init failed", ret); return; } // 初始化蓝牙控制器 esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); ret = esp_bt_controller_init(&bt_cfg); if (ret) { handle_error("initialize controller failed", ret); return; } // 启用蓝牙控制器 ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); if (ret) { handle_error("enable controller failed", ret); return; } // 初始化蓝牙协议栈 ret = esp_bluedroid_init(); if (ret) { handle_error("init bluetooth failed", ret); return; } ret = esp_bluedroid_enable(); if (ret) { handle_error("enable bluetooth failed", ret); return; } esp_ble_gatts_register_callback(gatts_event_handler); esp_ble_gatts_app_register(0); EthernetManager ethManager; ethManager.start(); while (1) { // 主循环可以添加其他任务 if (global_error_flag) { // 可以在这里添加错误处理逻辑,如重启等 } vTaskDelay(pdMS_TO_TICKS(1000)); } } 不涉及wifi只涉及蓝牙连接
09-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值