0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简析esp32的wifi驱动如何被集成进Zephyr的驱动

ZephyrProject 来源:ZephyrProject 作者:ZephyrProject 2021-06-01 10:41 次阅读

分析Zephyr ESP32 WIFI驱动的实现可以更为清晰的掌握esp32 wifi在zephyr上的使用,本文主要分析esp32的wifi驱动如何被集成进Zephyr的驱动,并不涉及esp32 wifi驱动本身API的说明。

框架

目前ESP32 wifi在zephyr上的实现框架如下图

93deaa3e-c240-11eb-9e57-12bb97331649.png

1. esp_private:

esp提供的wifi驱动,不开源,属于zephyr的外部module,其API头文件在moduleshalespressifcomponentsesp_wifiincludeesp_private内

2. adapter

esp提供的zephyr wifi适配层,对esp_private进行封装专门为zephyr用,属于zephyr的外部module,其代码放在moduleshalespressifzephyradaptersrcwifi

3. esp_wifi_drv:

Zephyr中的esp32 wifi驱动,调用adapter,和L2 ethernet进行对接。明明是wifi,不封装为L2 wifi, 而封装为L2 ethernet,这可能是目前zephyr对L2 wifi的抽象还不完备,目前只支持offload wifi。

这部分是后文的主要分析内容,代码在zephyrdriverswifiesp32src

4. L2 ethernet

Zephyr L2 ethernet,提供ethernet初始化/配置/收发功能, 代码在zephyrsubsys etl2ethernet,本文不做分析

esp_wifi_drv

zephyr的esp32 wifi驱动可以分为初始化,收,发三部分来分析:

初始化

主要是完成L2的初始化,注册入device初始化函数eth_esp32_dev_init和iface的初始化函数eth_esp32_init已经L2的发送函数eth_esp32_send

1

2

static const struct ethernet_api eth_esp32_apis = {

.iface_api.init= eth_esp32_init,

.send = eth_esp32_send,

};

NET_DEVICE_DT_INST_DEFINE(0,

eth_esp32_dev_init, NULL,

ð_data, NULL, CONFIG_ETH_INIT_PRIORITY,

ð_esp32_apis, ETHERNET_L2,

NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);

使用NET_DEVICE_DT_INST_DEFINE注册后,在系统启动时kernel的POST_KERNEL阶段调用eth_esp32_dev_init,在net初始化阶段调用eth_esp32_init.

eth_esp32_dev_init代码如下,主要是调用hal中提供的一系列初始化和启动函数,让wifi启动,值得注意的是当CONFIG_ESP32_WIFI_STA_AUTO=y时,zephyr驱动会自动去帮你用配置好的CONFIG_ESP32_WIFI_SSID和CONFIG_ESP32_WIFI_PASSWORD去连接Wifi。

如果没有配置,就需要在应用代码中直接调用esp hal的API进行连接,另外就是zephyr目前并没有将esp32 wifi的scan/connect/disconnect做到L2 WIFI内进行管理,可以参考Zephyr网络管理模块分析-注册请求机制, 这边部分也需要在应用中直接调用esp hal的API进行管理。

static int eth_esp32_dev_init(const struct device *dev)

{

esp_timer_init();

esp_event_init();

wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();

esp_err_t ret = esp_wifi_init(&config);

ret |= esp_supplicant_init();

ret |= esp_wifi_start();

//安装配置进行WIFI连接

if (IS_ENABLED(CONFIG_ESP32_WIFI_STA_AUTO)) {

wifi_config_t wifi_config = {

.sta = {

.ssid = CONFIG_ESP32_WIFI_SSID,

.password = CONFIG_ESP32_WIFI_PASSWORD,

},

};

ret = esp_wifi_set_mode(WIFI_MODE_STA);

ret |= esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);

ret |= esp_wifi_connect();

}

if (ret != ESP_OK) {

LOG_ERR(“Connect failed”);

}

return ret;

}

网络初始化, 完成ethernet iface注册,并注册数据接收callback,

static void eth_esp32_init(struct net_if *iface)

