lwip---(四)网络接口结构

  今天我们来讨论LWIP是怎样来处理与底层硬件即网卡芯片间的关系的

  为什么要首先讨论这个问题呢?与许多其他的TCP/IP实现一样,LWIP也是以分层的协议为参照来设计实现TCP/IP的LWIP从逻辑上看分为四层:链路层、网络层、传输层和应用层。注意,虽然LWIP也采用了分层机制,但它没有在各层之间进行严格的划分,各层协议之间可以进行或多或少的交叉存取,即上层可以意识到下层协议所使用的缓存处理机制。因此各层可以更有效地重用缓冲区。而且,应用进程和协议栈代码可以使用相同的内存,应用可以直接读写内部缓存,因此节省了执行拷贝的开销。我们将从LWIP的最底层链路层起步,开始整个LWIP内部协议之旅。

  在LWIP中,是通过一个叫做netif网络结构体来描述一个硬件网络接口的。这个接口结构比较简单,下面我们从源代码结构来分析分析这个结构:

struct netif {
  struct netif *next;                     // 指向下一个netif结构的指针
  struct ip_addr ip_addr;                 // IP地址相关配置
  struct ip_addr netmask;
  struct ip_addr gw;

  err_t (* input)(struct pbuf *p, struct netif *inp);        //调用这个函数可以从网卡上取得一个数据包
  err_t (* output)(struct netif *netif, struct pbuf *p,      // IP层调用这个函数可以向网卡发送一个数据包
  
  struct ip_addr *ipaddr);                

  err_t (* linkoutput)(struct netif *netif, struct pbuf *p); // ARP模块调用这个函数向网卡发送一个数据包
  
  void *state;                            // 用户可以独立发挥该指针,用于指向用户关心的网卡信息
  
  u8_t hwaddr_len;                        // 硬件地址长度,对于以太网就是MAC地址长度,为6各字节
  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];      //MAC地址
  u16_t mtu;                              // 一次可以传送的最大字节数,对于以太网一般设为1500
  u8_t flags;                             // 网卡状态信息标志位

  char name[2];                           // 网络接口使用的设备驱动类型的种类
  
  u8_t num;                               // 用来标示使用同种驱动类型的不同网络接口
};

  next字段是指向下一个netif结构的指针。我们的一个产品可能会有多个网卡芯片,LWIP会把所有网卡芯片的结构体链成一个链表进行管理,有一个netif_list的全局变量指向该链表的头部。next字段就是用于链表用。

  ip_addr、netmask、gw三个字段用于发送和处理数据包用,分别表示IP地址、子网掩码和网关地址。前两个字段在数据包发送时有重要作用,第三个字段似乎没什么用。IP地址和网卡设备必须一一对应。如果你连什么叫IP地址、子网掩码和它们的作用都不晓得,那你有必要去看看TCP/IP协议详解卷1第三章。

  input字段指向一个函数,这个函数将网卡设备接收到的数据包提交给IP层,使用时将input指针指向该函数即可,后面将详细讨论这个问题。该函数的两个参数是pbuf类型和netif类型的,返回参数是err_t类型。其中pbuf代表接收到的数据包。

  output字段向一个函数,这个函数和具体网络接口设备驱动密切相关,它用于IP层将一个数据包发送到网络接口上。用户需要根据实际网卡编写该函数,并将output字段指向该函数。该函数的三个参数是pbuf类型、netif类型和ip_addr类型,返回参数是err_t类型。其中pbuf代表要发送的数据包。ipaddr代表网卡需要将该数据包发送到的地址,该地址应该是接收实际的链路层帧的主机的 IP 地址,而不一定为数据包最终需要到达的IP地址。例如,当要发送 IP信息包到一个并不在本地网络里的主机上时,链路层帧会被发送到网络里的一个路由器上。在这种情况下,给 output 函数的 IP地址将是这个路由器的地址。

  linkoutput字段和上面的output基本上是起相同的作用,但是这个函数是在ARP模块中被调用的,这里不赘述了。注意这个函数只有两个参数实际上output字段函数的实现最终还是调用linkoutput字段函数将数据包发送出去的

  state字段可以指向用户关心的关于设备的一些信息,用户可以自由发挥,也可以不用。hwaddr_lenhwaddr[]表示MAC地址长度MAC地址,一般MAC地址长度为6

  mtu字段表示该网络一次可以传送的最大字节数,对于以太网一般设为1500,不多说。

  flags字段是网卡状态信息标志位,是很重要的控制字段,它包括网卡功能使能、广播使能、ARP使能等等重要控制位

  name[]字段用于保存每一个网络网络接口的名字。用两个字符的名字来标识网络接口使用的设备驱动的种类,名字由设备驱动来设置并且应该反映通过网络接口表示的硬件的种类。比如蓝牙设备(bluetooth)的网络接口名字可以是 bt,而 IEEE 802.11b WLAN设备的名字就可以是 wl,当然设置什么名字用户是可以自由发挥的,这并不影响用户对网络接口的使用。当然,如果两个网络接口具有相同的网络名字,我们就用num字段来区分相同类别的不同网络接口。

  到这里,你可能一头雾水,太抽象的东西太容易让人纠结。我们举个例子来看看一个以太网网卡接口结构是这样被初始化,还有数据包是如何接收和发送的。先来看初始化过程,源码:

