HDLC驱动注册为网络设备(转)

Design and Implementation of HDLC Device Driver Based on S3C4510B and uClinux
Abstract:A design and implementation of HDLC device driver based on the S3C4510B and uClinux is presented. By registering the HDLC device to the uClinux kernel as an Ethernet device and carrying out protocol conversion between Ethernet and HDLC in the device driver, high efficient data forwarding between Ethernet and HDLC interface is achieved. The initialization of HDLC device, data transmitting and receiving along with their interrupt handlings are discussed.
Key words:S3C4510B; uClinux; HDLC; device driver; protocol conversion
摘 要:本文介绍了基于S3C4510B和嵌入式操作系统uClinux的HDLC接口驱动的设计与实现。采取将HDLC接口向内核注册为Ethernet设备,并在驱动中完成Ethernet与HDLC协议间转换的设计方案,实现了数据在Ethernet和HDLC接口间的高效转发。对驱动编写中的HDLC设备的初始化、DMA模式下的数据发送、接收过程和中断处理进行了较为详细的介绍。该方案已在实际的卫星通信系统中应用,取得了良好的效果。
关键词:S3C4510B;uClinux;HDLC;设备驱动;协议转换
1. 引言
嵌入式系统的特点在于:针对特定的应用,使用“量体裁衣”的方式将所需的功能嵌入到各种应用系统当中。其早期主要应用于军事及航空、航天领域,之后逐步被工业控制、汽车电子、通信和消费电子领域广泛使用。与此同时,各种新兴的应用也对嵌入式系统的处理能力、通信能力等方面提出了更高的要求。
S3C4510B正是Samsung公司针对新兴的网络应用而开发的一款性价比很高的ARM核16/32位RISC微处理器。它内含一个由ARM公司设计的高性能、低功耗的ARM7TDMI内核,内置10/100M Ethernet控制器、HDLC控制器等一系列网络通信控制器,特别适合对价格和功耗均比较敏感的嵌入式网络应用。
uClinux是针对通信和控制领域的嵌入式操作系统,其主要的优势在于开放源代码、稳定、强大的网络通信功能以及其精简性。其内核功能与Linux基本相同,只是对内存管理和进程管理进行了改写,主要应用于没有MMU的微处理器平台,如S3C4510B处理器。
高级数据链路控制(HDLC)协议是一个在同步网上传输数据,面向位的数据链路层协议,由国际标准化组织ISO制定。由于HDLC面向位的特性,因而可以实现不限制编码的、高可靠和高效率的透明数据传输。随着通信的发展,HDLC正被日益广泛的应用,同时,它还是其他许多重要的数据链路层协议的基础。
本文介绍了基于S3C4510B和uClinux的HDLC接口驱动的设计与实现,以满足数据在Ethernet和HDLC接口间高效的协议转换和数据转发的需求。在给出HDLC驱动总体架构的基础上,本文较为详细的介绍了驱动编写中的HDLC设备初始化、DMA模式下的数据发送、接收过程和中断处理,最后讨论了如何编译和移植包含HDLC驱动的uClinux内核。
2. HDLC协议帧结构
HDLC使用同步传输机制,传输的所有数据均被封装为帧的形式,HDLC的帧结构如图1所示[1],它由六个字段组成,这六个字段可以分为五种类型:标志序列(F)、地址字段(A)、控制字段(C)、信息字段(I)和帧校验字段(FCS)。对于S3C4510B平台上的HDLC驱动开发者而言,上述字段中仅有“地址字段(A)”和“信息字段(I)”需要在驱动中被设置和填充,其余字段的设置和操作均由S3C4510B的HDLC控制器(HDLC Controller)自动完成。
 