{

const struct device *dev = net_if_get_device(iface);

struct esp32_wifi_runtime *dev_data = DEV_DATA(dev);

dev_data-》iface = iface;

esp32_wifi_iface = iface;

//从ESP32读出MAC地址,设置给zephyr的iface

/* Start interface when we are actually connected with WiFi network */

net_if_flag_set(iface, NET_IF_NO_AUTO_START);

esp_read_mac(dev_data-》mac_addr, ESP_MAC_WIFI_STA);

/* Assign link local address. */

net_if_set_link_addr(iface,

dev_data-》mac_addr, 6, NET_LINK_ETHERNET);

//进行ethernet初始化

ethernet_init(iface);

//注册接收数据的callback,当hal esp32 wifi驱动收到网络封包后会调用eth_esp32_rx

esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, eth_esp32_rx);

}

数据接收

前面的代码可以看到注册的callback是eth_esp32_rx,hal esp32 wifi驱动收到网络封包后会调用eth_esp32_rx,eth_esp32_rx会将网络封包直接转发给IP层

static esp_err_t eth_esp32_rx(void *buffer, uint16_t len, void *eb)

{

struct net_pkt *pkt;

if (esp32_wifi_iface == NULL) {

LOG_ERR(“network interface unavailable”);

return ESP_FAIL;

}

//为封包分配内存

pkt = net_pkt_rx_alloc_with_buffer(esp32_wifi_iface, len,

AF_UNSPEC, 0, K_NO_WAIT);

if (!pkt) {

LOG_ERR(“Failed to get net buffer”);

return ESP_FAIL;

}

//将封包数据从驱动搬运到pkt内

if (net_pkt_write(pkt, buffer, len) 《 0) {

LOG_ERR(“Failed to write pkt”);

goto pkt_unref;

}

//将封包抓发给IP层

if (net_recv_data(esp32_wifi_iface, pkt) 《 0) {

LOG_ERR(“Failed to push received data”);

goto pkt_unref;

}

//通知esp驱动封包数据已经使用完

esp_wifi_internal_free_rx_buffer(eb);

return ESP_OK;

pkt_unref:

net_pkt_unref(pkt);

return ESP_FAIL;

}

数据发送

数据发送的API在初始化时将eth_esp32_send注册进ethernet_api的send, IP层在呼叫L2的send时会找到ethernet_send进行发送,ethernet_send调用就是eth_esp32_send

static int ethernet_send(struct net_if *iface, struct net_pkt *pkt)

{

。。。

//这里api-》send就是注册的eth_esp32_send

ret = net_l2_send(api-》send, net_if_get_device(iface), iface, pkt);

。。。

}

static inline int net_l2_send(net_l2_send_t send_fn,

const struct device *dev,

struct net_if *iface,

struct net_pkt *pkt)

{

net_capture_pkt(iface, pkt);

return send_fn(dev, pkt);

}

static int eth_esp32_send(const struct device *dev, struct net_pkt *pkt)

{

const int pkt_len = net_pkt_get_len(pkt);

//找到frame

/* Read the packet payload */

if (net_pkt_read(pkt, DEV_DATA(dev)-》frame_buf, pkt_len) 《 0) {

return -EIO;

}

//使用hal esp32 wifi进行发送

/* Enqueue packet for transmission */

esp_wifi_internal_tx(ESP_IF_WIFI_STA, (void *)DEV_DATA(dev)-》frame_buf, pkt_len);

LOG_DBG(“pkt sent %p len %d”, pkt, pkt_len);

return 0;

}

待确认

Wifi的帧结构是802.11, 其帧结构和ethernet不一样,现在直接将hal esp32 wifi和zephyr ethernet对接,应该是esp做了相应的转换,具体如何,待确认。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 驱动
    +关注

    关注

    11

    文章

    1710

    浏览量

    84275
  • API
    API
    +关注

    关注

    2

    文章

    1370

    浏览量

    60924
  • WIFI
    +关注

    关注

    80

    文章

    5144

    浏览量

    199192
  • ESP
    ESP
    +关注

    关注

    0

    文章

    168

    浏览量

    33351
  • 开源
    +关注

    关注

    3

    文章

    2953

    浏览量

    41599

原文标题:Zephyr ESP32 wifi驱动简析

