LWIP ethernetif.c分析

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
1、ethernetif_init()初始化底层接口
err_t
ethernetif_init(struct netif *netif)
{
  struct ethernetif *ethernetif;
  ethernetif 是一个结构体,用来描述底层硬件设备,该结构体唯一不可或缺的是MAC地址,它是LWIP用于相应ARP查询的核心数据。其他如果没有特殊需要,可以不添加其他成员数据。
    
  ethernetif = mem_malloc(sizeof(struct ethernetif));
  if (ethernetif == NULL) {
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    return ERR_MEM;
  }
#if LWIP_NETIF_HOSTNAME
  /* Initialize interface hostname */
  netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
  /*
   * Initialize the snmp variables and counters inside the struct netif.
   * The last argument should be replaced with your link speed, in units
   * of bits per second.
   */
  NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, ???);
  netif->state = ethernetif;
  netif->name[0] = IFNAME0;
  netif->name[1] = IFNAME1;
  /* We directly use etharp_output() here to save a function call.
   * You can instead declare your own function an call etharp_output()
   * from it if you have to do some checks before sending (e.g. if link
   * is available...) */
  netif->output = ethernetif_output;
向LwIP注册发送函数。注意,这个函数并不是真正的发送函数,它是通过调用下一句完成信息包发送的。
  netif->linkoutput = low_level_output;
向LwIP注册链路层发送函数,该函数完成实际的信息包发送。这个函数需要结合实际的硬件情况亲自编写实现,LwIP仅提供了一个参考结构。
  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
ethernetif->ethaddr指针指向netif中保存的网卡MAC地址 。
  /* initialize the hardware */
  low_level_init(netif);
网卡初始化,建立稳定的物理连接链路并建立接收线程(见图5.4.1中的第(3)、(4)步)。这个函数直接与底层硬件打交道,LwIP仅能为其提供一个参考结构,需要我们结合实际硬件情况重新设计实现。
  return ERR_OK;
}
 
2、low_level_output()――链路层发送函数
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
  struct ethernetif *ethernetif = netif->state;
  struct pbuf *q;
  initiate transfer();
  
#if ETH_PAD_SIZE
  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
  for(q = p; q != NULL; q = q->next) {
    /* Send the data from the pbuf to the interface, one pbuf at a
       time. The size of the data in each pbuf is kept in the ->len
       variable. */
    send data from(q->payload, q->len);
  }
  signal that packet should be sent();
#if ETH_PAD_SIZE
  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
  发送数据包
  LINK_STATS_INC(link.xmit);
  return ERR_OK;
}
3、low_level_init()――网卡初始化函数
static void
low_level_init(struct netif *netif)
{
  struct ethernetif *ethernetif = netif->state;
  
  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;
设置网卡MAC地址的长度。这个长度由LwIP定义的宏NETIF_MAX_HWADDR_LEN指定,长度值为6,单位为字节
  /* set MAC hardware address */
  netif->hwaddr[0] = ;
  ...
  netif->hwaddr[5] = ;
设定MAC地址
  /* maximum transfer unit */
  netif->mtu = 1500;
 设定mtu值 
  /* device capabilities */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
允许处理网络广播通信,ARP。
 
  /* Do whatever else is needed to initialize interface. */  
}
4、ethernetif_input()――实现接收线程
static void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;
  ethernetif = netif->state;
获取当前MAC地址
  /* move received packet into a new pbuf */
  p = low_level_input(netif);
读取EMAC的接收缓冲区
  /* no packet could be read, silently ignore this */
  if (p == NULL) return;
  /* points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;
获得以太网帧头
  switch (htons(ethhdr->type)) {
  /* IP or ARP packet? */
  case ETHTYPE_IP:
  case ETHTYPE_ARP:
#if PPPOE_SUPPORT
  /* PPPoE packet? */
  case ETHTYPE_PPPOEDISC:
  case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
    /* full packet send to tcpip_thread to process */
    if (netif->input(p, netif)!=ERR_OK)
     { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
       pbuf_free(p);
       p = NULL;
     }
    break;
  default:
    pbuf_free(p);
    p = NULL;
    break;
  }
根据以太网帧头携带的上层协议类型值传递数据。以太网帧格式定义:
目的MAC地址 源MAC地址           类型/长度                  数据                     校验
   6字节                  6字节               2字节                   46-1500字节              4字节
                                                 ip:0x0800
                                                ARP:0x0806
最大帧长1518字节 最小字节64字节

}