static struct netif enc28j60;                (1)

struct ip_addr ipaddr, netmask, gw;          (2)

IP4_ADDR(&gw, 192,168,0,1);                  (3)

IP4_ADDR(&ipaddr, 192,168,0,60);             (4)

IP4_ADDR(&netmask, 255,255,255,0);           (5)

netif_init();                                (6)

netif_add(&enc28j60, &ipaddr, &netmask, &gw, NULL, ethernetif_init, tcpip_input);  (7)

netif_set_default(&enc28j60);                (8)

netif_set_up(&enc28j60);                     (9)

  上面的(1)声明了一个netif结构的变量enc28j60,由于在我的板子上使用的是网卡芯片enc28j60,所以我选择使用了这个名字。(2)声明了三个分别用于暂存IP地址、子网掩码和网关地址的变量,它们是32位长度的。(3)~ (5)分别是对上述三个地址值的初始化,该过程简单。

  (6)很简单,它只需初始化上面所述的全局变量netif_list即可:netif_list = NULL

  (7)调用netif_add函数初始化变量enc28j60,其中比较重要的两个参数是ethernetif_inittcpip_input,前者是用户自己定义的底层接口初始化函数,tcpip_input函数是向IP层递交数据包的函数,从前面的讲述中可以很明显的看出,该值会被传递给enc28j60input字段。再来看看源码:

struct netif *
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
	struct ip_addr *gw,
	void *state,
	err_t (* init)(struct netif *netif),
	err_t (* input)(struct pbuf *p, struct netif *netif))
{
	static u8_t netifnum = 0;
	netif->ip_addr.addr = 0;                      //复位变量enc28j60中各字段的值
	netif->netmask.addr = 0;
	netif->gw.addr = 0;
	netif->flags = 0;                             //该网卡不允许任何功能使能
	netif->state = state;                         //指向用户关心的信息,这里为NULL
	netif->num = netifnum++;                      //设置num字段,
	netif->input = input;                         //如前所诉,input函数被赋值
	netif_set_addr(netif, ipaddr, netmask, gw);   //设置变量enc28j60的三个地址
	
	if (init(netif) != ERR_OK) {                  //用户自己的底层接口初始化函数
		return NULL;
	}
	
	netif->next = netif_list;                     //将初始化后的节点插入链表netif_list
	netif_list = netif;                           // netif_list指向链表头
	
	return netif;
}

  上面的初始化函数调用了用户自己定义的底层接口初始化函数,这里为ethernetif_init,再来看看它的源代码:

