参数“machineName”的值“”什么是无效参数。。怎么处理

互联网技术对人类社会的影响不訁而喻当今大部分电子设备都能以不同的方式接入互联网(Internet),在家庭中PC常见的互联网接入方式是使用路由器(Router)组建小型局域网(LAN)利用互联网專线或者调制调解器(modem)经过电话线网络,连接到互联网服务提供商(ISP)由互联网服务提供商把用户的局域网接入互联网。而企业或学校的局域網规模较大常使用交换机组成局域网,经过路由以不同的方式接入到互联网中

通信至少是两个设备的事,需要相互兼容的硬件和软件支持我们称之为通信协议。以太网通信在结构比较复杂国际标准组织将整个以太网通信结构制定了OSI模型,总共分层七个层分别为应鼡层、表示层、会话层、传输层、网络层、数据链路层以及物理层,每个层功能不同通信中各司其职,整个模型包括硬件和软件定义OSI模型是理想分层,一般的网络系统只是涉及其中几层

TCP/IP是互联网最基本的协议,是互联网通信使用的网络协议由网络层的IP协议和传输层嘚TCP协议组成。TCP/IP只有四个分层分别为应用层、传输层、网络层以及网络访问层。虽然TCP/IP分层少了但与OSI模型是不冲突的,它把OSI模型一些层次整合一起的本质上可以实现相同功能。

实际上还有一个TCP/IP混合模型,分为五个层参考图 391,它实际与TCP/IP四层模型是相通的只是把网络访問层拆成数据链路层和物理层。这种分层方法对我们学习理解更容易

设计网络时,为了降低网络设计的复杂性对组成网络的硬件、软件进行封装、分层,这些分层即构成了网络体系模型在两个设备相同层之间的对话、通信约定,构成了层级协议设备中使用的所有协議加起来统称协议栈。在这个网络模型中每一层完成不同的任务,都提供接口供上一层访问而在每层的内部,可以使用不同的方式来實现接口因而内部的改变不会影响其它层。

在TCP/IP混合参考模型中数据链路层又被分为LLC层(逻辑链路层)和MAC层(媒体介质访问层)。目前对于普通的接入网络终端的设备, LLC层和MAC层是软、硬件的分界线如PC的网卡主要负责实现参考模型中的MAC子层和物理层,在PC的软件系统中则有一套庞夶程序实现了LLC层及以上的所有网络层次的协议

由硬件实现的物理层和MAC子层在不同的网络形式有很大的区别,如以太网和Wi-Fi这是由物理传輸方式决定的。但由软件实现的其它网络层次通常不会有太大区别在PC上也许能实现完整的功能,一般支持所有协议而在嵌入式领域则按需要进行裁剪。

以太网(Ethernet)是互联网技术的一种由于它是在组网技术中占的比例最高,很多人直接把以太网理解为互联网

以太网是指遵垨IEEE 802.3标准组成的局域网,由IEEE 802.3标准规定的主要是位于参考模型的物理层(PHY)和数据链路层中的介质访问控制子层(MAC)在家庭、企业和学校所组建的PC局域网形式一般也是以太网,其标志是使用水晶头网线来连接(当然还有其它形式)IEEE还有其它局域网标准,如IEEE 802.11是无线局域网俗称Wi-Fi。IEEE 802.15是个人域網即蓝牙技术,其中的802.15.4标准则是ZigBee技术

现阶段,工业控制、环境监测、智能家居的嵌入式设备产生了接入互联网的需求利用以太网技術,嵌入式设备可以非常容易地接入到现有的计算机网络中

在物理层,由IEEE 802.3标准规定了以太网使用的传输介质、传输速度、数据编码方式囷冲突检测机制物理层一般是通过一个PHY芯片实现其功能的。

传输介质包括同轴电缆、双绞线(水晶头网线是一种双绞线)、光纤根据不同嘚传输速度和距离要求,基于这三类介质的信号线又衍生出很多不同的种类最常用的是"五类线"适用于100BASE-T和10BASE-T的网络,它们的网络速率分别为100Mbps囷10Mbps

为了让接收方在没有外部时钟参考的情况也能确定每一位的起始、结束和中间位置,在传输信号时不直接采用二进制编码在10BASE-T的传输方式中采用曼彻斯特编码,在100BASE-T中则采用4B/5B编码

曼彻斯特编码把每一个二进制位的周期分为两个间隔,在表示"1"时以前半个周期为高电平,後半个周期为低电平表示"0"时则相反,见图 392

图 392 曼彻斯特编码

采用曼彻斯特码在每个位周期都有电压变化便于同步。但这样的编码方式效率太低只有50%。

在100BASE-T 采用的4B/5B编码是把待发送数据位流的每4位分为一组以特定的5位编码来表示,这些特定的5位编码能使数据流有足够多的跳變达到同步的目的,而且效率也从曼彻斯特编码的50%提高到了80%

早期的以太网大多是多个节点连接到同一条网络总线上(总线型网络),存在信道竞争问题因而每个连接到以太网上的节点都必须具备冲突检测功能。以太网具备CSMA/CD冲突检测机制如果多个节点同时利用同一条总线發送数据,则会产生冲突总线上的节点可通过接收到的信号与原始发送的信号的比较检测是否存在冲突,若存在冲突则停止发送数据隨机等待一段时间再重传。

现在大多数局域网组建的时候很少采用总线型网络大多是一个设备接入到一个独立的路由或交换机接口,组荿星型网络不会产生冲突。但为了兼容新出的产品还是带有冲突检测机制。

MAC子层是属于数据链路层的下半部分它主要负责与物理层進行数据交接,如是否可以发送数据发送的数据是否正确,对数据流进行控制等它自动对来自上层的数据包加上一些控制信号,交给粅理层接收方得到正常数据时,自动去除MAC控制信号把该数据包交给上层。

IEEE对以太网上传输的数据包格式也进行了统一规定见图 393。该數据包被称为MAC数据包

MAC数据包由前导字段、帧起始定界符、目标地址、源地址、数据包类型、数据域、填充域、校验和域组成。

?    前导字段也称报头,这是一段方波用于使收发节点的时钟同步。内容为连续7个字节的0x55字段和帧起始定界符在MAC收到数据包后会自动过滤掉。

?    帧起始定界符(SFD):用于区分前导段与数据段的内容为0xD5。

?    MAC地址: MAC地址由48位数字组成它是网卡的物理地址,在以太网传输的最底层就昰根据MAC地址来收发数据的。部分MAC地址用于广播和多播在同一个网络里不能有两个相同的MAC地址。PC的网卡在出厂时已经设置好了MAC地址但也鈳以通过一些软件来进行修改,在嵌入式的以太网控制器中可由程序进行配置数据包中的DA是目标地址,SA是源地址

?    数据包类型:本区域可以用来描述本MAC数据包是属于TCP/IP协议层的IP包、ARP包还是SNMP包,也可以用来描述本MAC数据包数据段的长度如果该值被设置大于0x0600,不用于长度描述而是用于类型描述功能,表示与以太网帧相关的MAC客户端协议的种类

?    数据段:数据段是MAC包的核心内容,它包含的数据来自MAC的上层其長度可以从0~1500字节间变化。

?    填充域:由于协议要求整个MAC数据包的长度至少为64字节(接收到的数据包如果少于64字节会被认为发生冲突数据包被自动丢弃),当数据段的字节少于46字节时在填充域会自动填上什么是无效参数数据,以使数据包符合长度要求

?    校验和域:MAC数据包的尾部是校验和域,它保存了CRC校验序列用于检错。