图1 HDLC帧结构
3. S3C4510B HDLC模块
S3C4510B微处理器的HDLC模块的主要功能单元为HDLC控制器,其能够完成HDLC协议的帧同步、“比特填充”、FCS的产生和检测以及与Buffer Descriptor相关的操作等。下面主要对S3C4510B上HDLC驱动开发中所涉及的较为重要的两个方面:“本地HDLC站点地址设置”以及“缓冲区描述符(Buffer Descriptor)”进行介绍。
 本地HDLC站点地址设置
每个HDLC通道都有5个32-bit的寄存器以完成本地HDLC站点地址的关联和识别,其中包括4个本地HDLC站点地址寄存器(例如,Channel A为HSADR0A~HSADR3A)和1个地址掩码寄存器(例如,Channel A为HMASKA)。因此,每个HDLC通道都可以关联1个到4个HDLC地址,且地址长度可以从8-bit到32-bit,由地址掩码寄存器控制。所有接收到的HDLC帧的地址字段都会在与地址掩码异或之后按照从HSADR0到HSADR3的顺序与本地HDLC站点地址进行比较,以判断接收数据帧的目的地是否是本机。
 缓冲区描述符(Buffer Descriptor,BD)
S3C4510B的HDLC控制器支持两种数据传输模式:中断模式和DMA模式。对于中断模式,由于CPU需要主动干预缓冲区和I/O模块之间的数据传送,因此将会导致过多的系统切换开销,降低CPU利用率,同时无法支持高速的数据传输。因而通常情况下我们都会采用更为高效的DMA模式。在DMA模式下,S3C4510B中的HDLC控制器使用了“缓冲区描述符(Buffer Descriptor,BD)”来实现以帧为单位的数据发送和接收。
BD是S3C4510B中HDLC控制器用以实现DMA模式下的数据收发而使用的数据结构,且构成循环链表的形式。发送BD和接收BD在结构上有细微差别,但均包含6个域:1)所有权位(Ownership):表明该BD将由CPU还是DMA负责处理;2)数据缓冲区指针(Buffer Data Pointer):指向该BD所关联的数据缓冲区,是实际需要发送或接收到的数据;3)控制位/状态位(Control bits/Status bits):发送BD既包含控制位也包含状态位,接收BD仅包含状态位;4)数据缓冲区长度(Buffer Length):存储该BD所关联数据的长度,该域为16-bit,即每个BD所关联数据的最大长度为64K-Byte,因此发送和接收的一帧数据可能会对应生成多个BD,发送数据帧的分片由用户完成,接收数据帧的分片由DMA控制器完成;5)下一个BD指针(Next Buffer Descriptor Pointer):用以将BD构成循环链表;6)保留(Reserved):未用,以备将来扩展。
4. uClinux环境下S3C4510B的HDLC驱动
 HDLC驱动总体架构
由于我们的系统需要完成的主要工作是S3C4510B中Ethernet接口和HDLC接口间高效的协议转换和数据转发,针对上述需求,我们提出的一种设计方案为:将HDLC接口向uClinux操作系统内核注册为Ethernet设备,然后在HDLC驱动中完成Ethernet协议和HDLC协议之间的转换和底层设备驱动等任务。上述方案的优点在于:首先,将HDLC接口注册为Ethernet设备后可以利用uClinux内核自带的IP转发(IP forwarding)功能实现Ethernet接口和被内核“认为”是另一个Ethernet类型接口的HDLC接口之间的高效数据转发;其次,Ethernet设备驱动框架清晰,易于开发者进行定制、扩展和实现。
按照上述方案,HDLC驱动的总体框架与普通Ethernet设备相同[3]。特别的,其中针对HDLC设备定制的功能函数包括:
int hdlc4510b_init(struct net_device *dev);  /*初始化HDLC控制器*/
int hdlc4510b_open(struct net_device *dev);  /*打开HDLC设备,主要是注册HDLC收发中断,使能HDLC接收,从而开始等待发送和接收数据/*
int hdlc4510b_stop(struct net_device *dev);  /*停止HDLC设备的发送和接收*/
int hdlc4510b_start_xmit(struct sk_buff *skb, struct net_device *dev); /*对内核提供的数据发送接口,主要通过调用函数hdlc4510b_hw_tx(dev)完成实际的硬件发送*/
int hdlc4510b_hw_tx(struct net_device* dev); /*完成协议转换以及硬件数据发送*/
void hdlc4510b_tx_isr(int irq, void *dev_id, struct pt_regs *regs);  /*发送中断处理函数*/
void hdlc4510b_rx_isr(int irq, void *dev_id, struct pt_regs *regs);  /*接收中断处理函数*/
下面主要就HDLC设备的初始化、DMA模式的数据发送和接收过程及中断处理进行较为详细的论述。
 HDLC设备的初始化