FreeRTOS+Lwip+STM32 网卡驱动函数运行原理(网卡+wifi) 塞2564196 项目背景 主板是野火的STM32H743,例程也是野火附带的例程,有需要的可以去野火大学堂下载。因为野火只是给出了以太网和wifi的单独例程,而项目需要两者结合在一个工程,所以需要弄清楚两者驱动函数都是如何编写的,方便合并。 Lwip网络接口函数 在Lwip当中,源码作者用netif结构体来表示一个网卡接口,内含网卡的IP地址、数据接收函数、数据发送函数等。然后通过netif_add函数添加到网卡链表当中去。 在源码当中存在一个ethernetif.c文件,这个文件存在5个函数的 阅读详情

相关推荐

lwip初始化流程

lwip初始化流程 lwip初始化不同平台代码可能存在微弱差异,但是大体步骤还是一致的。 lwip_tcpip_init()其中包括tcpip_init,ethernetif_init 一.tcpip_init() 包括lwip_init,sys_thread_new 1.tcpip_init源码如下 void tcpip_init(tcpip_init_done_fn initfunc, voi...

qq_38240926的博客 7813

LwIP 之二 网络接口 netif(netif.c、ethernetif.c、slipif.c)、多网口处理

LwIP 使用 struct netif 来描述一个硬件网络接口。netif 是 LwIP 抽象出来的各网络接口,协议栈可以使用多个不同的接口,而 ./src/netif/ethernet.c、./src/netif/slipif.c 就提供了netif 访问硬件的各接口。

技术干货 1万+

RT-Thread与LWIP协议栈在GD32F450XX上的移植实战:从FreeRTOS到RT-Thread的切换指南

本文详细介绍了将LWIP协议栈从FreeRTOS移植到RT-Thread系统,并在GD32F450XX开发板上实现的完整实战指南。重点解析了sys_arch适配层、邮箱与信号量接口的关键改造,以及网络驱动ethernetif.c的适配步骤,帮助开发者解决线程通信差异,实现稳定网络连接。

linux6sysadmin的博客 795

LwIP之ethernet_if.c和底层驱动概览

ethernet_if.c用来连接LwIP栈和网络接口 ehternet_if.c中使用的函数 1.low_level_init       调用以太网驱动来初始化处理器(ST)以太网外围接口 2.low_level_out      调用以太网驱动来发送以外网数据包 3.low_level_input   调用以太网驱动来接收以太网数据包 4.ethernetif_init

wjjontheway的专栏 8180

LwIP源码分析(4):netif网卡驱动初始化代码分析

本文主要介绍了netif网卡的添加流程,如果想深入了解LwIP协议中的以太网,最好还是要先理解以太网协议,比如前面phyksz8081网卡是怎么根据参考手册进行配置的、用户设置的哪些参数需要设置到芯片的ENET寄存器中。这个如果后续有时间,我会专门写一个博客进行介绍。本文中一些变量的作用也不太明显,光看名字看不出来是干什么的,也没有在我们分析的过程中再出现过。但我们不可能一个个刨根问底地进行分析,但是在后续代码分析过程中遇到了这些变量,回过头来看的时候,我们便会恍然大悟,或者再回来补充这些。

主要分享嵌入式软件、人工智能部分知识 3324

lwip【3】LWIP ethernetif.c分析

1、ethernetif_init()初始化底层接口 err_t ethernetif_init(struct netif *netif) {   struct ethernetif *ethernetif;   ethernetif 是一个结构体,用来描述底层硬件设备,该结构体唯一不可或缺的是MAC地址,它是LWIP用于相应ARP查询的核心数据。其他如果没有特殊需要,可以不添加

yangzhao0001的博客 1454

STM32 基础系列教程 37 - Lwip_igmp

前言 组播通信的特点是报文从一个源发出,被转发到一组特定的接收者。但在组播通信模型中,发送者不关注接收者的位置信息,只是将数据发送到约定的目的组播地址。要使组播报文最终能够到达接收者,需要某种机制使连接接收者网段的组播路由器能够了解到该网段存在哪些组播接收者,同时保证接收者可以加入相应的组播组中。IGMP就是用来在接收者主机和与其所在网段直接相邻的组播路由器之间建立、维护组播组成员关系的协议。 ...

张十三的博客 3650

LwIP移植uCos+stm32f407

LwIP同操作系统一起工作的时候模型如下: 1.TCP/IP协议栈和应用程序以分离的任务运行 2.应用同协议栈沟通是通过API函数调用(API函数调用事实上就是通过OS自带的进程间通信机制,由应用程序与协议栈任务进行邮箱通信) 3.除上述两个任务之外,还有一个额外任务(网络接口任务),该任务由中断激活,然后任务将数据传输给协议栈 这几个任务,对应程序中函数来说的话。 TCP/IP s...

weixin_33878457的博客 869

STM32F4+FreeRTOS实战:如何用LAN8720快速搞定LWIP2.1.2移植(附避坑指南)

本文详细介绍了在STM32F4平台结合FreeRTOS操作系统,为LAN8720以太网PHY芯片移植LWIP 2.1.2协议栈的完整实战流程。内容涵盖硬件连接、CubeMX配置、源码工程化组织、核心移植层代码详解,并重点提供了PHY驱动配置、DMA描述符、内存管理等关键环节的避坑指南,帮助开发者快速构建稳定的嵌入式网络通信基础。

ol789012345的博客 618

嵌入式LWIP协议栈移植实战:从驱动到配置的完整指南

TCP/IP协议栈是嵌入式设备实现网络通信的核心基础,它定义了数据如何在网络中寻址、路由和可靠传输。其工作原理是通过分层模型(如链路层、网络层、传输层)协同工作,将应用数据封装成分组进行传输。在资源受限的嵌入式领域,一个轻量级、可裁剪的协议栈至关重要,它能赋予设备联网能力,广泛应用于物联网终端、工业控制和智能家居等场景。本文将聚焦于轻量级IP协议栈LWIP的移植实践,深入剖析其与硬件平台和实时操作系统的集成过程。移植的关键在于实现网络接口驱动和系统抽象层,其中涉及以太网控制器的底层初始化和数据收发,以及信号

weixin_29159127的博客 8

LWIP 接口(netif 与 ethernetif

本文对 LWIP 中网卡抽象(netif)和底层驱动框架(ethernetif.c)进行梳理,突出关键点与移植要点,方便在嵌入式平台上快速实现网卡对接。

huayidw的博客 1642

LwIP 之 网络接口 netif(ethernetif.c、netif.c)

简介   LwIP使用netif来描述一个硬件网络接口,但是由于网络接口是直接与硬件打交道的,硬件不同则处理可能不同,必须由用户提供最底层接口。LwIP的网络驱动有一定的模型,/src/netif/ethernetif.c文件即为底层接口的驱动的模版,用户为自己的网络设备实现驱动时应参照此模块。该文件中的函数通常为与硬件打交道的函数,当有数据接收的时候被调用,以使接收到的数据进入tcpip协议栈。...

Black_黑色的博客 1万+

LwIP 网络接口 netif(ethernetif.c、netif.c)

/** Generic data structure used for all lwIP network interfaces. * The following fields should be filled in by the initialization * function for the device driver: hwaddr_len, hwaddr[], mtu, fl...

hello_world的博客 1090

lwip学习

Lwip的基本功能 ARP以太网地址解析协议 IP协议,支持ipv4和ipv6 ICMP支持网络调试与维护 IGMP用于网络组管理 UDP TCP支持tcp拥塞设计,rtt时间估计,自动回复重传 DHCP,动态主机配置协议 AUTOIP动态分配ip地址 PPP点对点协议 DNS域名解析 SNMP简单网络管理协议 关系图 lwip提供3种用户变成方式,raw/callback API,BSD-s...

raoxu1154492168的博客 4069

LwIP带操作系统的移植

LwIP是支持操作系统的,在操作系统的支持下我们可以使用LwIP提供的另外两种API编程接口编程。没有操作系统的时候,我们只能使用RAW编程,相较于其他两种API编程,RAW编程难度较大,需要用户对LwIP协议栈有较深的了解。使用操作系统之后,我们可以多任务运行,将LwIP作为任务来运行。

qq_43460068的博客 3318

一文搞定stm32移植LWIP及代码逻辑

一,使用以太网所需要的代码 为了再stm32中使用以太网进行通信,需要使用两个部分的代码。 分别是由ST官方提供的以太网库,以及LWIP库。 其中ST提供的以太网库负责处理硬件PHY与软件的数据交换逻辑,也可以理解成物理层,数据链路层的实现。 而LWIP则负责在软件上实现网络层,传输层等上层协议。 所以下面分两个部分进行移植 二,ST以太网库的移植 首先我使用的是正点原子的stm32f4探索者,其中的MCU为stm32f407,它拥有mac控制器,可以与phy芯片进行数据交换。开发板使用的phy芯片为LAN

杀手的博客 1万+

STM32F407以太网通信避坑指南:LWIP移植中PHY驱动与ethernetif.c的5个关键修改点

本文详细解析了STM32F407以太网通信中LWIP移植的5个关键修改点,包括PHY驱动配置、ethernetif.c函数处理、中断协作机制、网络接口标志位设置以及静态IP与DHCP模式切换。针对STM32开发中常见的网络通讯问题,提供了实用的解决方案和调试技巧,帮助开发者高效完成项目设计中的以太网功能实现。

weixin_33704234的博客 536

LwIP 协议栈移植教程

lwIP是TCP/IP协议套件的一个小型独立实现,本文主要介绍如何在裸机和FreeRTOS环境下,移植 lwIP 协议栈。

Flee Elf 3392
上一篇: LwIP移植心得[转]
下一篇: wireshark报The capture session could not be initiated 错误
slj_win
博客等级 码龄16年 234粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值