err_t  ethernetif_init(struct netif *netif)
{
	netif->name[0] = IFNAME0;              //初始化变量enc28j60的name字段
	netif->name[1] = IFNAME1;              // IFNAME在文件外定义的,这里不必关心它的具体值
	netif->output = etharp_output;         //IP层发送数据包函数
	netif->linkoutput = low_level_output;  // //ARP模块发送数据包函数
	low_level_init(netif);                 //底层硬件初始化函数
	
	return ERR_OK;
}

  还有函数调用!low_level_init函数就是与我们使用的硬件密切相关的函数了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于ST官方DfuSe-v3.0.4 ,实现了hex转dfu,解决官方代码的一些bug STM32是由意法半导体(STMicroelectronics)公司推出的基于ARM Cortex-M内核的高性能、低功耗、高性价比32位微控制器系列。自其面世以来,STM32凭借其广泛的适用性和卓越的特性,已成为嵌入式系统设计领域的主流选择之一,广泛应用于工业控制、消费电子、物联网、汽车电子、医疗设备、智能家居等多个领域。 内核与架构 STM32产品线采用了不同版本的ARM Cortex-M内核,包括M0、M0+、M3、M4、M7等,分别对应不同级别的性能需求。这些内核提供单周期乘法、硬件除法、DSP指令集、浮点单元(FPU)等功能,以满足不同应用场景中的计算密集型任务需求。处理器架构遵循哈佛结构,具有独立的指令总线和数据总线,确保高效的代码执行和数据访问。 丰富的外设与接口 STM32微控制器集成了丰富的外设资源,以适应各种复杂系统设计。这些外设包括但不限于: 通信接口:如USART、UART、SPI、I2C、CAN、USB(全速/高速)、Ethernet、无线连接模块(如BLE、Wi-Fi)等,用于实现设备间的串行通信和网络连接。 定时器:多种通用定时器、高级定时器、基本定时器以及PWM输出,支持定时、计数、脉冲捕获、电机控制等多种功能。 模拟外设:高精度ADC(模数转换器)、DAC(数模转换器)、比较器、温度传感器等,用于采集和处理模拟信号。 存储器:内置Flash和SRAM,容量从几KB到几MB不等,满足不同应用的数据存储和运行空间需求。部分型号还支持外部存储器接口(如FSMC、Octo-SPI)以扩展存储能力。 安全与保护机制:如加密加速器、安全单元、内存保护单元(MPU)、看门狗定时器、时钟安全系统(CSS)等,保障系统安全稳定运行。 开发环境与生态系统 STM32拥有强大的软件支持和生态系统,简化开发流程并加速产品上市时间: 开发工具:官方提供STM32CubeMX初始化配置工具,帮助开发者快速进行项目设置、外设配置及代码生成。此外,还有STM32CubeIDE集成开发环境,集成了编译器、调试器和仿真器支持。 软件库:STM32Cube软件包包含HAL(硬件抽象层)库和LL(低层)库,前者提供跨平台、跨系列的统一API接口,后者直接面向寄存器提供高效访问。同时,还提供各类外设驱动、中间件组件(如FreeRTOS、FatFS、LwIP等)以及特定应用框架(如STM32Cube.AI for AI推理)。 社区与资源:ST官方社区、论坛、博客、技术文档、培训材料、应用笔记、用户案例等资源丰富,为开发者提供全方位的技术支持和交流平台。 产品线与封装 STM32产品线按性能、功耗、外设组合等特性划分为多个子系列,如STM32F、STM32L、STM32G、STM32H等,每个子系列下又包含多种型号,以适应不同成本、性能、尺寸和功耗要求。封装形式多样,从小型QFN、LQFP到大型BGA,满足不同应用场景的封装密度和散热需求。 综上所述,STM32微控制器以其强大的内核性能、丰富的外设集成、完善的开发支持和广泛的市场应用,为嵌入式系统设计提供了高度灵活且极具竞争力的解决方案。