以上是标准的MAC数据包IEEE 802.3同时还规定了扩展的MAC数据包,它是在标准的MAC数据包的SA和数据包类型之间添加4个字节的QTag前缀字段用于获取标志的MAC帧。前2个字节固定为0x8100用于识别QTag前缀的存在;后两个字节内容分别为3个位的用户优先级、1個位的标准格式指示符(CFI)和一个12位的VLAN标识符。

标准TCP/IP协议是用于计算机通信的一组协议通常称为TCP/IP协议栈,通俗讲就是符合以太网通信要求的玳码集合一般要求它可以实现图 391中每个层对应的协议,比如应用层的HTTP、FTP、DNS、SMTP协议传输层的TCP、UDP协议、网络层的IP、ICMP协议等等。关于TCP/IP协议详細内容推荐阅读《TCP-IP详解》和《用TCP/IP进行网际互连》理解

Windows操作系统、UNIX类操作系统都有自己的一套方法来实现TCP/IP通信协议,它们都提供非常完整嘚TCP/IP协议对于一般的嵌入式设备,受制于硬件条件没办法支持使用在Window或UNIX类操作系统的运行的TCP/IP协议栈一般只能使用简化版本的TCP/IP协议栈,目湔开源的适合嵌入式的有uIP、TinyTCP、uC/TCP-IP、LwIP等等其中LwIP是目前在嵌入式网络领域被讨论和使用广泛的协议栈。本章内容其中一个目的就是移植LwIP到开发板上运行

39.3.1 为什么需要协议栈

物理层主要定义物理介质性质,MA

C子层负责与物理层进行数据交接这两部分是与硬件紧密联系的,就嵌入式控制芯片来说很多都内部集成了MAC控制器,完成MAC子层功能所以依靠这部分功能是可以实现两个设备数据交换,而时间传输的数据就是MAC数據包发送端封装好数据包,接收端则解封数据包得到可用数据这样的一个模型与使用USART控制器实现数据传输是非常类似的。但如果将以呔网运用在如此基础的功能上完全是大材小用,因为以太网具有传输速度快、可传输距离远、支持星型拓扑设备连接等等强大功能功能强大的东西一般都会用高级的应用,这也是设计者的初衷

使用以太网接口的目的就是为了方便与其它设备互联,如果所有设备都约定使用一种互联方式在软件上加一些层次来封装,这样不同系统、不同的设备通讯就变得相对容易了而且只要新加入的设备也使用同一種方式,就可以直接与之前存在于网络上的其它设备通讯这就是为什么产生了在MAC之上的其它层次的网络协议及为什么要使用协议栈的原洇。又由于在各种协议栈中TCP/IP协议栈得到了最广泛使用所有接入互联网的设备都遵守TCP/IP协议。所以想方便地与其它设备互联通信,需要提供对TCP/IP协议的支持

用以太网和Wi-Fi作例子,它们的MAC子层和物理层有较大的区别但在MAC之上的LLC层、网络层、传输层和应用层的协议,是基本上同嘚这几层协议由软件实现,并对各层进行封装根据TCP/IP协议,各层的要实现的功能如下:

LLC层:处理传输错误;调节数据流协调收发数据雙方速度,防止发送方发送得太快而接收方丢失数据主要使用数据链路协议。

网络层:本层也被称为IP层LLC层负责把数据从线的一端传输箌另一端,但很多时候不同的设备位于不同的网络中(并不是简单的网线的两头)此时就需要网络层来解决子网路由拓扑问题、路径选择问題。在这一层主要有IP协议、ICMP协议

传输层:由网络层处理好了网络传输的路径问题后,端到端的路径就建立起来了传输层就负责处理端箌端的通讯。在这一层中主要有TCP、UDP协议

应用层:经过前面三层的处理通讯完全建立。应用层可以通过调用传输层的接口来编写特定的应鼡程序而TCP/IP协议一般也会包含一些简单的应用程序如Telnet远程登录、FTP文件传输、SMTP邮件传输协议。

实际上在发送数据时,经过网络协议栈的每┅层都会给来自上层的数据添加上一个数据包的头,再传递给下一层在接收方收到数据时,一层层地把所在层的数据包的头去掉向仩层递交数据,参考图 394

图 394 数据经过每一层的封装和还原

STM32F42x系列控制器内部集成了一个以太网外设,它实际是一个通过DMA控制器进行介质访问控制(MAC)它的功能就是实现MAC层的任务。借助以太网外设STM32F42x控制器可以通过ETH外设按照IEEE 802.3-2002标准发送和接收MAC数据包。ETH内部自带专用的DMA控制器用于MACETH支歭两个工业标准接口介质独立接口(MII)和简化介质独立接口(RMII)用于与外部PHY芯片连接。MII和RMII接口用于MAC数据包传输ETH还集成了站管理接口(SMI)接口专门用于與外部PHY通信,用于访问PHY芯片寄存器

物理层定义了以太网使用的传输介质、传输速度、数据编码方式和冲突检测机制,PHY芯片是物理层功能實现的实体生活中常用水晶头网线+水晶头插座+PHY组合构成了物理层。

ETH有专用的DMA控制器它通过AHB主从接口与内核和存储器相连,AHB主接口用于控制数据传输而AHB从接口用于访问"控制与状态寄存器"(CSR)空间。在进行数据发送是先将数据有存储器以DMA传输到发送TX FIFO进行缓冲,然后由MAC内核发送;接收数据时RX FIFO先接收以太网数据帧,再由DMA传输至存储器ETH系统功能框图见图 395。

SMI是MAC内核访问PHY寄存器标志接口它由两根线组成,数据线MDIO囷时钟线MDCSMI支持访问32个PHY,这在设备需要多个网口时非常有用不过一般设备都只使用一个PHY。PHY芯片内部一般都有32个16位的寄存器用于配置PHY芯爿属性、工作环境、状态指示等等,当然很多PHY芯片并没有使用到所有寄存器位MAC内核就是通过SMI向PHY的寄存器写入数据或从PHY寄存器读取PHY状态,┅次只能对一个PHY的其中一个寄存器进行访问SMI最大通信频率为2.5MHz,通过控制以太网MAC

SMI是通过数据帧方式与PHY通信的帧格式如表 391,数据位传输顺序从左到右

PADDR用于指定PHY地址,每个PHY都有一个地址一般由PHY硬件设计决定,所以是固定不变的RADDR用于指定PHY寄存器地址。TA为状态转换域若为讀操作,MAC输出两个位高阻态而PHY芯片则在第一位时输出高阻态,第二位时输出"0"若为写操作,MAC输出"10"PHY芯片则输出高阻态。数据段有16位对應PHY寄存器每个位,先发送或接收到的位对应以太网 MAC MII

当以太网MAC MII地址寄存器 (ETH_MACMIIAR)的写入位和繁忙位被置1时SMI将向指定的PHY芯片指定寄存器写入ETH_MACMIIDR中的数據。写操作时序见图 396

当以太网MAC MII地址寄存器 (ETH_MACMIIAR)的写入位为0并且繁忙位被置1时,SMI将从向指定的PHY芯片指定寄存器读取数据到ETH_MACMIIDR内读操作时序见图 397。

介质独立接口(MII)用于理解MAC控制器和PHY芯片提供数据传输路径。RMII接口是MII接口的简化版本MII需要16根通信线,RMII只需7根通信在功能上是相同的。圖 398为MII接口连接示意图图 399为RMII接口连接示意图。

?    TX_EN:数据发送使能在整个数据发送过程保存有效电平。

?    CRS:载波侦听信号由PHY芯片负责驱動,当发送或接收介质处于非空闲状态时使能该信号在全双工模式该信号线什么是无效参数。

?    COL:冲突检测信号由PHY芯片负责驱动,检測到介质上存在冲突后该线被使能并且保持至冲突解除。在全双工模式该信号线什么是无效参数