HDLC设备的初始化由函数int hdlc4510b_init(struct net_device *dev)完成,其工作流程如图2所示。由于HDLC接口并没有MAC地址,因此在将其向内核注册为Ethernet设备时需要为其手动设置一个MAC地址。此处设置的MAC地址可以是任意值,因为其仅会在本机内部被使用(参见4.4节),不会出现在网络传输的数据包中。
      


图2 HDLC设备初始化  图3 DMA方式数据发送及中断处理 图4 DMA方式接收中断处理
 DMA模式下HDLC发送过程及中断处理
DMA模式下的HDLC发送由函数int hdlc4510b_start_xmit(struct sk_buff *skb, struct net_device *dev)通过在内部调用int hdlc4510b_hw_tx(struct net_device* dev)完成,其工作流程如图3所示。由于我们将HDLC设备在内核注册为Ethernet设备,因此在发送真正的数据包之前,IP内核会发送ARP请求,此时仅需对所有的ARP请求进行ARP欺骗即可。在我们的实现中,由于整个系统使用的是一个B类IP地址,因此“伪造”的ARP应答中的对端MAC地址的前4个字节均被设为0x00,后两个字节被设置为与对端的IP地址的后两字节相同,以保证“伪造”的MAC地址与对端真实IP地址的可对应性与唯一性。
在接下来的数据传输过程中,为了将Ethernet帧转换为HDLC帧,首先将对端的HDLC地址(我们的实现中使用16-bit的HDLC地址)填入待发送HDLC帧的地址字段,然后将Ethernet帧中除去MAC头部和尾部CRC校验的IP数据包部分拷贝至HDLC帧的信息字段。在生成包含地址和信息字段的部分HDLC帧之后,根据其长度决定是否将其分片,并生成相应的1个或多个BD,将上述BD的所有权位均设为DMA所有,然后使能HDLC控制器和DMA控制器进行发送,HDLC控制器将会补全构成完整的HDLC帧所需的其余字段,然后DMA控制器将会顺着BD链发送全部“所有权位”为DMA的BD所关联的数据。
DMA方式的发送中断处理由函数void hdlc4510b_tx_isr(int irq, void *dev_id, struct pt_regs *regs)完成。其处理比较简单,仅完成清除中断标志位、记录统计信息、释放占用的数据缓冲区以及通知上层可以继续发送数据等工作。
 DMA模式下HDLC接收过程及中断处理
DMA模式下的HDLC接收完全由接收中断处理函数void hdlc4510b_rx_isr(int irq, void *dev_id, struct pt_regs *regs)完成,其工作流程如图4所示。在接收中断的处理中,首先需要顺着BD链回溯至对应完整一帧帧头位置的BD,然后恢复出完整的一个数据帧。此时的数据帧实际上是IP数据包,接下来需要为其添加MAC头部和CRC校验从而将其转换为Ethernet帧。这里“伪造”的MAC头部中的源MAC地址使用与ARP欺骗中相同的方式构造,而目的MAC地址需要设置为HDLC设备初始化时所选择的本机MAC地址,MAC层的CRC校验可以通过函数eth_copy_and_sum(skb, ether_pkt, ether_pkt_len, 0)完成。生成的Ethernet帧通过函数netif_rx(skb)交给IP内核进行转发处理,最后需要将所有接收中断处理函数中所使用的BD的所有权重新设置为DMA所有,以供DMA控制器接收后续数据使用。
 HDLC驱动的编译和移植