STM32是由意法半导体(STMicroelectronics)公司推出的基于ARM Cortex-M内核的高性能、低功耗、高性价比32位微控制器系列。自其面世以来,STM32凭借其广泛的适用性和卓越的特性,已成为嵌入式系统设计领域的主流选择之一,广泛应用于工业控制、消费电子、物联网、汽车电子、医疗设备、智能家居等多个领域。 内核与架构 STM32产品线采用了不同版本的ARM Cortex-M内核,包括M0、M0+、M3、M4、M7等,分别对应不同级别的性能需求。这些内核提供单周期乘法、硬件除法、DSP指令集、浮点单元(FPU)等功能,以满足不同应用场景中的计算密集型任务需求。处理器架构遵循哈佛结构,具有独立的指令总线和数据总线,确保高效的代码执行和数据访问。 丰富的外设与接口 STM32微控制器集成了丰富的外设资源,以适应各种复杂系统设计。这些外设包括但不限于: 通信接口:如USART、UART、SPI、I2C、CAN、USB(全速/高速)、Ethernet、无线连接模块(如BLE、Wi-Fi)等,用于实现设备间的串行通信和网络连接。 定时器:多种通用定时器、高级定时器、基本定时器以及PWM输出,支持定时、计数、脉冲捕获、电机控制等多种功能。 模拟外设:高精度ADC(模数转换器)、DAC(数模转换器)、比较器、温度传感器等,用于采集和处理模拟信号。 存储器:内置Flash和SRAM,容量从几KB到几MB不等,满足不同应用的数据存储和运行空间需求。部分型号还支持外部存储器接口(如FSMC、Octo-SPI)以扩展存储能力。 安全与保护机制:如加密加速器、安全单元、内存保护单元(MPU)、看门狗定时器、时钟安全系统(CSS)等,保障系统安全稳定运行。 开发环境与生态系统 STM32拥有强大的软件支持和生态系统,简化开发流程并加速产品上市时间: 开发工具:官方提供STM32CubeMX初始化配置工具,帮助开发者快速进行项目设置、外设配置及代码生成。此外,还有STM32CubeIDE集成开发环境,集成了编译器、调试器和仿真器支持。 软件库:STM32Cube软件包包含HAL(硬件抽象层)库和LL(低层)库,前者提供跨平台、跨系列的统一API接口,后者直接面向寄存器提供高效访问。同时,还提供各类外设驱动、中间件组件(如FreeRTOS、FatFS、LwIP等)以及特定应用框架(如STM32Cube.AI for AI推理)。 社区与资源:ST官方社区、论坛、博客、技术文档、培训材料、应用笔记、用户案例等资源丰富,为开发者提供全方位的技术支持和交流平台。 产品线与封装 STM32产品线按性能、功耗、外设组合等特性划分为多个子系列,如STM32F、STM32L、STM32G、STM32H等,每个子系列下又包含多种型号,以适应不同成本、性能、尺寸和功耗要求。封装形式多样,从小型QFN、LQFP到大型BGA,满足不同应用场景的封装密度和散热需求。 综上所述,STM32微控制器以其强大的内核性能、丰富的外设集成、完善的开发支持和广泛的市场应用,为嵌入式系统设计提供了高度灵活且极具竞争力的解决方案。
作者:杨红超 绪论 本章主要阐述多功能气压计的应用背景,包括根据大气压强判断和确定建筑工人的楼层位置、帮助建筑工人感知周围环境温度变化等,同时也可根据大气压强判断无人机的GPS定位。其次着重介绍气压计的具体功能,如可以通过对工人周围的气压和温度的采集计算出当前所在的楼层位置,并将数据信息通过ONENET上传到云服务器上,通过语音识别实现设备在线升级功能。最后对本次设计的组织结构进行介绍,以表明每章节的主要内容和作用。 1.1应用背景 为确保建筑工人在工地施工时的人身安全,故此设计一款工人们的“运行手环”——多功能气压计。它内置气体压强检测装置可实时检测建筑工人身处的大气压强和周围的环境温度,进而根据采集的数据推算出工人所在的楼层高度,并将数据实时上传到云服务器上通过管理者对数据的检测给建筑工人提供一份双保险。 此外,该多功能气压计还具有无人机GPS定位和判断吸尘器吸力大小等应用于多对象、多环境的特点。 1.2实现功能 本次多功能气压计的设计硬件采用ART-Pi开发板、LPS22HH气压传感器和LD3320语音识别模块,操作系统使用RT-Thread 4.0.3,软件使用RT-Thread Studio 1.1.5开发平台和使用C语言实现软件编程,具有如下功能: (1)利用LPS22HH气压传感器实时对大气压的压强进行采集,并通过SPI4接口将采集的数据传给单片机。 (2)利用AP6212 WIFI模块实时将经过处理后的数据,如温度值和楼层信息等上传到云服务器;同时通过WIFI模块实现在线升级用户程序。 (3)语音识别模块通过SPI2实现与开发板的数据交互,完成语音重启设备和语音在线升级功能。 1.3设计组织结构 本次基于ART-Pi开发板的多功能气压计设计,主要分为五个章节其具体设计组织结构如下: 第一章绪论,主要介绍多功能气压计的实际应用背景和具有的具体功能,以及设计组织结构的规划。 第二章RT-Thread概述,主要对在本设计中涉及的RT-Thread内核、及其组件和软件包进行阐述,欲以说明对RT-Thread操作系统的使用情况和了解程度,同时对其内容作些简单的介绍。 第三章硬件设计,主要阐述硬件模块的电气连接和本次设计使用的硬件电路,如LPS22HH气压传感器、ART-Pi开发板和语音识别模块等。 第章软件设计,主要阐述软件实现的设计流程和各个软件模块设计的框架,以及模块之间的通讯方式。 第五章总结与展望,主要阐述对本次设计的评估,即软件设计存在的不足和功能与性能存在的不足,以及针对不足之处提出的具体改进措施和方案、参加比赛的感悟和心得。 1.4本章小节 本章主要介绍多功能气压计的应用背景和具体的应用功能,以及对软硬件开发环境和该设计文档的组织结构进行阐述。 RT-Thread概述 本章主要阐述在软件设计中关于RT-Thread操作系统的应用情况,如与线程运行有关的采用动态方式创建线程,与线程同步有关的信号量的动态创建、释放和获取,以及与网络有关的SAL组件、OneNET软件包等。 2.1内核 为了提高软件运行的并发性和数据采集的实时性,故使用内核中的核心部分——线程,使其维护和管理每个任务的运行,同时以使用信号量和事件集等的同步方式,以及使用邮箱和消息队列等的通信方式来确保每个任务在运行过程中能“自由飞翔”。 不仅如此,为增加任务在运行状态中的时间和提高每个任务响应的快慢速度,故使用线程中重要的两个属性即线程优先级和时间片,并根据应用的具体环境和软实时性的要求将每个任务赋予各自该具有的任务优先级和时间片。同时,使用rt_thread_mdelay延迟函数来定时释放线程(任务)确保在其处于非运行态时可以退出时间片以让其它任务能及时运行。 2.2驱动 在bootloader程序中主要初始化SPI和SFUD驱动实现对外部SPI FLASH的读写操作,同时结合使用FAL软件包将操作FLASH的函数进行分层,进而实现在bootloader程序中读取“download”分区的升级固件,以及使用ota_downloader软件包完成升级固件的下载,最后使用出厂W25QXX函数实现固件搬运工作进而完成在线升级应用。 2.3组件 SAL组件完成并提供了基于RT-Thread操作系统的对不同网络协议栈网络实现接口的抽象和与上层应用有关的一组标准BSD Socket API,在网络开发设计时可只需关心和使用网络应用层提供的网络接口,而无需关心底层具体网络协议栈类型和具体实现,如TCP/IP协议栈LWIP和AT Socket网络。SAL组件不仅提高了软件系统对底层驱动的兼容性,而且缩短了网络开发周期。此外,SAL组件还具有一下功能特点[1]: 抽象、统一多种网络协议栈接口; 提供Socket层面的TLS加密传输特性; 支持标准BSP S
STM32F1是意法半导体公司推出的一款32位ARM Cortex-M3单片机系列产品,具有良好的性能和扩展能力。它采用了低功耗技术,集成了丰富的外设和内存,适用于广泛的应用领域。 寄存器是计算机体系结构中的重要组成部分,用于存储和操作数据。STM32F1芯片内部集成了大量的寄存器,包括通用寄存器、特殊功能寄存器和外设寄存器等。通过对寄存器的读写操作,可以实现对芯片内部各种功能的配置和控制。 LwIP-2.1.2是一个开源的轻量级网络协议栈,适用于嵌入式系统。它提供了TCP/IP协议栈的实现,支持各种网络协议和服务,例如IP、TCP、UDP、ARP、DHCP、DNS等。LwIP-2.1.2具有较小的内存占用和高性能的特点,适用于资源有限的嵌入式环境。 ENC28J60是一款低成本的SPI以太网控制器芯片,由微芯科技(Microchip Technology)公司推出。它支持10Mbps以太网通信,采用硬件SPI接口和内部缓存,能够有效减少主控制器的负担。ENC28J60与STM32F1可以通过SPI总线进行连接,用于实现嵌入式设备与以太网的通信。 综上所述,STM32F1是一款强大的单片机系列产品,具备丰富的外设和可编程寄存器,可以灵活配置和控制芯片内部功能。LwIP-2.1.2是一个轻量级的网络协议栈,用于实现嵌入式系统的网络通信。ENC28J60是一款低成本的以太网控制器芯片,可以与STM32F1通过SPI总线进行连接。这些技术的结合可以实现嵌入式设备的网络功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值