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

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

3天内不再提示

RT-Thread源码分析之网卡数据的接收和发送

冬至子 来源:happycode999 作者:happycode999 2023-08-11 16:49 次阅读

一、lwip网卡接口ethernetif.c
ethernetif.c是lwip的网卡接口,在该接口中处理网卡的数据接收和发送,rt-thread在该接口文件中抽象了一个eth_device,管理网络数据的收发和向内核的netdev_list添加netdev。

二、网络设备eth_device
eth_device是rt-thread实现的ethernetif。

struct eth_device
{
/* inherit from rt_device /
struct rt_device parent;
/
network interface for lwip */
struct netif netif;
struct rt_semaphore tx_ack;
rt_uint16_t flags;
rt_uint8_t link_changed;
rt_uint8_t link_status;
/
eth device interface /
struct pbuf
(*eth_rx)(rt_device_t dev);
rt_err_t (eth_tx)(rt_device_t dev, struct pbuf p);
};
netif:lwip的网络接口。
eth_rx:底层数据接收接口。
eth_tx:底层数据发送接口。

三、网络设备数据的接收和发送
网络设备的接收和发送通过eth_device的eth_rx和eth_tx完成。在系统初始化时内核调用eth_system_device_init创建erx和etx两个线程,用于处理接收和发送。

3.1 数据接收
当erx线程起来后,等待eth_rx_thread_mb,当网卡准备好或者改变网卡状态时,往下执行,进入while(1)处理网卡接收,调用网卡注册的eth_rx接收网卡数据,并传递给协议栈上层。

static void eth_rx_thread_entry(void* parameter)
{
struct eth_device* device;
while (1)
{
if (rt_mb_recv(ð_rx_thread_mb, (rt_ubase_t*)&device, RT_WAITING_FOREVER) == RT_EOK)
{
struct pbuf p;
/
check link status /
if (device->link_changed)
{
int status;
rt_uint32_t level;
level = rt_hw_interrupt_disable();
status = device->link_status;
device->link_changed = 0x00;
rt_hw_interrupt_enable(level);
if (status)
netifapi_netif_set_link_up(device->netif);
else
netifapi_netif_set_link_down(device->netif);
}
/
receive all of buffer /
while (1)
{
if(device->eth_rx == RT_NULL) break;
p = device->eth_rx(&(device->parent));
if (p != RT_NULL)
{
/
notify to upper layer */
if( device->netif->input(p, device->netif) != ERR_OK )
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input errorn"));
pbuf_free(p);
p = NULL;
}
}
else break;
}
}
else
{
LWIP_ASSERT("Should not happen!n",0);
}
}
}
3.2 数据发送
当协议栈需要发送数据时,调用netif的linkoutput接口,在linkoutput中,将数据封装成消息发送给etx线程,最终通过eth_device的eth_tx接口将数据发送出去。