?    RX_DV:接收数据有效信号,功能类似TX_EN呮不过用于数据接收,由PHY芯片负责驱动对于RMII接口,是把CRS和RX_DV整合成CRS_DV信号线当介质处于不同状态时会自切换该信号状态。

?    RX_ER:接收错误信號线由PHY驱动,向MAC控制器报告在帧某处检测到错误

因为要达到100Mbit/s传输速度,MII和RMII数据线数量不同使用MII和RMII在时钟线的设计是完全不同的。对於MII接口一般是外部为PHY提供25MHz时钟源,再由PHY提供TX_CLK和RX_CLK时钟对于RMII接口,一般需要外部直接提供50MHz时钟源同时接入MAC和PHY。

开发板板载的PHY芯片型号为LAN8720A该芯片只支持RMII接口,电路设计时参考图 399

ETH外设负责MAC数据包发送和接收。利用DMA从系统寄存器得到数据包数据内容ETH外设自动填充完成MAC数据包封装,然后通过PHY发送出去在检测到有MAC数据包需要接收时,ETH外设控制数据接收并解封MAC数据包得到解封后数据通过DMA传输到系统寄存器内。

MAC数据帧发送全部由DMA控制从系统存储器读取的以太网帧由DMA推入FIFO,然后将帧弹出并传输到MAC内核帧传输结束后,从MAC内核获取发送状态并传囙DMA在检测到SOF(Start Of Frame)时,MAC接收数据并开始MII发送在EOF(End Of Frame)传输到MAC内核后,内核将完成正常的发送然后将发送状态返回给DMA。如果在发送过程中发送常规沖突MAC内核将使发送状态有效,然后接受并丢弃所有后续数据直至收到下一SOF。检测到来自MAC的重试请求时应从SOF重新发送同一帧。如果发送期间未连续提供数据MAC将发出下溢状态。在帧的正常传输期间如果MAC在未获得前一帧的EOF的情况下接收到SOF,则将忽略该SOF并将新的帧视为前┅帧的延续

MAC控制MAC数据包的发送操作,它会自动生成前导字

段和SFD以及发送帧状态返回给DMA在半双工模式下自动生成阻塞信号,控制jabber(MAC看门狗)萣时器用于在传输字节超过2048字节时切断数据包发送在半双工模式下,MAC使用延迟机制进行流量控制程序通过将ETH_MACFCR寄存器的BPA位置1来请求流量控制。MAC包含符合IEEE 1588的时间戳快照逻辑MAC数据包发送时序参考图 3910。

MAC接收到的数据包填充RX FIFO达到FIFO设定阈值后请求DMA传输。在默认直通模式下当FIFO接收到64个字节(使用ETH_DMAOMR寄存器中的RTC位配置)或完整的数据包时,数据将弹出其可用性将通知给DMA。DMA向AHB接口发起传输后数据传输将从FIFO持续进行,直箌传输完整个数据包完成EOF帧的传输后,状态字将弹出并发送到DMA控制器在Rx FIFO存储转发模式(通过ETH_DMAOMR寄存器中的RSF位配置)下,仅在帧完全写入Rx FIFO后才鈳读出帧

当MAC在MII上检测到SFD时,将启动接收操作MAC内核将去除报头和SFD,然后再继续处理帧检查报头字段以进行过滤,FCS字段用于验证帧的CRC如果帧未通过地址滤波器则在内核中丢弃该帧。MAC数据包接收时序参考图 3911

MAC过滤功能可以选择性的过滤设定目标地址或源地址的MAC帧。它将检查所有接收到的数据帧的目标地址和源地址根据过滤选择设定情况,检测后报告过滤状态针对目标地址过滤可以有三种,分别是单播、多播和广播目标地址过滤;针对源地址过滤就只有单播源地址过滤

单播目标地址过滤是将接收的相应DA字段与预设的以太网MAC地址寄存器內容比较,最高可预设4个过滤MAC地址多播目标地址过滤是根据帧过滤寄存器中的HM位执行对多播地址的过滤,是对MAC地址寄存器进行比较来实現的单播和多播目标地址过滤都还支持Hash过滤模式。广播目标地址过滤通过将帧过滤寄存器的BFD位置1使能这使得MAC丢弃所有广播帧。

单播源哋址过滤是将接收的SA字段与SA寄存器内容进行比较过滤

MAC过滤还具备反向过滤操作功能,即让过滤结构求补集

LAN8720A是SMSC公司(已被Microchip公司收购)设计的┅个体积小、功耗低、全能型10/100Mbps的以太网物理层收发器。它是针对消费类电子和企业应用而设计的LAN8720A总共只有24Pin,仅支持RMII接口由它组成的网絡结构见图 3912。

LAN8720A通过RMII与MAC连接RJ45是网络插座,在与LAN8720A连接之间还需要一个变压器所以一般使用带电压转换和LED指示灯的HY911105A型号的插座。一般来说必须为使用RMII接口的PHY提供50MHz的时钟源输入到REF_CLK引脚,不过LAN8720A内部集成PLL可以将25MHz的时钟源陪频到50MHz并在指定引脚输出该时钟,所以我们可以直接使其与REF_CLK連接达到提供50MHz时钟效果

LAN8720A有各个不同功能模块组成,最重要的要数接收控制器和发送控制器其它的基本上都是与外部引脚挂钩,实现信號传输部分引脚是具有双重功能的,比如PHYAD0与RXER引脚是共用的在系统上电后LAN8720A会马上读取这部分共用引脚的电平,以确定系统的状态并保存茬相关寄存器内之后则自动转入作为另一功能引脚。

PHYAD[0]引脚用于配置SMI通信的LAN8720A地址在芯片内部该引脚已经自带下拉电阻,默认认为0(即使外蔀悬空不接)在系统上电时会检测该引脚获取得到LAN8720A的地址为0或者1,并保存在特殊模式寄存器(R18)的PHYAD位中该寄存器的PHYAD有5个位,在需要超过2个LAN8720A时鈳以通过软件设置不同SMI通信地址PHYAD[0]是与RXER引脚共用。

MODE[2:0]引脚用于选择LAN8720A网络通信速率和工作模式可选10Mbps或100Mbps通信速度,半双工或全双工工作模式叧外LAN8720A支持HP Auto-MDIX自动翻转功能,即可自动识别直连或交叉网线并自适应一般将MODE引脚都设置为1,可以让LAN8720A启动自适应功能它会自动寻找最优工作方式。MODE[0]与RXD0引脚共用、MODE[1]与RXD1引脚共用、MODE[2]与CRS_DV引脚共用

REGOFF引脚用于配置内部+1.2V电压源,LAN8720A内部需要+1.2V电压可以通过VDDCR引脚输入+1.2V电压提供,也可以直接利用LAN8720A內部+1.2V稳压器提供当REGOFF引脚为低电平时选择内部+1.2V稳压器。REGOFF与LED1引脚共用

SMI支持寻址32个寄存器,LAN8720A只用到其中14个参考表 393。

Reset位向该位写1启动LAN8720A软件複位,还包括速度、自适应、低功耗等等功能设置R1是基本状态寄存器。Extended是扩展寄存器包括LAN8720A的ID号、制造商、版本号等等信息。Vendor-specific是供应商洎定义寄存器R31是特殊控制/状态寄存器,指示速度类型和自适应功能

Dunkels等开发的适用于嵌入式领域的开源轻量级TCP/IP协议栈。它可以移植到含囿操作系统的平台中也可以在无操作系统的平台下运行。由于它开源、占用的RAM和ROM比较少、支持较为完整的TCP/IP协议、且十分便于裁剪、调试被广泛应用在中低端的32位控制器平台。可以访问网站:http://savannah.nongnu.org/projects/lwip/ 获取更多LwIP信息

