摘要:本文介绍了以DM9000AE作为网络控制器的嵌入式系统以太网通信功能的实现方法。系统设计采用DE2作为开发平台。该系统基于Nios II软核处理器,以太网控制器使用DM9000AE;运行μC/OS-II操作系统,加载网络协议LwIP。本文研究DM9000AE的初始化、数据包收发的软件编程算法,重点分析LwIP的网络接口驱动层设计。开发了DM9000AE在LwIP下的驱动程序,完成LwIP在DM9000AE芯片上的移植。最后,通过开发通信软件来测试系统的通信功能。
引言:
使用IP软核进行SOPC设计的方法正因为其低成本,可剪裁,可重构等特性受到越来越广泛的应用。Altera公司的SOPC Builder正是一款使用IP软核进行SOPC设计的优秀工具。DE2是Altera为了推广其大学计划,面向广大学生、教师推出的用于学习SOPC设计的开发板。本系统设计使用该开发板作为开发平台。而随着Internet的发展,网络功能正被越来越多的集成到嵌入式系统中。其中DM9000AE就是一款优秀的嵌入式系统网络控制芯片。LwIP网络协议栈因为其独有的特性而被广泛应用到嵌入式系统中以实现网络功能,但是DE2并没有提供DM9000AE在LwIP下的驱动程序。本文将介绍DM9000AE在LwIP下的驱动程序开发。
1 硬件设计
DE2有着丰富的器件资源和外设接口。其中包括一块Cyclone II 2C35 FPGA芯片,4MB FLASH,512KB SRAM和8MB SDRAM。外部接口包括了:PS/2,以太网接口,VGA,TV,AV,串口,SD读卡器,IrDA,USB主/从接口。可以利用该开发板来学习和设计嵌入式系统。
DE2采用DM9000AE嵌入式网络控制芯片。与现在广泛使用的LAN91C111芯片相比,它具有更快的I/O访问速度(约为10ns左右),只有48针脚,支持AUTO-MDIX,价格更低,支持TCP/IP硬件加速,可以有效的减轻CPU的负担,内部提供了高达16KB的数据收发缓存。其中3KB用来作为发送数据缓冲区,其它的13KB用来作为接收数据缓冲区。该芯片提供了8位或16位位宽模式,设计人员在系统设计的时候按照相应的位宽进行引脚连接就可。
本设计使用SOPC Builder构建硬件平台。本设计的硬件构成有:Nios II软核处理器,片上存储器,Flash,SDRAM,SRAM,LED,DM9000AE网络控制芯片及其桥接器组件。这些器件构成的硬件系统如图1所示:
图1 硬件系统框图
图中的Avalon交换架构是由SOPC Builder自动生成的互连逻辑。Avalon交换架构将系统各个功能模块连接起来,从而构成一个完整的系统。
2 软件设计
在完成系统的硬件设计后,利用Altera提供的Nios II IDE软件,针对系统的硬件平台开发相应的软件,实现网络通信模块的软件设计。本系统的软件平台采用μC/OS-II嵌入式操作系统,使用LwIP网络协议栈。针对所使用的DM9000AE芯片,设计其驱动程序。使该驱动程序可以为LwIP所用。在此基础上开发网络通信程序。系统模型如图2所示:
应用程序 |
LwIP协议栈 |
μC/OS-II |
硬件 |
图2 系统模型图
2.1 LwIP协议介绍
LwIP是Light Weight(轻量级)IP协议,有无操作系统的支持都可以运行。LwIP实现的重点是在保持TCP协议主要功能的基础上减少对RAM的占用,一般它只需要几百字节的RAM和40K左右的ROM就可以运行,这使LwIP协议栈适合在低端的嵌入式系统中使用[2]。
LwIP主要可以分为以下几个层次,如图3。主要有以下几个功能模块:操作系统模拟层、网络接口函数、实现TCP/IP协议的各部分模块(IP,UDP,TCP,ICMP,ARP)、缓冲和存储管理子系统、校验和函数。
BSD Socket API |
|
LwIP API |
|
IP,UDP,TCP,ICMP,ARP |
|
操作系统模拟层 |
网络接口驱动层 |
图3 LwIP软件层次图
LwIP API是一组应用程序接口,通过该接口程序员就可以使用LwIP所有的功能。另外,LwIP也为开发者提供了更加高级的BSD Socket API。它的优点在于可以使用通用的Socket函数来编写网络通讯软件。这为熟悉传统Socket编程人员提供了极大的方便。也就是说对于软件编程人员来说,利用BSD Socket API来编写网络程序和在PC上编写网络程序完全一样。当然,为开发者提供BSD Socket API也使系统付出了代价。BSD Sockets要求在TCP/IP协议栈中将要发送的数据从应用程序拷贝到内部缓存。需要拷贝数据的原因是通常TCP/IP协议栈和应用程序一般都处在不同的保护区域。大多数时候应用程序是位于用户进程而TCP/IP却在操作系统内核中。这样的拷贝需要分配额外的内存,每个消息包都浪费了双倍内存[3]。而且,花费了不少CPU时间。降低了系统性能。
操作系统模拟层可以使LwIP使用操作系统提供的一些高级管理功能,例如信号量管理,消息队列管理,创建线程等功能。如果使用的操作系统不同,则必须针对不同的操作系统进行移植。
网络接口驱动层用来为LwIP提供网络接口芯片的驱动程序。针对不同的网络接口芯片开发设计相应的驱动程序就可以使LwIP操作不同的网络接口芯片。本系统采用的是DM9000AE网络控制芯片。下面将介绍DM9000AE在LwIP下的驱动程序开发。
2.2 DM9000AE驱动程序的开发
在DM9000AE中,对外只有两个寄存器,名为INDEX端口和DATA端口可以被直接访问。DM9000AE常用内部的控制和状态寄存器[4](见表1)通过INDEX/DATA来间接访问。访问特定的控制/状态寄存器的命令顺序:首先,将寄存器的地址写入INDEX端口,然后,通过DATA端口读/写数据。DATA端口的地址在INDEX地址上加4。
表1 DM9000AE常用内部寄存器说明:
寄存器 |
说明 |
地址 |
NSR |
网络状态寄存器 |
01H |
TCR |
发送控制寄存器 |
02H |
MRCMDX |
地址不增的存储器数据预读命令寄存器 |
F0H |
MRCMD |
地址自增的存储器数据读命令寄存器 |
F2H |
MWCMDX |
地址不增的存储器数据写命令寄存器 |
F6H |
MWCMD |
地址自增的存储器数据写命令寄存器 |
F8H |
TXPLL |
发送包长度低字节寄存器 |
FCH |
TXPLH |
发送包长度高字节寄存器 |
FDH |
ISR |
中断状态寄存器 |
FEH |
IMR |
中断屏蔽寄存器 |
FFH |
在LwIP中提供了一个名为ethernetif.c的文件。该文件中的函数为开发新的网络芯片驱动程序提供了模板。针对本系统使用的DM9000AE网络芯片编写相应的函数。分别是use_logic_dm9000a_init();use_logic_dm9000a_input();use_logic_dm9000a_output()。这几个函数主要完成对DM9000AE芯片的初始化,数据接收和数据发送功能。另外,编写use_logic_dm9000a_irq()作为DM9000AE的中断服务程序。
2.2.1 初始化
u 芯片初始化:芯片的初始化工作参照DM9000AE的应用手册[5]进行。
在完成芯片的初始化工作后,芯片就可以开始接收和发送数据包了。但是为了保证程序正确有序的运行,还要进行下面两步工作:
u 使用sys_sem_new()申请一个值为2的发送缓冲区信号量。该信号量表示了可用的发送缓冲区,每次发送数据包的时候必须要获取该信号量。否则,表示发送数据缓冲区正在使用,必须等待。
u 使用alt_irq_register()向系统注册一个名为use_logic_dm9000a_irq()中断服务程序。该函数用来响应DM9000AE芯片发出的中断。该函数的作用将在后面详细介绍。
2.2.2 接收数据包
在介绍接收数据包程序之前。首先,让我们先看一下在网络芯片上接收到的数据帧格式。如图4所示:
标志位 |
状态位 |
长度的低字节 |
长度的高字节 |
数据 |
图4 数据帧格式
u 标志位:“01”代表接收到数据包;“00”表示没有接收到数据包。如果两者都不是,则说明芯片工作状态不稳定,必须立即对芯片进行软件复位。
u 状态位表示该数据包的一些状态信息。如广播帧,CRC错误,物理层错误等。
u 数据包的数据长度用长度的低字节和长度的高字节两个字节来表示。
u 数据则是在网络传输中常见的物理层数据帧,在此就不展开了。
在弄清楚了芯片接收到的数据包的格式后。下面介绍一下DM9000AE芯片接收数据的软件编程算法:
1) 向INDEX端口写入MRCMDX寄存器的地址。
2) 读取DATA端口的数据。此时读出的是数据包的标志位。此时读数据指针地址不变。如果标志位为01H。则进入第3步。否则如果不为00H,则进行软件复位。为00H,退出程序。
3) 向INDEX断口写入MRCMD寄存器的地址。此时,每读一次DATA端口,读数据地址将自增。
4) 读出数据的状态位和数据包长度,数据包长度的值存入length变量。通过状态位判断是否为好的数据包,通过数据包长度判断是否超长。如果为好的数据包且不超长。则进入第5步。否则,读length/2次DATA端口。将数据包从接收缓冲区取出。
5) 向系统申请长度为length-4的缓冲区用于存放接收到的数据包。此处要将length减4是因为在数据包中的最后部分包括了4个字节的CRC码。
6) 循环读length-4/2次DATA端口将芯片接收缓冲区的数据读到系统刚分配的缓冲区中。要将长度除以2是因为该芯片是16位位宽模式。所以,每读一次DATA端口可读出两个字节的数据。
7) 最后,读两次DATA端口将CRC码从芯片缓冲区中读出。
至此,接收数据包流程完成。
2.2.3 发送数据包
在发送数据包之前必须使用函数sys_sem_wait()获取发送缓冲区信号量。限于篇幅具体算法不再叙述。
2.2.4中断服务处理函数use_logic_dm9000a_irq()
中断服务处理函数是用来响应网络芯片的中断。而网络芯片的中断源已经在初始化的时候通过设置IMR寄存器完成了。中断服务处理程序步骤:
1) 读取ISR寄存器的值。通过该值判断,如果是接收中断,则向接收消息队列发送一条消息。LwIP函数将捕获该消息,进而调用网络芯片的数据包接收函数。
2) 读取NSR寄存器的值。通过该值可以判断发送缓冲区1和发送缓冲区2的使用情况,如果已经发送完毕了。那么通过sys_sem_post()释放发送缓冲区信号量。
3 通信模块测试
在完成网络芯片的驱动程序开发后。通过分别编写TCP和UDP方式的通信程序来测试通信模块的功能以验证ARP,TCP, UDP,IP协议是否正常工作。通过Ping命令来测试ICMP协议是否正常工作。
TCP方式的通信程序使用BSD Socket API进行编程。以开发的系统作为服务端,指定IP地址10.0.0.67,监听30端口。而客户机通过telnet连接上服务端。然后,发送一些命令给服务端,服务端接收到后执行该命令,将执行结果返回给客户端。经测试可以顺利实现。说明TCP方式工作正常.
为了验证UDP方式的通信功能。本系统设计了UDP方式的通信程序,并使该系统作为UDP通信的服务端,指定IP地址为10.0.0.67,监听本地的3000端口。采用了LwIP API的方式来进行编程。另外在PC端,用VC编写一个使用UDP方式发送数据的程序。用来作为客户机向服务端发送消息。经过测试,服务端可以成功接收到客户端发送的消息。而客户端也可收到服务端发的反馈消息。说明UDP方式工作正常。
在PC 端用Ping程序连接服务端。PC端有回显,说明ICMP,ARP协议工作正常。
经过以上几项测试,说明ICMP,ARP,TCP,UDP协议都已经正常工作。
4 结论
本文使用Altera的SOPC Builder工具,运用组件化的方式对嵌入式系统进行硬件设计。这种硬件设计方式使得硬件设计更加简单,灵活。在生成系统硬件之后,通过加载μC/OS-II操作系统,LwIP网络协议栈,针对本系统所使用的网络芯片DM9000AE,开发相应的LwIP驱动程序。这样LwIP协议栈就可以利用DM9000AE进行网络数据的收发,系统具备了以太网通信功能。最后,利用LwIP的API函数,编写实现具体的网络应用程序,通过测试证明系统的以太网通信功能正常。成功完成了以太网控制器驱动开发。