0.引言
随着嵌入式系统的广泛应用,嵌入式软件开发变得日趋重要。嵌入式软件开发有别于桌面软件开发,其显著特点是软件开发的调试过程采用宿主机/目标机的模式进行,其交叉调试器分为宿主机和目标机两部分,因此在软件调试过程中就需要进行主机与目标机之间的通信。
目前宿主机与目标机之间的通信方式主要有串口方式、以太网接口方式和USB接口方式三种,其中串口通信实现简单,稳定可靠,是目前广泛使用的通信方式,但是串口通信存在着速度慢、通信距离受限等弊端,而以太网接口方式则可以克服串口方式的不足,不仅可提供稳定可靠的数据传输,而且无论是传输速度还是传输距离都远远优于串口方式,是一种快速高效的通信方式。目前网络通信协议的发展已经相当成熟,Internet工程委员会IETF及其下属的管理组IESG在RFC文挡中已经明确定义了Internet协议族的规范,该规范已经成为一种标准在Internet中广泛应用。本文根据此规范讨论了在嵌入式调试器中如何实现以太网接口通信,给出了一种基于嵌入式调试器的网络通信方法。
1.硬件结构
S3C4510B是三星公司开发的一款16/32位RISC嵌入式处理器,芯片内部集成了一个10Mbps/100Mvps以太网控制器,网卡芯片采用的是RTL8201。以太网控制器主要分为BDMA控制器和MAC子层两部分,该控制器工作于MAC层,兼容IEEE802.3协议标准,支持半双工或全双工模式,采用介质独立接口(MII)与网卡芯片通信。
2.通信协议
在嵌入式调试器的通信中,主机向目标机发送命令,目标机接收、执行命令并将结果返回主机,网口通信主要是面向数据和字符串传输的,因此在通信中主要用到IP协议、ARP协议和UDP协议。要通过网络调试目标机,那么目标机IP地址的设置是必不可少的,因此目标机还需要实现BOOTP协议,通过BOOTP协议向主机申请本机IP地址,完成IP地址的配置。
BOOTP协议即引导程序协议,是一种基于UDP/IP的协议,主要用于客户机从服务器获得本机IP地址、服务器IP地址及其它配置信息,如本地子网掩码等。UDP协议即用户数据报协议,是一个简单的面向数据报的传输协议,与TCP不同,UDP不提供对IP协议的可靠机制、流控制以及错误恢复功能,所以实现起来比较简单,且不影响传输速度,适用于嵌入式系统。IP协议即网际协议,是网络上实现数据传输的基础,所有的TCP、UDP数据都以IP数据报格式传输,该协议提供了一种高效不可靠的无连接传输方式。ARP协议即地址解析协议,为IP地址与对应的物理地址提供映射。
3.网络通信程序实现
具体的程序实现主要包括网口驱动和通信协议两部分,网口驱动即初始化S3C4510B的硬件,主要是以太网控制器和收发缓冲的设置;网络协议的实现主要是完成数据的收发,保证目标板接入以太网。程序实现流程如图1所示。
3.1网口驱动实现
网口驱动的实现主要是针对具体的开发板所做的硬件初始化,配置硬件工作环境。
3.1.1管理网卡芯片
在4510开发板中由MAC层的状态管理控制机通过MII接口来读取和设置网卡的工作状态,物理设备地址及其内部寄存器地址存放在站管理控制与地址寄存器STACON中,而要设置或读取的数据则放在站管理数据寄存器STADATA中。
在实际应用中,网卡的MAC地址可以从ICC EEPROM中读取,也可自行设定,只要保证在同一局域网内该地址的唯一性即可。
3.1.2初始化以太网控制器
①关闭MAC、BDMA收发中断,保证初始化程序的顺利进行。
②设置MAC、BDMA中断向量表。S3C4510B中共有21个中断源,MAC和BDMA发送/接收中断源占用16~19四个中断号。
③设置MAC、BDMA控制器的初始值,即初始化BDMA接收/发送控制寄存器和MAC接收/控制寄存器,具体收发细节。
④配置以太网的收发缓冲区。发送帧和接收帧的帧描述符起始地址分别存放在寄存器BDMATXPTR和BDMARXPTR中,在BDMA的操作过程中它们会更新为下一个帧地址。其中,帧描述符定义为结构类型,结构体成员描述了帧信息。
⑤使能BDMA接收中断和MAC发送中断。将中断屏蔽寄存器INTMSK中的相应位清零,响应BDMA和MAC中断请求。
3.1.3收发以太数据帧
①发送以太数据帧:调用发送函数DrvEthWrite(),从BDMATXPTR中获得发送帧地址,为发送帧缓冲赋值,将数据帧的控制权交给BDMA控制器,以太网控制器自动为发送数据加上同步位、分割位、校验位以及填充字段并将以太帧发送出去。
②接收以太数据帧:接收时产生BDMA接收中断,中断处理函数BDMA_Rx_isr()完成数据的接收,并做相关的处理,如清楚中断标志位、检查数据帧的所有权、获取下一个未处理的帧结构指针等。
部分主要程序如下:
/*配置物理设备*/
MIIWrite(0x0, 0x2, 1<<13|1<<8);/*设置物理设备的状态*/
status = MIIRead(0x1, 0x0);/*读取物理设备的状态*/
/*配置MAC地址*/
GetMyMacAddr():
/*关闭收发中断*/
Disable_Int(nMAC_RX_INT);
Disable_Int(nMAC_TX_INT);
Disable_Int(nBDMA_RX_INT);
Disable_Int(nBDMA_TX_INT);
/*设置MAC发送中断和BDMA接收中断向量*/
SetInterrupt(nMAC_TX_INT, MAC_Tx_isr);
SetInterrupt(nBDMA_RX_INT, BDMA_Rx_isr);
/*初始化MAC、BDMA控制器*/
BDMARXCON = BRxRS; /*设置BDMA接收控制寄存器*/
BDMATXCON = BTxRS; /*设置BDMA发送控制寄存器*/
MACCON = Reset; /*复位MAC控制寄存器*/
BDMARXLSZ = MaxRxFrameSize+40; /*接收帧的最大尺寸*/
MACON = gMacCon; /*设置为全双工方式*/
/*配置以太网的收发缓冲*/
TxFDInitialize();
RxFDInitialize();
/*使能BDMA接收中断和MAC发送中断*/
Enable_Int(nBDMA_RX_INT);
Enable_Int(nMAC_TX_INT);
3.2通信协议实现
本文采用结构类型定义数据结构bootphdr、Udphdr、ip和arphdr,分别用来记录BOOTP、UDP、IP和ARP协议数据报报头的各种信息。
3.2.1配置目标机IP地址
目标机首先向主机发送BOOTP请求,主机运行DHCP服务为目标机分配IP地址,向目标机发送BOOTP应答包,目标机收到应答包后,按照协议格式获取主机和本机的IP地址以及其它相关信息。
①生成BOOTP请求。初始化bootphdr中各个结构体成员的值,客户IP地址和主机IP地址分别设为0.0.0.0和255.255.255.255,在系统进行引导时0.0.0.0是一个有效的IP地址,目标机在不知道目的主机的IP地址时可以使用广播地址255.255.255.255,以广播的方式发送BOOTP请求。MAC地址已在初始化时获得,并存放在全局变量MyMacSrcAddr中,其它成员变量可以按照协议的格式设置即可。
②发送BOOTP请求。BOOTP请求需封装在UDP数据报中发送,BOOTP的服务器端口和客户端口分别使用知名端口67和68;UDP校验和通过调用函数udpChksum()计算获取。IP报头各成员按照IP数据报格式设置,源IP地址与目的IP地址分别是0.0.0.0和255.255.255.255,IP校验和通过调用函数ipChksum()计算获得。本机MAC地址作为源MAC地址,广播形式的MAC地址0xffffffff作为目的MAC地址,封装成以太数据帧,调用写函数DrvEthWrite()发送。调用发送中断处理函数MAC_Tx_isr(),更新当前帧结构描述指针并复位MAC控制器。
③接收BOOTP应答包,获取主机和本机的IP地址。采用中断方式接收BOOTP应答包。中断处理函数BDMA_Rx_isr()将接收到的包存放在接收帧描述符RxFDBaseAddr中,提取有效数据放入BOOTP接收缓冲区BOOTP_REC_BUF中,并且复位相应的BDMA控制寄存器道和中断控制位。
③按照协议的数据报格式从BOOTP_REC_BUF中提取数据,记录本机和主机的IP地址。
3.2.2数据收发
数据的收发主要是涉及IP、UDP和ARP三个重要的协议,在具体实现中根据嵌入式系统的特性有针对性地做了裁减,既保证了网口的正常工作,又节省了嵌入式系统的资源。
①有以太网数据包到来,首先进行判断。如果是ARP请求则发送一个ARP应答;如果是ARP应答,则记录发送方的IP地址和以太网地址;如果是IP数据包,则开始接收数据。
②接收数据:IP数据包到来,中断处理函数将数据包放在接收帧描述符RxFDBaseAddr中,提取IP包放入接收缓冲区IP_REC_BUF。从IP_REC_BUF中提取有效数据交给调试器进行处理。
③发送数据:发送的数据封装在UDP数据报中,目标机IP地址和主机IP地址分别记录在全局变量MyIpAddr和HostIpAddr中,按照UDP和IP协议的数据报格式为数据加上UDP报头和IP报头。以本机MAC地址作为源物理地址,以ARP应答中获得的主机物理地址作为目的地址,封装成以太数据帧,调用写函数DrvEthWrite()发送,中断处理函数MAC_Tx_isr()进行发送中断处理。
部分主要通信程序如下:
SendBootpRequest(bootp_id);/*发送BOOTP请求,bootp_id是该请求随机分配的标识号*/
/*等待BOOTP应答包*/
/*BOOTP应答包到来,从接收缓冲BOOTP_REC_BUF提取数据*/
memcpy(MyIpAddr,bhdr->your_ip,4); /*提取目标板的IP地址放在全局变量MyIpAddr中*/
memcpy(HostIpAddr,bhdr->server_ip,4); /*提取主机IP地址放在全局变量HostIpAddr中*/
/*检查到来的包*/
if(pro_type==ETHERTYPE_IP) IpProcess(IP_REC_BUF);/*处理到来的IP包*/
if(pro_type==ETHERTYPE_ARP) ArpProcess(IP_REC_BUF,42);/*处理到来的ARP包*/
4.结语
用C语言实现的程序代码已调试通过,并成功应用于嵌入式调试器中。该功能模块针对具体的开发板所设计的网口驱动和协议栈,裁减了冗余的功能部分,既能满足嵌入式系统对资源占用的要求,又能保证数据准确、无丢失传输。测试证明对于批量数据的传输,网口的速度远远优于串口,有效地实现了主机与目标机之间的调试通信,具有一定的实际意义。
本文作者创新点:设计并实现了嵌入式调试器的以太网接口通信方式,针对具体的开发板对网口驱动和协议栈做了裁减,既能满足嵌入式系统的资源占用要求,又能保证数据高效传输。