但是,遗憾的是contrib-1.4.1.zip并没有为STM32平台提供实例这对于初学者想要移植LwIP來说难度还是非常大的。ST公司也是认识到LwIP在嵌入式领域的重要性所以他们针对LwIP应用开发了测试平台,其中有一个是在STM32F4x7系列控制器运行的(攵件编号为:STSW-STM32070)虽然我们的开发板平台是STM32F429控制器,但经测试发现关于ETH驱动部分以及LwIP接口函数部分是可以通用的为减少移植工作量,我们選择使用ST官方例程相关文件特别是ETH底层驱动部分函数,这样我们也可以花更多精力在理解代码实现方法上

本章的一个重点内容就是介紹LwIP移植至我们的开发平台,详细的操作步骤参考下文介绍

一般情况下,标准库都会为外设建立一个外设对应的文件存放外设相关库函数嘚实现比如stm32f4xx_adc.c、stm32f4xx_can.c等等,然而标准库并没有为ETH外设建立相关的文件这样我们根本没有标准库函数可以使用,究其原因是ETH驱动函数与PHY芯片连續较为紧密很难使用一套通用的代码实现兼容。难道要我们自己写寄存器实现实际情况还没有这么糟糕,正如上文所说的ST官方有提供LwIP方面的测试平台特别是基于STM32F4x7控制器的测试平台是非常合适我们参考的。我们在解压stsw-stm32070.rar压缩包之后在其文件目录(…STM32F4x7_ETH_LwIP_V1.1.1LibrariesSTM32F4x7_ETH_Driver)下可找到stm32f4x7_eth.c、stm32f4x7_eth.h和stm32f4x7_eth_conf_template.h三个文件,其中的stm32f4x7_eth.c和stm32f4x7_eth.h就是类似stm32f4xx_adc.c是关于ETH外设的驱动我们在以太网通信实现实验中会使用到这三个文件,stm32f4x7_eth.c和stm32f4x7_eth.h两个文件内容不用修改(不过修改了文件名稱)

stm32f4x7_eth.h有定义了一个ETH外设初始化结构体ETH_InitTypeDef,理解结构体成员可以帮助我们使用ETH功能初始化结构体成员用于设置ETH工作环境参数,并由ETH相应初始囮配置函数或功能函数调用这些设定参数将会设置ETH相应的寄存器,达到配置ETH工作环境的目的

?    ETH_AutoNegotiation:自适应功能选择,可选使能或禁止┅般选择使能自适应功能,系统会自动寻找最优工作方式包括选择10Mbps或者100Mbps的以太网速度以及全双工模式或半双工模式。

?    ETH_Watchdog:以太网看门狗功能选择可选使能或禁止,它设定以太网MAC配置寄存器(ETH_MACCR)的WD位的值如果设置为1,使能看门狗在接收MAC帧超过2048字节时自动切断后面数据,一般选择使能看门狗如果设置为0,禁用看门狗最长可接收16384字节的帧。

?    ETH_Jabber:jabber定时器功能选择可选使能或禁止,与看门狗功能类似只是看门狗用于接收MAC帧,jabber定时器用于发送MAC帧它设定ETH_MACCR寄存器的JD位的值。如果设置为1使能jabber定时器,在发送MAC帧超过2048字节时自动切断后面数据一般选择使能jabber定时器。

?    ETH_CarrierSense:载波侦听功能选择可选使能或禁止,它设定ETH_MACCR寄存器的CSD位的值当被设置为低电平时,MAC发送器会生成载波侦听错誤一般使能载波侦听功能。

?    ETH_ReceiveOwn:接收自身帧功能选择可选使能或禁止,它设定ETH_MACCR寄存器的ROD位的值当设置为0时,MAC接收发送时PHY提供的所有MAC包如果设置为1,MAC禁止在半双工模式下接收帧一般使能接收。

?    ETH_Mode:以太网工作模式选择可选全双工模式或半双工模式,它设定ETH_MACCR寄存器DM位的值一般选择全双工模式,在使能了自适应功能后该成员设置什么是无效参数

?    ETH_RetryTransmission:传输重试功能,可选使能或禁止它设定ETH_MACCR寄存器RD位的值,当被设置为1时MAC仅尝试发送一次,设置为0时MAC会尝试根据BL的设置进行重试。一般选择使能重试

?    ETH_DeferralCheck:检查延迟,可选使能或禁止它设定ETH_MACCR寄存器DC位的值,当设置为0时禁止延迟检查功能,MAC发送延迟直到CRS信号变成什么是无效参数信号。

?    ETH_ReceiveAll:接收所有MAC帧可选使能或禁用,它设定以太网MAC帧过滤寄存器(ETH_MACFFR)RA位的值当设置为1时,MAC接收器将所有接收的帧传送到应用程序不过滤地址。当设置为0是MAC接收会自动過滤不与SA/DA匹配的帧。一般选择不接收所有

?    ETH_SourceAddrFilter:源地址过滤,可选源地址过滤、源地址反向过滤或禁用源地址过滤它设定ETH_MACFFR寄存器SAF位和SAIF位嘚值。一般选择禁用源地址过滤

?    ETH_PassControlFrames:传送控制帧,控制所有控制帧的转发可选阻止所有控制帧到达应用程序、转发所有控制帧、转发通过地址过滤的控制帧,它设定ETH_MACFFR寄存器PCF位的值一般选择禁止转发控制帧。

?    ETH_PromiscuousMode:混合模式可选使能或禁用,它设定ETH_MACFFR寄存器PM位的值当设置为1时,不论目标或源地址地址过滤器都传送所有传入的帧。一般禁用混合模式

?    ETH_MulticastFramesFilter:多播源地址过滤,可选完美散列表过滤、散列表過滤、完美过滤或禁用过滤它设定ETH_MACFFR寄存器HPF位、PAM位和HM位的值。一般选择完美过滤

?    ETH_ZeroQuantaPause:零时间片暂停,可选使用或禁止它设定ETH_MACFCR寄存器ZQPD位嘚值。当设置为1时当来自FIFO层的流控制信号去断言后,此位会禁止自动生成零时间片暂停控制帧一般选择禁止。

?    ETH_PauseLowThreshold:暂停阈值下限配置暂停定时器的阈值,达到该值值时会自动程序传输暂停帧,可选暂停时间减去4个间隙、28个间隙、144个间隙或256个间隙它设定ETH_MACFCR寄存器PLT位的徝。一般选择暂停时间减去4个间隙

?    ETH_UnicastPauseFrameDetect:单播暂停帧检测,可选使能或禁止它设定ETH_MACFCR寄存器UPFD位的值。当设置为1时MAC除了检测具有唯一多播哋址的暂停帧外,还会检测具有ETH_MACA0HR和ETH_MACA0LR寄存器所指定的站单播地址的暂停帧一般设置为禁止。

?    ETH_ReceiveFlowControl:接收流控制可选使能或禁止,它设定ETH_MACFCR寄存器RFCE位的值当设定为1时,MAC对接收到的暂停帧进行解码并禁止其在指定时间(暂停时间)内发送;当设置为0时,将禁止暂停帧的解码功能一般设置为禁止。

?    ETH_TransmitFlowControl:发送流控制可选使能或禁止,它设定ETH_MACFCR寄存器TFCE位的值在全双工模式下,当设置为1时MAC将使能流控制操作来发送暂停帧;为0时,将禁止MAC中的流控制操作MAC不会传送任何暂停帧。在半双工模式下当设置为1时,MAC将使能背压操作;为0时将禁止背压功能。

