嵌入式网络接口基本知识
1. 以太网驱动器
一个网络应用,首先要有一个网络驱动器. ESP32-C3 提供了多种以太网驱动器,比如: w5500. 我们要通过硬件的方式来将其配置成为一个网络驱动器.
以太网驱动器由两部分组成:MAC 和 PHY。也就是说,只要实现了这两个部分功能,就可以成为一个网络驱动器.
ESP-IDF 在宏 ETH_MAC_DEFAULT_CONFIG 和 ETH_PHY_DEFAULT_CONFIG 中为 MAC 和 PHY 提供了默认配置。
c
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // 应用默认的通用 MAC 配置
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // 应用默认的 PHY 配置
//----------
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);2. 安装驱动程序
有了一个网络设备,还需要将这个设备安装到系统中.
以太网驱动程序包含事件驱动模型,该模型会向用户空间发送有用及重要的事件。安装以太网驱动程序之前,需要首先初始化事件循环。
c
// 初始化事件循环. 这个事件是指的网络二层的事件.
esp_event_loop_create_default(); // 创建一个在后台运行的默认事件循环
esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL);
// 安装驱动程序
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // 应用默认驱动程序配置
esp_eth_handle_t eth_handle = NULL; // 驱动程序安装完毕后,将得到驱动程序的句柄
esp_eth_driver_install(&config, ð_handle); // 安装驱动程序3. 连接驱动程序至 TCP/IP 协议栈
现在,以太网驱动程序已经完成安装。但对应 OSI(开放式系统互连模型)来看,目前阶段仍然属于第二层(即数据链路层)。这意味着可以检测到 link up/down 事件,获得用户空间的 MAC 地址,但无法获得 IP 地址,当然也无法发送 HTTP 请求。ESP-IDF 中使用的 TCP/IP 协议栈是 LwIP,关于 LwIP 的更多信息,请参考 LwIP。
3.1 创建一个网络接口
c
esp_netif_init(); // 初始化 TCP/IP 网络接口(在应用程序中应仅调用一次)
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); // 应用以太网的默认网络接口配置
esp_netif_t *eth_netif = esp_netif_new(&cfg); // 为以太网驱动程序创建网络接口3.2 将以太网驱动程序连接至 TCP/IP 协议栈
c
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)); // 将以太网驱动程序连接至 TCP/IP 协议栈
esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL); // 注册用户定义的 IP 事件处理程序3.4 启动以太网驱动程序
c
esp_eth_start(eth_handle); // 启动以太网驱动程序状态机4. 完成
将以上步骤完成后,就可以使用 TCP/IP 协议栈了.不需要其它代码了
ESP-NETIF的使用方法
| (A) 用户代码 |
| 应用程序 |
.................| 初始化 设置 事件 |
. +----------------------------------------+
. . | *
. . | *
--------+ +===========================+ * +-----------------------+
| | 新建/配置 获取/设置/应用程序| * | 初始化 |
| | |...*.....| 应用程序 (DHCP, SNTP) |
| |---------------------------| * | |
初始化 | | |**** | |
启动 |************| 事件处理程序 |*********| DHCP |
停止 | | | | |
| |---------------------------| | |
| | | | NETIF |
+-----| | | +-----------------+ |
|胶水层|---<----|---| esp_netif_transmit |--<------| netif_output | |
| | | | | | | |
| |--->----|---| esp_netif_receive |-->------| netif_input | |
| | | | | + ----------------+ |
| |...<....|...| esp_netif_free_rx_buffer |...<.....| 数据包 buffer |
+-----| | | | | | |
| | | | | | (D) |
(B) | | | | (C) | +-----------------------+
--------+ | | +===========================+ 网络堆栈
网络 | | ESP-NETIF
接口 | |
驱动 | | +---------------------------+ +------------------+
| | | |.........| 开启/关闭 |
| | | | | |
| -<--| l2tap_write |-----<---| 写入 |
| | | | |
---->--| esp_vfs_l2tap_eth_filter |----->---| 读取 |
| | | (A) |
| (E) | +------------------+
+---------------------------+ 用户代码
ESP-NETIF L2 TAP