基于DM 9000A的嵌入式以太网接口设计与实现
2011-03-15温阳东
施 勇, 温阳东
(合肥工业大学电气与自动化工程学院,安徽合肥 230009)
目前,网络技术在电子产品中的应用越来越广,更多的嵌入式设备需要提供网络接口,以方便与外部或上层网路设备的相互通信[1]。以太网是现在最为流行的局域网标准,在嵌入式系统中的应用已经越来越广泛。以太网接口不仅通信速度快,传输可靠,使用和配置方便,而且不受地域限制。以太网控制芯片是以太网接口的核心器件,其性能是影响网络性能的关键因素之一,如何正确使用网络控制器是设计以太网接口的关键。本文介绍了一种以高性能的以太网控制芯片DM 9000A和32位ARM处理器LPC2468为核心的嵌入式以太网接口的实现方法。
1 DM 9000A芯片介绍
DM 9000A[2]芯片是台湾DAVICOM公司推出的一款高度集成、功能强大、引脚少、性价比高的单片快速以太网控制芯片,非常适用于嵌入式系统设计。
DM 9000A主要特性是:集成10/100M物理层接口;内部带有16 K字节SRAM用作接收发送的FIFO缓存;支持8/16-bit 2种主机工作模式;支持802.3以太网传输协议;体积小,只有48个引脚;功耗非常低,单电源3.3 V工作,内置3.3 V变2.5 V电源电路,I/O端口支持3.3~5.0 V的容差。
DM 9000A实现以太网媒体介质访问层(MAC)和物理层(PHY)的功能,包括MAC数据帧的组装/拆分与收发、地址识别、CRC编码/校验、M LT-3编码器、接收噪声抑制、输出脉冲形成、超时重传、链路完整性测试、信号极性检测与纠正等。
2 硬件接口设计
LPC2468[3]是NXP公司2008年推出的含有以太网控制器的32位ARM 7TDM I-S处理器,运行频率高达72 MHz,98 kB片内SRAM,其中64 kB SRAM可供高性能CPU通过ARM局部总线访问,16 kB SRAM用于以太网接口,也可作为通用SRAM来使用。该芯片的以太网模块包含一个功能齐全的10 M b/s或100 M b/s以太网MAC(媒体访问控制器),可以使用M II(媒体独立接口)或RM II的片外以太网PHY通过片内M IIM(媒体独立接口管理)串行总线进行连接,实现以太网功能。为实现在嵌入式系统中增加以太网口,本设计硬件部分采用嵌入式处理器+ DM 9000A结构[4],如图1所示。
图1 LPC2468与DM 9000A硬件连接
DM 9000A有8位和16位2种模式,本系统采用16位模式,DM 9000A的EECS引脚(pin21)悬空,默认为16模式,数据线SD0~SD15直接与LPC2468数据线的低16位D0~D15连接,并且该模式可以通过ISR寄存器的Bit[7]检测。
DM 9000A的 IO读信号线 IOR、写信号线IOW分别与LPC2468的读信号线ARM-OE、写信号线ARM-WE相连;片选信号CS与处理器的片选信号ARM-CS0相连,因此网络控制器的端口地址IOaddress为0x83000000。读写信号与片选信号都是保持默认设置的低电平有效。隔离变压器的主要作用是将嵌入式系统与外部线路相隔离,防止干扰和烧坏元器件,实现带电的插拔功能。
在DM 9000A中只有INDEX端口与DATA端口2个寄存器可以被CPU直接访问,其它所有内部控制和状态寄存器都是通过这2个端口寄存器间接访问的。网络控制器CMD引脚决定了处理器访问的是哪个端口寄存器:当CMD=0时,主机访问的是INDEX端口寄存器;当CMD=1时,访问的是DATA端口寄存器。设计中将CMD引脚与处理器的地址线 ARM-A2相连,则DM 9000A的2个外部接口端口地址分别为:
INDEX端口地址=IOaddress+0x00,
DATA端口地址=IOaddress+0x04。
实际中INDEX端口寄存器保存的是访问DA TA端口寄存器的内部寄存器的地址,因此对DM 9000A控制或状态寄存器访问的命令顺序是:①写要访问寄存器的地址到INDEX端口;②通过DATA端口来读/写数据。
3 网络接口的软件设计
以太网接口电路的工作原理是:在系统上电时,处理器通过总线对DM 9000A完成初始化后,DM 900A进入数据收发等待状态;当处理器要向以太网发送数据帧时,先通过上层协议函数对数据进行封装,然后通过总线逐字节发送到DM 9000A的发送缓冲区中,将数据长度等信息填充到DM 9000A相应的寄存器中,使能发送命令后,DM 9000A自动将数据进行MAC组帧并发送出去;当接收到以太网数据帧时,处理器首先检测帧的合法性,保存正确的数据帧,然后将正确的数据帧发送到上层协议进行处理。
网络接口的软件设计主要有底层网卡驱动程序和上层通信协议2个部分[5]。网卡的驱动程序功能包括网卡芯片的初始化、以太网数据帧发送和接收。
3.1 网络接口模块的驱动程序设计
本设计的开发环境是ARM公司推出的ARM核微控制器集成开发工具ARM Developer Suite 1.2。在此开发环境下编写DM 9000A.h头文件和DM 9000A.c源文件作为网络接口模块的驱动程序。在DM 9000A.h头文件中利用宏定义了各个端口的地址、片内寄存器的片内相对地址以及片内寄存器各个位置上的信息,在DM 9000A.c源文件中直接调用宏定义即可。DM 9000A.c源文件主要函数有phy-read()、phy-w rite()、set-PH Y-mode()、InitNic()、DM 9000A-Init()、DM 9000A-Exception()、Send-Packet()、Rec-Packet()。
3.1.1 驱动初始化
为了启动网络控制器DM 9000A,使之处于数据接收发送就绪状态,必须对其进行初始化。首先是调用InitNic(void)函数,读取DM 9000A生产厂家序列号及产品序列号,然后调用初始化函数DM 9000A-Init(void)进行初始化[6]。主要是设置一些关键的寄存器,具体步骤如下:
(1)设置通用寄存器GPR(REG.1FH)的Bit[0](PHYPD位)为0,启动PHY。
(2)设置网络控制寄存器NCR(REG.00H)的Bit[0](RST位)为1,10μs后软件复位。
(3)设置NCR的Bit[2∶1](LBK位)为00,设置网络工作模式为回环模式。
(4)设置中断屏蔽寄存器IMR(REG.FFH)的Bit[7]为1,使能指针自动跳回,当SRAM读、写指针超过SRAM的大小时,指针自动跳回起始位置。
(5)写6个字节的以太网节点地址到物理地址寄存器PAR(REG.10H~15H)中。
(6)读、写1到网络状态寄存器NSR(REG. 01H)清除TX状态标志,读、写1到中断状态寄存器ISR(REG.FEH)来清除中断状态标志。
(7)设置IMR寄存器的Bit[0]/Bit[1]为使能接收/发送中断。
(8)设置接收控制寄存器RCR(REG.05H)的Bit[0](RXEN位)为1,使能接收功能。
完成上述初始化步骤后,网络控制器就可以正常启动,收发数据包。
3.1.2 数据包的发送
DM 9000A内部有16 kB的SRAM用来作为收发数据的缓冲区,其中地址从0x0000H到0x0BFFH的前3 kB空间用来作为发送数据缓冲区,在该数据缓冲区中可以同时保存2个完整的以太网帧。可将发送缓冲区看作2个独立缓冲区——Index1和 Index2;将该帧数据的长度写入长度寄存器TXPLH和TXPLL中;然后将发送控制寄存器TCR的bit[1]置位,启动发送该帧数据,DM 9000A自动对发送缓存区中的数据进行以太网组帧后,开始发送Index1中的数据。在发送Index1中数据同时,将下一帧数据写入Index2中,当Index1中的数据发送完成后,将Index2中数据长度写入长度寄存器,启动网络控制器发送Index2中的数据,同时将要发送的下一帧数据写入Index1。
发送函数Send-Packet()用于发送以太网帧。输入参数是结构-pkst指针,程序如下所示:
*STPTR为一个结构本身类型的指针,用于指向前一个结构;length为以太网帧的长度; *DAPTR为指向要发送的以太网帧头的起始地址。发送函数Send-Packet()的输入参数值是要发送的数据链表。
根据输入参数,获得整个需要发送的数据,然后发送,如果发送失败(因为冲突等原因)则重发6次直到成功。要发送的数据链表结构如图2所示。
图2 要发送的数据链表结构图
发送处理函数首先根据输入参数计算出需要发送的帧长度;软件把要发送的帧存入发送缓存块中;然后判断需要发送的字节数是否小于60,如果小于就设为60;最后设置发送寄存器,设置了发送寄存器后该帧自动被发送出去。发送完成后检查状态位是否发送成功,不成功就重新发送。其中设置发送寄存器函数比较复杂,首先检查发送缓冲区块是否为空;如果不为空,表明还有数据未发送,直接退出;如果为空,就将对应描述符数组的PACKET指针指向发送缓冲区块的起始位置;最后MWCMD寄存器加“2”,检测NSR寄存器完成标志位。发送数据包函数处理流程图如图3所示。
3.1.3 数据包的接收
接收到的数据先保存在DM 9000A内部SRAM中地址从0x0C00~0x3FFF的13 K空间中,它是一个环形结构。当使能数据接收功能后,DM 9000A就会自动接收数据,一旦它接收完一帧数据后就会产生一个接收中断。每个数据包的MAC头有4个字节信息存放在 RX FIFO SRAM中,用寄存器MRCMDX(REG.F0H)和寄存器M RCMD(REG.F2H)获取数据包的信息。接收到的数据包格式如图4所示。
图3 发送数据包函数流程
图4 数据包格式
图4前4个字节为MAC头,它包含了一个数据包的基本信息。第1个字节用于检测是否接收到数据包,01H表示接收到数据包,00H表示未接收到数据包。第2个字节保存接收包的状态信息,状态信息的高字节与RSR寄存器相同,通过这个状态信息来确认接收包的正确与否。第3、4字节是接收包的长度,其它字节是接收包的数据。
寄存器MRCMDX被定义为地址不增加的存储数据读命令寄存器,只用于从RX FIFO SRAM中读接收包准备标志“01”或最后字节的Bit[0]=1,而Bit[7:5]和Bit[4:2]分别表示IP/ TCP/UDP校验的状态和类型。接收数据包的流程如图5所示。
3.2 上层通信软件设计
为了实现嵌入式系统的网络互连,在上述的驱动程序之上,系统还必须要实现TCP/IP网络协议栈[7]。TCP/IP协议分为4层,即网络接口层、网络层、传输层和应用层,底层一般包含上层。数据包的发送是由上层协议函数调用下层协议函数来进行的。
(1)以太网层的数据收发。以太网的数据接收函数Rec-Ethernet-Packed()由驱动的Rec-Packet()调用,它的输入参数是以太网帧数据包的其实地址和网络接口号。在 Rec-E thernet-Packed()中调用了结构eip,该结构在IP.H文件中定义了IP报的报头。
图5 接收数据包函数流程
首先Rec-Ethernet-Packed()函数通过传递函数参数获知该帧的类型是IP报还是ARP报,然后分别调用IP处理函数和ARP接收处理函数。另外,在调用 IP处理函数之前还要进行ARP表的更新工作。其中,ARP表包含3个单元:生存时间(TTL)、IP地址、IP地址对应的MAC地址。ARP表项的添加和维护由ARP处理程序和以太网层的接收函数来完成。以太网接收函数流程图如图6所示。
图6 以太网接收函数流程
数据包的接收与数据包的发送是一个相反的过程。上层的TCP处理函数或SOCKET接口函数都是通过调用Send-Ip-Frame()函数来发送IP报的,而Send-Ip-Frame()函数调用Send-Ip-To-LLC()函数来处理IP地址对应MAC地址,Send-Ip-To-LLC()函数再调用Send-ethernet-Frame()函数,把对应的MAC地址写入发送区,最后调用驱动程序发送函数Send-Packet()。
(2)IP层。IP协议处理主要针对IP协议层的处理,包括对接收到的IP报分类、根据上层的信息封装和发送IP报等[8]。
IP报发送函数Send-Ip-Frame()主要由上层协议的处理函数调用,负责IP层的数据封装以及把数据传递给以太网层的发送函数。IP层的数据接收函数是IP-PROCESS(),它由以太网层的接受函数Rec-E thernet-Packed()调用,其输入参数是IP帧数据包的起始地址和网络接口号。IP-PROCESS()函数在执行过程中,首先通过传递参数获得该数据报的报头长度和总长度(IP报头+有限负载),然后向RECQ结构数组填写相关的信息,最后通过IP报中的协议字段来判断有限负载中上层协议的类型进行处理。
(3)TCP层。传输控制协议(TCP)是一种功能完备的面向连接的传输协议,具有流控制、传输确认和重传机制[9]。在数据传送之前必须先建立TCP连接,待所有数据传送完毕后,再终止连接。TCP协议是一个比较复杂的协议,它与SOCKET接口关系非常密切。TCP完成接收处理而SOCKET负责发送处理。
TCP协议的每个连接都由4个标志(服务器IP地址、服务器TCP端口、客户机IP地址、客户机TCP端口)作为它唯一标识。在进行数据传输前,服务器与客户机之间必须使用TCP连接的建立过程,建立连接成功后,再进行数据传输。终止连接也要使用 TCP连接中断过程关闭连接。TCP共有11种连接状态,正常连接和断开的状态变化如图7所示。
图7 TCP连接状态变化过程
TCP接收处理函数 Tcp-Process()的任务主要是把接收到的TCP报文连接分类,然后根据该连接所处的状态调用状态处理函数进行处理。首先判断该TCP报是否过长,然后把TCP报(TCP报头+有效负载)从接收缓存区(RECBUFF)复制到TCP接收缓冲区(Tcp-Packed)。接着检查结构体数组 TcpStatus中的 IP和PORT单元,查看是否有对应的连接已经建立从而得到 TcpStatus的序号。如果有,则根据该TcpStatus得State发送到对应状态处理函数;否则,检查TcpStatus的M yport单元,查看是否有监听对应的端口。若有,则发送到Tcp-Listen()函数处理;否则,证明该端口没有被监听,或监听的连接数已经满了,就发送RST-ACK包给对方。
4 结束语
本文介绍的以ARM处理器LPC2468为核心,采用DM 9000A作为网络接口芯片的嵌入式以太网接口方案,结构简单、运行稳定、体积小、功耗低,能够十分方便地实现嵌入式系统的网络互连。本设计成功地运用于数据网关、微机保护装置、无线基站等项目中,具有良好的效果。
[1] 于 博,张崇巍.基于μC/OS-Ⅱ的多任务工业以太网测控节点设计[J].合肥工业大学学报:自然科学版,2009,32 (12):1812-1815.
[2] 刘伟明,杜 林.基于DM 9000A和LPC2214的嵌入式以太网接口设计[J].电子测量技术,2008,(6):86-22.
[3] 周立功.深入浅出ARM 7:基于LPC 2400[R].广州:广州致远电子有限公司,2008:268-324.
[4] 赵艳祥,师五喜,郭文成,等.基于ARM的以太网控制系统的设计与实现[J].科技广场,2009,(5):205-206.
[5] 韩 超,王可人.基于DM 9000的嵌入式系统的网络接口设计与实现[J].工业控制计算机,2007,(4):17-18.
[6] 贾东耀,彭树林.嵌入式系统网络接口与驱动设计[J].微型电脑应用,2008,(4):20-22.
[7] 扬小辉,肖丽娜.基于ARM和以太网的远程智能控制仪表的设计[J].工业控制网络,2009,(5):22-24.
[8] Scaglia S.The embedded Internet TCP/IP basics:im plementation and application[M].北京:北京航空航天大学出版社,2008:67-98.
[9] 周立功.ARM嵌入式系统软件开发实例:二[M].北京:北京航空航天大学出版社,2004:449-458.