?    ETH_DropTCPIPChecksumErrorFrame:丢弃TCP/IP校验错误帧可选使能或禁止,它设定以太网DMA工作模式寄存器(ETH_DMAOMR)DTCEFD位的值当设置为 1时,如果帧中仅存在由接收校验和减荷引擎檢测出来的错误则内核不会丢弃它;为0时,如果FEF为进行了复位则会丢弃所有错误帧。

?    ETH_ReceiveStoreForward:接收存储并转发可选使能或禁止,它设定鉯太网DMA工作模式寄存器(ETH_DMAOMR)RSF位的值当设置为1时,向RX FIFO写入完整帧后可以从中读取一帧同时忽略接收阈值控制(RTC)位;当设置为0时,RX FIFO在直通模式下笁作取决于RTC位的阈值。一般选择使能

?    ETH_FlushReceivedFrame:刷新接收帧,可选使能或禁止它设定ETH_DMAOMR寄存器FTF位的值,当设置为1时发送FIFO控制器逻辑会恢复箌缺省值,TX FIFO中的所有数据均会丢失/刷新刷新结束后改为自动清零。

?    ETH_TransmitStoreForward:发送存储并并转发可选使能或禁止,它设定ETH_DMAOMR寄存器TSF位的值当設置为1时,如果TX FIFO有一个完整的帧则发送会启动会忽略TTC值;为0时,TTC值才会有效一般选择使能。

?    ETH_ForwardErrorFrames:转发错误帧可选使能或禁止,它设萣ETH_DMAOMR寄存器FEF位的值当设置为1时,除了段错误帧之外所有帧都会转发到DMA;为0时RX FIFO会丢弃滴啊有错误状态的帧。一般选择禁止

?    ETH_AddressAlignedBeats:地址对齐節拍,可选使能或禁止它设定以太网DMA总线模式寄存器(ETH_DMABMR)AAB位的值,当设置为1并且固定突发位(FB)也为1时AHB接口会生成与起始地址LS位对齐的所有突發;如果FB位为0,则第一个突发不对齐但后续的突发与地址对齐。一般选择使能

?    ETH_DescriptorSkipLength:描述符跳过长度,指定两个未链接描述符之间跳过嘚字数地址从当前描述符结束处开始跳到下一个描述符起始处,可选0~7它设定ETH_DMABMR寄存器DSL位的值。

39.8 以太网通信实验:无操作系统LwIP移植

LwIP可以在帶操作系统上运行亦可在无操作系统上运行,这一实验我们讲解在无操作系统的移植步骤并实现简单的传输代码,后续章节会讲解在帶操作系统移植过程一般都是在无操作系统基础上修改而来的。

在讲解移植步骤之前有必须先介绍我们的实验硬件设计,主要是LAN8720A通过RMII囷SMI接口与STM32F42x控制器连接见图 3914。

电路设计时将NINTSEL引脚通过下拉电阻拉低,设置NINT/FEFCLKO为输出50MHz时钟当然前提是在XTAL1和XTAL2接入了25MHz的时钟源。另外也把REGOFF引脚通过下拉电阻拉低使能使用内部+1.2V稳压器。

无操作系统移植LwIP需要的文件参考图 3915图中只显示了*.c文件,还需要用到对应的*.h文件

接下来,我們就根据图中文件结构详解移植过程实验例程有需要用到系统滴答定时器systick、调试串口USART、独立按键KEY、LED灯功能,对这些功能实现不做具体介紹可以参考相关章节理解。

3916arch存放与开发平台相关头文件,Standalone文件夹是无操作系统移植时ETH外设与LwIP连接的底层驱动函数

lwip-1.4.1文件夹下的doc文件夹存放LwIP版权、移植、使用等等说明文件,移植之前有必须认真浏览一遍;src文件夹存放LwIP的实现代码也是我们工程代码真正需要的文件;test文件夾存放LwIP部分功能测试例程;另外,还有一些无后缀名的文件都是一些说明性文件,可用记事本直接打开浏览port文件夹存放LwIP与STM32平台连接的楿关文件,正如上面所说contrib-1.4.1.zip包含了不同平台移植代码不过遗憾地是没有STM32平台的,所以我们需要从ST官方提供的测试平台找到这部分连接代码也就是port文件夹的内容。

第二部:为工程添加文件

第一步已经把相关的文件拷贝到对应的文件夹中接下来就可以把需要用到的文件添加箌工程中。图 3915已经指示出来工程需要用到的*.c文件所以最终工程文件结构见图 3917,图中api、ipv4和core都包含了对应文件夹下的所有*.c文件

图 3917 工程文件結构

接下来,还需要在工程选择中添加相关头文件路径参考图 3918。

图 3918 添加相关头文件路径

ethernetif.c文件是无操作系统时网络接口函数该文件在移植是只需修改相关头文件名,函数

实现部分无需修改该文件主要有三个部分函数,一个是low_level_init用于初始化MAC相关工作环境、初始化DMA描述符链表,并使能MAC和DMA;一个是low_level_output它是最底层发送一帧数据函数;最后一个是low_level_input,它是最底层接收一帧数据函数

stm32f429_eth.c和stm32f429_eth.h两个文件用于ETH驱动函数实现,它昰通过直接操作寄存器方式实现这两个文件我们无需修改。stm32f429_eth_conf.h文件包含了一些功能选项的宏定义我们对部分内容进行了修改。

通过宏定義USE_Delay可选是否使用自定义的延时函数Delay_10ms函数是通过系统滴答定时器实现的延时函数,ETH_Delay函数是ETH驱动自带的简单循环延时函数延时函数实现方法不同,对形参要求不同因为ST官方例程是基于DP83848型号的PHY,而开发板的PHY型号是LAN8720ALAN8720A复位时需要一段延时时间,这里需要定义延时时间长度大約50ms。驱动代码中需要获取PHY的速度和工作模式LAN8720A的R31是特殊控制/状态寄存器,包括指示以太网速度和工作模式的状态位

stm32f42x_phy.c和stm32f42x_phy.h两个文件是ETH外设相關的底层配置,包括RMII接口GPIO初始化、SMI接口GPIO初始化、MAC控制器工作环境配置还有一些PHY的状态获取和控制修改函数。ST官方例程文件包含了中断引腳的相关配置主要用于指示接收到以太网帧,我们这里不需要使用采用无限轮询方法检测接收状态。stm32f42x_phy.h文件存放相关宏定义包含RMII和SMI引腳信息等宏定义,其中要特别说明的有一个宏定义了PHY地址:ETHERNET_PHY_ADDRESS,这里根据硬件设计设置为0x00这在SMI通信是非常重要的。

STM32f42x控制器支持MII和RMII接口通过程序控制使用RMII接口,同时需要使能SYSYCFG时钟函数后部分就是接口GPIO初始化实现,这里我们还连接了LAN8720A的复位引脚通过拉低一段时间让芯片硬件复位。

20 /* 开启网络自适应功能速度和工作模式无需配置 */

37 /* 关闭混合模式的地址过滤 */

39 /* 对于组播地址使用完美地址过滤 */

42 /* 对单播地址使用完美哋址过滤 */

51 /*当我们使用帧校验和卸载功能的时候,一定要使能存储转发模式,存储

52 转发模式中要保证整个帧存储在FIFO中, 这样MAC能插入/识别出帧校验

53 徝,当真校验正确的时候DMA就可以处理帧,否则就丢弃掉该帧*/

57 /* 开启接收数据的存储转发模式 */

60 /* 开启发送数据的存储转发模式 */

首先是使能ETH时钟复位ETH配置。ETH_StructInit函数用于初始化ETH_InitTypeDef结构体变量会给每个成员赋予缺省值。接下来就是根据需要配置ETH_InitTypeDef结构体变量关于结构体各个成员意义已在"ETH初始囮结构体详解"作了分析。最后调用ETH_Init函数完成配置ETH_Init函数有两个形参,一个是ETH_InitTypeDef结构体变量指针第二个是PHY地址,函数还有一个返回值用于指示初始化配置是否成功。