文章出处:【微信号:ZephyrProject,微信公众号:ZephyrProject】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    请问foc驱动板上可以用esp32吗?

    foc驱动板上可以用esp32
    发表于 03-19 06:03

    请问foc驱动板上可以用esp32吗?

    foc驱动板上可以用esp32
    发表于 08-07 15:11

    ESP32学习笔记:WiFi

    今天我们来说说ESP32WiFi
    的头像 发表于 07-15 16:20 2184次阅读
    <b class='flag-5'>ESP32</b>学习笔记:<b class='flag-5'>WiFi</b>

    构建ESP32 MicroPython Wifi的机器人汽车

    电子发烧友网站提供《构建ESP32 MicroPython Wifi的机器人汽车.zip》资料免费下载
    发表于 07-12 09:12 5次下载
    构建<b class='flag-5'>ESP32</b> MicroPython <b class='flag-5'>Wifi</b>的机器人汽车

    ESP32ESP32通过Internet进行通信

    电子发烧友网站提供《ESP32ESP32通过Internet进行通信.zip》资料免费下载
    发表于 06-15 09:58 2次下载
    <b class='flag-5'>ESP32</b>到<b class='flag-5'>ESP32</b>通过Internet进行通信

    基于ESP32+MicroPython实现联网并进行UDP通信

    使用 esp32 开发程序,非常重要的功能就是使用 wifi,下面我们就讲一下 esp32 连接 wifi 的方法。
    的头像 发表于 06-13 17:05 3539次阅读
    基于<b class='flag-5'>ESP32</b>+MicroPython实现联网并进行UDP通信

    ESP8266或ESP32上的WiFi Webradio

    电子发烧友网站提供《ESP8266或ESP32上的WiFi Webradio.zip》资料免费下载
    发表于 06-13 11:38 0次下载
    <b class='flag-5'>ESP</b>8266或<b class='flag-5'>ESP32</b>上的<b class='flag-5'>WiFi</b> Webradio

    基于ESP32WiFi温度传感器网络的实现

    电子发烧友网站提供《基于ESP32WiFi温度传感器网络的实现.zip》资料免费下载
    发表于 06-13 11:01 0次下载
    基于<b class='flag-5'>ESP32</b>的<b class='flag-5'>WiFi</b>温度传感器网络的实现

    [esp32教程] 5、UART使用

    基于Ubuntu下,利用esp-idf进行esp32开发的教程
    的头像 发表于 06-13 09:04 3848次阅读
    [<b class='flag-5'>esp32</b>教程] 5、UART使用

    ESP32C2 TCA6416A IO扩展驱动7段显示

    电子发烧友网站提供《ESP32C2 TCA6416A IO扩展驱动7段显示.zip》资料免费下载
    发表于 06-08 11:19 0次下载
    <b class='flag-5'>ESP32</b>C2 TCA6416A IO扩展<b class='flag-5'>驱动</b>7段显示

    [esp32教程] 4、LEDC使用

    基于Ubuntu下,利用esp-idf进行esp32开发的教程
    的头像 发表于 06-03 09:39 2894次阅读
    [<b class='flag-5'>esp32</b>教程] 4、LEDC使用

    ESP8266/ESP32在连接到Wifi网络时的问题求解

    我打算在我的温室中放置一些传感器(BME280、土壤湿度传感器……)来试验收集到的数据。 问题是我的 ESP8266 / ESP32 在连接到我的 Wifi 网络时遇到问题。 难道温室不是
    发表于 04-28 07:12

    乐鑫首款WiFi 6芯片—ESP32-C6现已开售

    乐鑫近期开售的Wi-Fi6“芯”品——ESP32-C6,是继ESP32-C3、ESP32-S3之后的另一款重量级产品。启明云端基于ESP32-C6推出WT0132C6-S5模组,兼容启
    的头像 发表于 04-13 11:02 1418次阅读
    乐鑫首款<b class='flag-5'>WiFi</b> 6芯片—<b class='flag-5'>ESP32</b>-C6现已开售

    如何阻止ping到ESP32

    我正在使用 Esp32-C3 和 ESP IDF。我通过以太网 (W5500) 或 WIFI 连接到网络。当我连接时,我不希望 esp32
    发表于 04-13 07:54

    ESP32-C3一个模块是否具有更长的Wifi范围?

    ESP32-C3-MINI-1和ESP32-C3-WROOM-02是等价的,前者是在封装中集成flash,后者是在模组中集成flash。我注意到天线尺寸也不同,这可能会引发一个问题,我
    发表于 04-12 07:52