static void eth_tx_thread_entry(void* parameter)
{
struct eth_tx_msg* msg;
while (1)
{
if (rt_mb_recv(ð_tx_thread_mb, (rt_ubase_t*)&msg, RT_WAITING_FOREVER) == RT_EOK)
{
struct eth_device* enetif;
RT_ASSERT(msg->netif != RT_NULL);
RT_ASSERT(msg->buf != RT_NULL);
enetif = (struct eth_device*)msg->netif->state;
if (enetif != RT_NULL)
{
/* call driver's interface /
if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK)
{
/
transmit eth packet failed /
}
}
/
send ACK */
rt_sem_release(&(enetif->tx_ack));
}
}
}

四、wlan设备数据的接收和发送
wlan设备的数据接收和发送是通过rt_wlan_prot完成的,rt_wlan_prot是对不同协议簇的抽象,在rt_wlan_set_mode启动wlan设备时,最终会调用rt_wlan_prot_attach将lwip协议簇挂载到wlan设备,在挂载过程中,会根据协议簇的名称匹配注册的rt_wlan_prot,并调用rt_wlan_prot的register将wlan设备注册到内核。

4.1 数据接收
在网卡的接收中断中,调用rt_wlan_dev_transfer_prot将网卡设备接收的数据传递给上层处理。

rt_err_t rt_wlan_dev_transfer_prot(struct rt_wlan_device *wlan, void *buff, int len)
{
struct rt_wlan_prot *prot = wlan->prot;
if (prot != RT_NULL)
{
return prot->ops->prot_recv(wlan, buff, len);
}
return -RT_ERROR;
}
注册到rt_wlan_prot的接收函数是rt_wlan_lwip_protocol_recv,在rt_wlan_lwip_protocol_recv中,通过lwip_prot_des获取eth_device(netif在eth_device_init_with_flag中被注册到eth_device),接着便可使用其中的netif的input将数据交给上层。

static rt_err_t rt_wlan_lwip_protocol_recv(struct rt_wlan_device *wlan, void *buff, int len)
{
struct eth_device *eth_dev = &((struct lwip_prot_des *)wlan->prot)->eth;//eth在rt_wlan_lwip_protocol_register中注册
struct pbuf *p = RT_NULL;
//...省略
{
p = buff;
if ((eth_dev->netif->input(p, eth_dev->netif)) != ERR_OK)
{
return -RT_ERROR;
}
return RT_EOK;
}
//...省略
}

4.2 数据发送
当协议栈需要发送数据时,会调用rt_wlan_prot_transfer_dev将数据传递给wlan设备,在rt_wlan_prot_transfer_dev中,会调用wlan设备的发送接口将数据发送出去。

4.3 以w601举例
w601的wlan驱动在driver文件夹下的drv_wifi.c。

4.3.1 数据接收
在内核需要初始化wlan的时候,调用drv_wlan_init,在tls_ethernet_data_rx_callback函数中注册wm_ethernetif_input到wifi接收中断,在wm_ethernetif_input中调用rt_wlan_dev_transfer_prot将接收的数据传给协议栈上层。

4.3.2 数据发送
在drv_wifi.c中,将drv_wlan_send函数注册到发送接口,在协议栈需要发送数据时,通过rt_wlan_prot_transfer_dev调用这个接口完成数据的发送。

static const struct rt_wlan_dev_ops ops =
{
//...省略
.wlan_recv = drv_wlan_recv,
.wlan_send = drv_wlan_send,/ 向内核注册的发送接口 /
};

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

    关注

    8

    文章

    1122

    浏览量

    52654
  • WLAN技术
    +关注

    关注

    0

    文章

    23

    浏览量

    9221
  • LwIP协议
    +关注

    关注

    0

    文章

    11

    浏览量

    8853
  • 串口中断
    +关注

    关注

    0

    文章

    63

    浏览量

    13615
  • RT-Thread
    +关注

    关注

    31

    文章

    1150

    浏览量

    38911
收藏 人收藏

    评论

    相关推荐

    RT-Thread记录(十一、UART设备—源码解析)

    一文带你深入理解 RT-Thread I/O 设备模型 — UART 设备源码分析
    的头像 发表于 07-01 11:24 5033次阅读
    <b class='flag-5'>RT-Thread</b>记录(十一、UART设备—<b class='flag-5'>源码</b>解析)

    RT-Thread记录(二、RT-Thread内核启动流程)

    在前面我们RT-Thread Studio工程基础之上讲一讲RT-Thread内核启动流程.
    的头像 发表于 06-20 00:30 4426次阅读
    <b class='flag-5'>RT-Thread</b>记录(二、<b class='flag-5'>RT-Thread</b>内核启动流程)

    RT-thread源码移植到STM32F10x和STM32F4xx

    RT-thread源码移植到STM32F10x和STM32F4xx: 一、源码下载 点击入门->下载   在历史版本里边随便选取一个   会进入百度云盘的下载地址,里边有全部版本的源码
    的头像 发表于 11-15 09:38 1037次阅读
    <b class='flag-5'>RT-thread</b><b class='flag-5'>源码</b>移植到STM32F10x和STM32F4xx

    RT-Thread的线程简介

    文章目录RT-Thread的线程简介源码分析初始化线程线程脱离启动线程挂起线程线程睡眠线程让出测试参考资料:RTT官网文档关键字:分析RT-Thre
    发表于 08-24 07:56

    【原创精选】RT-Thread征文精选技术文章合集

    优化系列(零) SysTick 优化分析rt-thread 优化系列(一) 过多关中断rt-thread 优化系列(二) 同步和消
    发表于 07-26 14:56

    如何使用RT-Thread的串口设备

    。进阶阅读串口通常被配置为接收中断和轮询发送模式。在中断模式下,CPU 不需要一直查询等待串口相关标志寄存器,串口接收数据后触发中断,我们在中断服务程序进行
    发表于 10-25 11:05

    基于RT-Thread的FM1702源码

    RT-Thread是一款来自中国的开源嵌入式实时操作系统,包括一系列应用组件和驱动框架,如TCP/IP协议栈,虚拟文件系统,POSIX接口,图形用户界面。---(转自RTT官网)。 FM1702是无线射频的一种,现将其移植到RT-Thread操作系统中。
    发表于 12-28 10:54 15次下载

    RT-Thread开发,如何有效学习RT-Thread的五个步骤

    RT-Thread推出RT-Thread Inside战略开放RT-Thread开发平台授权合作,与硬件十万个为什么合作首次推出第一款RT-Inside的开发板——iBox物联网开发套
    的头像 发表于 09-25 09:55 3.4w次阅读
    <b class='flag-5'>RT-Thread</b>开发,如何有效学习<b class='flag-5'>RT-Thread</b>的五个步骤

    源码解读·RT-Thread操作系统从开机到关机(转)

    源码解读·RT-Thread操作系统从开机到关机本篇内容比较简单,但却很繁琐,篇幅也很长,毕竟是囊括了整个操作系统的生命周期。这篇文章的目的是作为后续设计多任务开发的铺垫,后续会单独再抽出一篇分析
    发表于 12-16 16:58 11次下载
    <b class='flag-5'>源码</b>解读·<b class='flag-5'>RT-Thread</b>操作系统从开机到关机(转)

    RT-Thread开源作品秀】基于RT-Thread的星务平台研究

    本作品为了验证星务软件在RT-Thread系统运行的可行性,底层是否能够驱动星务软件,同时扩展RT-Thread应用范围。ART-Pi作为卫星下位机,...
    发表于 01-25 18:26 5次下载
    【<b class='flag-5'>RT-Thread</b>开源作品秀】基于<b class='flag-5'>RT-Thread</b>的星务平台研究

    RT-Thread自动初始化机制

      在分析之前首先查阅 RT-Thread 的官方文档 [RT-Thread 自动初始化机制](https://www.rt-thread.org/document/site
    的头像 发表于 06-17 08:52 1920次阅读
    <b class='flag-5'>RT-Thread</b>自动初始化机制

    RT-Thread学习笔记 RT-Thread的架构概述

    RT-Thread 简介 作为一名 RTOS 的初学者,也许你对 RT-Thread 还比较陌生。然而,随着你的深入接触,你会逐渐发现 RT-Thread 的魅力和它相较于其他同类型 RTOS
    的头像 发表于 07-09 11:27 4004次阅读
    <b class='flag-5'>RT-Thread</b>学习笔记 <b class='flag-5'>RT-Thread</b>的架构概述

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> 简介

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 7次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    rt-thread源码分析之socket抽象层和网卡注册

    如图所示,rt-thread的网络分为应用层、sal_socket、netdev、协议簇(at、lwip、wiznet)、网卡驱动五层。
    的头像 发表于 11-13 12:43 404次阅读