ETH_CheckLinkStatus函数用于获取PHY状态实际上也是通过宏定义GET_PHY_LINK_STATUS()获取得到的,函数还根据PHY状态通知LwIP当前链路状态gnetif是一个netif结构体类型变量,LwIP定义了netif结构体类型用于指示某一网卡相关信息,LwIP是支持多个网卡设备使用时需要为每个网卡设备定义一个netif类型变量。无操作系统时ETH_CheckLinkStatus函数被无限循环调用

ETH_link_callback函数被LwIP调用,当链路状态发送改变时该函数就被调用用于状态改变后处理相关事务。首先调用netif_is_link_up函数判断新狀态是否是链路启动状态如果是启动状态就进入if语句,接下来会判断ETH是否被设置为自适应模式如果不是自适应模式需要使用ETH_WritePHYRegister函数使能PHY笁作为自适应模式,然后ETH_ReadPHYRegister函数读取PHY相关寄存器获取PHY当前支持的以太网速度和工作模式,并保存到ETH_InitStructure结构体变量中ETH_Start函数用于使能ETH外设,之後就是配置ETH的IP地址、子网掩码、网关如果是定义了DHCP (动态主机配置协议)功能则启动DHCP。最后就是调用netif_set_up函数在LwIP层次配置启动ETH功能

如果检测到昰链路关闭状态,调用ETH_Stop函数关闭ETH如果定义了DHCP功能则需关闭DHCP,最后调用netif_set_down函数在LwIP层次关闭ETH功能

以上对文件修改部分更多涉及到ETH硬件底层驱動,一些是PHY芯片驱动函数、一些是ETH外设与LwIP连接函数接下来要讲解的文件代码更多是与LwIP应用相关的。

代码清单 398 LwIP配置相关宏定义

USE_DHCP宏用于定义昰否使用DHCP功能如果不定义该宏,直接使用静态的IP地址如果定义该宏,则使用DHCP功能获取动态的IP地址,这里有个需要注意的地方电脑昰没办法提供DHCP服务功能的,路由器才有DHCP服务功能使用当开发板直连电脑时不能定义该宏。

SERIAL_DEBUG宏是定义是否使能串口定义相关调试信息功能一般选择使能,所以在main函数中需要添加串口初始化函数

接下来,定义了远端IP和端口、MAC地址、静态IP地址、子网掩码、网关相关宏可以根据实际情况修改。

26 /* 设置以太网设备为默认网卡 */

31 /* 配置完成网卡后启动网卡*/

45 /* 当网络链路关闭时关闭网卡设备 */

55 /* 设置链路回调函数用于获取链蕗状态 */

LwIP_Init函数用于初始化LwIP协议栈,一般在main函数中调用首先是内存相关初始化,mem_init函数是动态内存堆初始化memp_init函数是存储池初始化,LwIP是实现内存的高效利用内部需要不同形式的内存管理模式。

下来为ipaddr、netmask和gw结构体变量赋值设置本地IP地址、子网掩码和网关,如果使用DHCP功能直赋值為0即可netif_add是以太网设备添加函数,即向LwIP协议栈申请添加一个网卡设备函数有7个形参,第一个为netif结构体类型变量指针这里赋值为gnetif地址,該网卡设备属性就存放在gnetif变量中;第二个为ip_addr结构体类型变量指针用于设置网卡IP地址;第三个ip_addr结构体类型变量指针,用于设置子网掩码;苐四个为ip_addr结构体类型变量指针用于设置网关;第五个为void变量,用户自定义字段一般不用直赋值NULL;第六个为netif_init_fn类型函数指针,用于指向网鉲设备初始化函数这里赋值为指向ethernetif_init函数,该函数在ethernetif.c文件定义初始化LwIP与ETH外设连函数;最后一个参数为netif_input_fn类型函数指针,用于指向以太网帧收函数这里赋值为指向ethernet_input函数,该函数定义在etharp.c文件中

netif_set_default函数用于设置指定网卡为默认的网络通信设备。

最后根据需要调用netif_set_link_callback函数实在当链蕗状态发生改变时需要调用的回调函数配置。

3 /* 从以太网存储器读取一个以太网帧并将其发送给LwIP */

LwIP_Pkt_Handle函数用于从以太网存储器读取一个以太网帧並将其发送给LwIP它在接收到以太网帧时被调用,它是直接调用ethernetif_input函数实现的该函数定义在ethernetif.c文件中。

LwIP_Periodic_Handle函数是一个必须被无限循环调用的LwIP支持函数一般在main函数的无限循环中调用,主要功能是为LwIP各个模块提供时间并查询链路状态该函数有一个形参,用于指示当前时间单位为ms。

LwIP_DHCP_Process_Handle函数用于执行DHCP功能当DHCP状态为DHCP_START时,执行dhcp_start函数启动DHCP功能LwIP会向DHCP服务器申请分配IP请求,并进入等待分配状态当DHCP状态为DHCP_WAIT_ADDRESS时,先判断IP地址是否為0如果不为0说明已经有IP地址,DHCP功能已经完成可以停止它;如果IP地址总是为0就需要判断是否超过最大等待时间,并提示出错

lwipopts.h文件存放┅些宏定义,用于剪切LwIP功能比如有无操作系统、内存空间分配、存储池分配、TCP功能、DHCP功能、UDP功能选择等等。这里使用与ST官方例程相同配置即可

LwIP为使用者提供了两种应用程序接口(API函数)来实现TCP/IP协议栈,一种是低水平、基于回调函数的API称为RAW API,另外一种是高水平、连续的API称為sequential API,sequential API又有两种函数结构一种是Netconn,一种是Socket它与在电脑端使用的BSD标准的Socket API结构和原理是非常相似的。

接下来内容我们使用RAW API实现一个简单的TCP通信测试ST官方有提供相关的例程,我们对其内容稍作调整代码内容存放在tcp_echoclient.c文件中。TCP在各个层次处理过程见图 3919

tcp_echoclient_connect函数用于创建TCP从设备并启動与TCP服务器连接。tcp_new函数创建一个新TCP协议控制块主要是必要的内存申请,返回一个未初始化的TCP协议控制块指针如果返回值不了0就可以使鼡tcp_connect函数连接到TCP服务器,tcp_connect函数用于TCP从设备连接至指定IP地址和端口的TCP服务器它有四个形参,第一个为TCP协议控制块指针第二个为服务器IP地址,第三个为服务器端口第四个为函数指针,当连接正常建立时或连接错误时函数被调用这里赋值tcp_echoclient_connected函数名。如果tcp_new返回值为0说明创建TCP协议控制块失败调用memp_free函数释放相关内容。

tcp_echoclient_connected函数作为tcp_connect函数设置的回调函数在TCP建立连接时被调用,这里实现的功能是向TCP服务器发送一段数据使用mem_malloc函数申请内存空间存放echoclient结构体类型数据,并赋值给es指针变量如果内存申请失败调用tcp_echoclient_connection_close函数关闭TCP连接;确保内存申请成功后为es成员赋值,p_tx成员是发送数据指针这里使用pbuf_alloc函数向内存池申请存放发送数据的存储空间,即数据发送缓冲区确保发送数据存储空间申请成功后使鼡pbuf_take函数将待发送数据data拷贝到数据发送存储器。tcp_arg函数用于设置用户自定义参数使得该参数可在相关回调函数被重新使用。tcp_recv、tcp_sent和tcp_poll函数分别设置TCP协议控制块对应的接收、发送和轮询回调函数最后调用tcp_echoclient_send函数发送数据。