按照前述方法编写好uClinux环境下针对S3C4510B的HDLC驱动(hdlc4510b.h和hdlc4510b.c)之后,还需要对uClinux进行如下的配置以编译新加入的HDLC驱动:1)将hdlc4510b.h和hdlc4510b.c拷贝至目录uClinux/linux-2.4.x/drivers/net下,并修改此目录下的Makefile文件,在原有的obj-y += s3c4510b.o后新加入一行:obj-y += hdlc4510b.o,即将HDLC驱动编入uClinux内核;2)修改uClinux/romfs/etc/rc,在最后加入语句:
ifconfig eth1 192.168.0.6 netmask 255.255.255.0; route add default gw 192.168.0.6
上述语句将在启动时自动加载HDLC驱动,并将eth1与HDLC接口关联,且将其设为默认路由,在适当配置内核IP转发之后即可完成Ethernet与HDLC接口之间的数据转发。
完成上述修改之后,重新编译uClinux内核[4],并将uClinux/image目录下的image.rom通过bootloader烧写入FLASH,加电重启后系统会自动将内核解压至SDRAM运行,且在启动最后按照脚本uClinux/romfs/etc/rc自动对HDLC接口进行配置。
5. 结束语
本文介绍了在S3C4510B嵌入式平台和uClinux操作系统环境下的HDLC接口驱动的设计与实现。为了满足数据在Ethernet和HDLC接口之间的高效协议转换和和数据转发的需求,本文提出了将HDLC接口向内核注册为Ethernet设备,且在驱动内部完成Ethernet和HDLC协议间转换及底层设备驱动任务的设计方案,在保证了高速数据转发的同时,由于可以借鉴Ethernet驱动开发的成熟经验,也缩短了HDLC驱动的开发周期,该设计方案对开发其他类型网络接口驱动也提供了参考。同时,本文所叙述的嵌入式开发流程,对其他基于uClinux的开发也有很好的借鉴作用。按照本文所述方案实现的HDLC接口驱动已经应用于实际的卫星通信系统,并取得了良好的效果。
参考文献
[1] William Stallings. 数据与计算机通信[M]. 北京:电子工业出版社,2004.
[2] UM_KS32C50100_REV1,User’s manual of Samsung snds100[S]
[3] Alessandro Rubini, Jonathan Corbet. Linux Device Drivers[M]. 北京:中国电力出版社,第二版,2002
[4] 衣美丽,刘庆文,杨扬等. 基于uClinux+S3C4510B的嵌入式系统的研究[J]. 微计算机信息,2005.20(1): 125-126
论文的创新点:
1. 与已有的不基于嵌入式Linux操作系统的“裸机”方式的实现方案不同,本文提出的HDLC驱动的设计与实现是基于嵌入式uClinux操作系统的实现方案。
2. 本文一个非常有特色的创新在于将HDLC设备向uClinux内核注册成为一个Ethernet设备,且在HDLC驱动中完成了Ethernet和HDLC间的协议转换、ARP欺骗等工作。按照此方案实现的HDLC驱动结构清晰,易于开发者进行功能的扩展和定制,

作者简介:刘朋(1981–),男,云南昆明人,硕士研究生,主要研究方向为卫星和无线网络通信协议及Linux嵌入式系统。
金野(1967–),男,黑龙江哈尔滨人,北京大学教授,博士生导师,主要研究方向为卫星与无线通信系统。
联系方式:
刘朋,北京大学畅春园63号楼412室,100871,boraliu@pku.edu.cn
金野,北京大学理科2号楼2350N,100871,yejin@ele.pku.edu.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值