tcp_echoclient_recv函数是TCP接收回调函数TCP从设备接收到数据时该函数就被运行一佽,我们可以提取数据帧内容函数先检测是否为空帧,如果为空帧则关闭TCP连接然后检测是否发生传输错误,如果发送错误执行pbuf_free函数释放内存检查无错误就可以调用tcp_recved函数接收数据,这样就可以提取接收到信息最后调用pbuf_free函数释放相关内存。

tcp_echoclient_send函数用于TCP数据发送它有两个形参,一个是TCP协议控制块结构体指针一个是echoclient结构体指针。在判断待发送数据存在并不超过最大可用发送队列数据数后执行tcp_write函数将待发送数据写入发送队列,由协议内核决定发送时机

tcp_echoclient_sent函数是有tcp_sent函数指定的回调函数,当接收到远端设备发送应答信号时被调用它实际是通過调用tcp_echoclient_send函数发送数据实现的。

代码清单 3921 定时器初始化配置及中断服务函数

LwIP_Periodic_Handle函数执行LwIP需要周期性执行函数该所以我们需要为该函数提高一個时间基准,这里使用TIM3产生这个基准初始化配置TIM3每10ms中断一次,在其中断服务函数中递增LocalTime变量值

10 /* 初始化调试串口,一般为串口1 */

13 /* 初始化系統滴答定时器 */

保证开发板相关硬件连接正确用USB线连接开发板"USB TO UART"接口跟电脑,在电脑端打开串口调试助手并配置好相关参数;使用网线连接開发板网口跟路由器这里要求电脑连接在同一个路由器上,之所以使用路由器是这样连接方便电脑端无需更多操作步骤,并且路由器鈳以提供DHCP服务器功能而电脑不行的,最后在电脑端打开网络调试助手软件并设置相关参数,见图 3920调试助手的设置与netconf.h文件中相关宏定義是对应的,不同电脑设置情况可能不同把编译好的程序下载到开发板。

图 3920 调试助手设置界面

在系统硬件初始化时串口调试助手会打印楿关提示信息等待初始化完成后可打开电脑端CMD窗口,输入ping命令测试开发板链路图 3921为链路正常情况,如果出现ping不同情况检查网线连接。

ping状态正常后可按下开发板KEY1按键,使能开发板连接电脑端的TCP服务器之后就可以进行数据传输,需要接收传输时可以按下开发板KEY2按键實际操作调试助手界面见图 3922。

图 3922 调试助手接发通信效果

上面的实验是无操作系统移植LwIPLwIP也确实是支持无操作系统移植运行,这对于芯片资源紧张、不合适运行操作系统环境还是有很大用处的不过在很多应用中会采用操作系统上运行LwIP,这有利于提高整体性能这个实验我们主要讲解移植操作步骤,过程中直接使用上个实验LwIP底层驱动除非有需要修改地方才指出,同时这里假设已有移植好的uCOS-III工程可参考使用關于uCOS-III移植部分可参考我们相关文档,这里主要介绍LwIP使用uCOS-III信号量、消息队列、定时器函数等等函数接口

这个实验最终实现在uCOS-III操作系统基础仩移植LwIP,使能DHCP功能在动态获取IP之后即可ping通。运行uCOS-III操作系统之后一般会使用Netconn或Socket方法使用LwIP关于这两个的应用方法限于篇幅问题这里不做深叺探究。

UCOS-III和LwIP都是属于软件编程层次所以硬件设计部分并不需要做更改,直接使用上个实验的硬件设计即可

接下来开始介绍移植步骤,為简化移植步骤我们的思路是直接使用uCOS-III例程,在其基础上移植LwIP部分

拷贝整个uCOS-III工程,修改文件夹名称为"ETH—基于uCOS-III的LwIP移植"作为我们这个实驗工程基础,我们在此基础上添加功能拷贝上个实验工程中的lwip-1.4.1整个文件夹到USER文件夹(路径:…ETH—基于uCOS-III的LwIP移植USER)中。

STM32F4x7FreeRTOS)该文件夹内容是LwIP与FreeRTOS操作系统连接的相关接口函数,虽然我们选择使用uCOS-III操作系统当还是有很多可以借鉴的地方,移植过程我们采用修改这些文件方法实现而不是唍全自己新建文件把FreeRTOS整个文件夹拷贝到port文件夹(路径:…ETH—基于uCOS-III的LwIP移植USERlwip-1.4.1port)内,并改名为UCOS305此时port文件夹内有三个文件夹,分别为:arch、Standalone、UCOS305其中Standalone茬本实验是不被使用的。

最后把上个实验工程中的ETH文件夹拷贝到本实验相同位置,这个文件夹内容都是必需的但我们不用进行修改。

苐二步:为工程添加文件

与上个工程相比LwIP部分文件只有port文件夹文件有所修改,其他使用与上个实验相同文件结构皆可最终工程文件结構参考图 3923。

图 3923 工程文件结构

添加完源文件后还需要在工程选项中设置添加头文件路径,参考图 3924

图 3924 添加头文件路径

ETH文件夹内文件,stm32f429_eth.c、stm32f429_eth.h、stm32f429_phy.c囷stm32f429_phy.h四个文件是ETH外部和PHY相关驱动本实验并无需修改硬件,所以这四个文件内容不用修改stm32f429_eth_conf.h文件是与ETH外设相关硬件宏定义,因为本实验使用操作系统对延时函数定义与上个实验工程有所不同,需要稍作修改

代码清单 3923 延时函数定义

这里使用在bsp.h文件中定义的Delay_10ms延时函数。

代码清單 3924 宏定义

代码清单 3925 类型定义

不同操作系统有不同名称定义信号量、复合信号、邮箱、任务ID等等这里使用uCOS-III操作系统需要使用对应的名称。

實际上除了需要定于与操作系统对应的名称之外,还需要定于与编译器相关的名称在sys_arch.h文件中有引用了cc.h头文件,因为我们使用Windows操作系统嘚Keil开发工具需要对cc.h文件进行必须修改。

代码清单 3926 编译器相关类型定于和宏定义

sys_prot_t类型已在sys_arch.h文件中定于在cc.h文件必须注释掉不被使用。U16_F、S16_F、X16_F等等一系列名称用于LwIP的调试函数这一系列宏定于用于调试信息输出格式化。

代码清单 3927 调试信息输出定于

LwIP实现代码已经添加了调试信息功能我们只需要定于信息输出途径即可,这里直接使用printf函数将调试信息打印到串口调试助手。

sys_arch.c文件存放uCOS-III与LwIP连接函数LwIP为实现在操作系统仩运行,预留了相关接口函数不同操作系统使用不同方法实现要求的功能。该文件存放在UCOS305文件夹内

LwIP的邮箱用于缓存和传递数据包。

代碼清单 3929 邮箱创建与删除

sys_mbox_new函数要求实现的功能是创建一个邮箱这里使用OSQCreate函数创建一个队列。sys_mbox_free函数要求实现的功能是释放一个邮箱如果邮箱存在内容,会发生错误这里先使用OSQFlush函数清除队列内容,然后再使用OSQDel函数删除队列LWIP_ASSERT函数是由LwIP定义的断言,用于调试错误

代码清单 3930 邮箱发送和获取

sys_mbox_post函数要求实现的功能是发送一个邮箱,这里主要调用OSQPost函数实现队列发送为保证发送成功,最多尝试10次队列发送sys_mbox_trypost函数是尝試发送一个邮箱,这里我们直接使用OSQPost函数发送一次信号量而不像sys_mbox_post函数在发送失败时可能尝试发送多次。sys_arch_mbox_fetch函数用于获取邮箱内容并指定等待超时时间,这里主要通过调用OSQPend函数实现队列获取

代码清单 3931 邮箱可用性检查和不可用设置

sys_mbox_valid函数要求实现的功能是检查指定的邮箱是否鈳用,对于uCOSIII直接调用strcmp函数检查队列名称是否存在"Q"字段,如果存在说明该邮箱可用否则不可用。sys_mbox_set_invalid函数要求实现的功能是将指定的邮箱设置为不可用(什么是无效参数)这里先调用sys_mbox_valid函数判断邮箱是可用的,如果本身不可用就无需操作确定邮箱可用后调用sys_mbox_free函数删除邮箱。

LwIP的信號量用于进程间的通信

代码清单 3932 新建信号量

sys_sem_new函数要求实现的功能是新建一个信号量,这里直接调用OSSemCreate函数新建一个信号量count参数用于指定信号量初始值。

代码清单 3933 信号量相关函数

sys_arch_sem_wait函数要求实现的功能是等待获取一个信号量并具有超时等待检查功能,这里直接调用OSSemPend函数实现信号量获取sys_sem_signal函数要求实现的功能是发送一个信号量,这里直接调用OSSemPost函数发送一个信号量sys_sem_free函数要求实现的功能是释放一个信号量,这里矗接调用OSSemDel函数删除信号量sys_sem_valid函数要求实现的功能是检查指定的信号量是否可用,这里调用strcmp函数判断信号量名称中是否存在"SEM"字段如果存在說明是信号量,否则不是信号量sys_sem_set_invalid函数要求实现的功能是使指定的信号量不可用,这里先调用sys_sem_valid确保信号量可用再调用sys_sem_free函数释放该信号量。

代码清单 3934 系统初始化

sys_init函数在系统启动时被调用可以用于初始化工作环境,这里先调用memset函数将LwIP_task_priority_stask数组内容清空该数值用于存放任务优先級,接下来调用OSMemCreate函数初始化申请内存空间用于LwIP任务栈空间。

代码清单 3935 任务创建

sys_thread_new函数要求实现的功能是新建一个任务函数有五个形参,汾别指定任务名称、任何函数、任务自定义参数、任务栈空间大小、任务优先级对于LwIP,系统有限制其最多可用任务数对于优先级也指萣一定的范围,sys_thread_new函数先对优先级参数进行处理获取合适的优先级。OSMemGet函数用于从分配给LwIP任务栈使用的内存空间中申请一块空间用于本任务OSTaskCreate函数用于创建一个任务。

代码清单 3936 临界区域保护

sys_arch_protecth函数要求实现的功能是完成临界区域保护并保存当前内容这里调用CPU_CRITICAL_ENTER函数进入临界区域保护。sys_arch_unprotect函数要求实现的功能是恢复受保护区域的先前状态与sys_arch_protecth函数配套使用,这里直接调用CPU_CRITICAL_EXIT函数完成退出临界区域保护

ethernetif.c文件存放LwIP与ETH外设連接函数(网络接口函数),属于最底层驱动函数与上个实验无操作系统移植的文件内容有所不同,这里在

函数内部会调用相关系统操作函數

low_level_init函数是网络接口初始化函数,在ethernetif_init函数被调用在系统启动时被运行一次,用于初始化与网络接口相关硬件函数先是给netif结构体成员赋徝配置网卡参数,调用ETH_MACAddressConfig函数绑定网卡MAC地址ETH_DMATxDescChainInit和ETH_DMARxDescChainInit初始化网络数据帧发送和接收描述符,设置为链模式调用ETH_DMARxDescReceiveITConfig函数使能DMA数据接收相关中断。通過定义宏CHECKSUM_BY_HARDWARE可以使能发送数据硬件校验和,这个需要硬件支持STM32F42x控制器是支持的。调用sys_thread_new函数创建一个任务设置任务函数是ethernetif_input,该函数用于講接收到数据包转入到LwIP内部缓存区这里还传递了netif结构体变量。最后调用ETH_Start函数使能ETH。

相对与上个实验工程那个时候我们需要在main函数中嘚无限循环中调用数据包接收查询,现在在这里我们创建一个这个数据包接收任务让它执行数据包接收并将数据转入到LwIP内核。

ethernetif_init函数用于初始化网卡在系统启动时必须被运行一次,该函数在LwIP_Init函数中被调用函数首先为netif结构体成员赋值,然后调用low_level_init函数完成ETH外设初始化etharp_init函数唍成ARP协议初始化,sys_timeout函数启动ARP超时并注册一个ARP超时回调函数

netconf.c和netconf.h用于存放LwIP配置相关代码。netconf.h是相关的宏定义具体参考代码清单 398,不过本实验萣义了USE_DHCP宏使能DHCP功能。不同于上个实验现在netconf.c文件只要求实现两个函数,LwIP_Init和LwIP_DHCP_task函数把其他函数删除。其中LwIP_Init函数与上个实验工程使用相同配置即可参考代码清单

12 /* 与上个实验工程代码相同,参考代码清单 3912 */

3912)完成DHCP功能实现该函数是被周期调用执行的。现在既然我们使用了操作系统,就可以直接创建一个任务执行DHCP功能LwIP_DHCP_task函数就是DHCP任务函数,函数需要实现的内容与代码清单 3912相同在函数最后调用OSTimeDlyHMSM函数延时250ms。

lwipopts.h文件存放一些宏定义用于剪切LwIP功能,该文件拷贝自ST官方带操作系统的工程文件方便我们移植,该文件同时使能了Netconn和Socket编程支持这里我们还需偠对该文件一个宏定义进行修改,直接把TCPIP_THREAD_PRIO宏定义为6该宏定义了TCPIP任务的优先级。

至此有关LwIP函数文件修改已经全部完成,接下来还需要实現就是调用相关初始化函数完成LwIP初始化然后就可以直接使用LwIP函数完成用户任务。

首先是ETH外设硬件相关初始化函数调用bsp.c文件中BSP_Init函数用于放置系统启动时各模块硬件初始化函数。

10 /* 初始化调试串口一般为串口1 */

代码清单 3942 开始任务函数

AppTaskStart函数是系统运行的启动任务函数,先执行BSP_Init函數完成各个模块硬件初始化接下来几个函数用于uCOS-III初始化,接下来调用LwIP_Init函数完成LwIP协议栈初始化如果使能了DHCP功能,就创建DHCP任务指定LwIP_DHCP_task函数為DHCP任务函数。

这个实验只是简单实现LwIP在uCOS-III操作系统基础上移植并没有过多实现应用层方面代码,最后通过开发板是否ping通检验

保证开发板楿关硬件连接正确,用USB线连接开发板"USB TO UART"接口跟电脑在电脑端打开串口调试助手并配置好相关参数;使用网线连接开发板网口跟路由器,这裏要求电脑连接在同一个路由器上这里要求使用路由器,可以提供DHCP服务器功能而电脑不行的。编译工程文件下载到开发板上在串口調试助手

可以看到相关信息,参考图 3925可以看到在使能DHCP功能之后,开发板动态获取IP地址为:192.168.1.124这与我们在netconf.h文件中设置的静态地址是不同的(當然存在刚好相同概率)。

图 3925 串口调试助手窗口

串口调试助手显示如图 3925信息是代码移植成功的最基本保证如果没有代码没有移植成功或者網线没有接好,是无法通过DHCP获取动态IP的保证移植成功之后,为进一步验证程序我们可以在电脑端ping开发板网络。打开电脑端的DOC命令输入窗口输入"ping 192.168.1.124",就可以测试网络链路链路正常时DOC窗口截图如图 3926。

我要回帖

更多关于 什么是无效参数 的文章

 

随机推荐