摘要: 为了缩短基于ARM的网络化嵌入式应用开发周期、降低开发成本和提高产品质量,提出一种有别于传统利用操作系统开发嵌入式应用的模式。在该模式的框架下,对W5100网络芯片底层驱动进行编写、封装和测试。测试表明该驱动能完成预期功能。该驱动一旦被设计好,就可以在多个项目中重复使用,缩短网络化嵌入式系统开发周期,降低开发成本和提高产品质量。

关键词: W5100驱动;复用;面向对象;ARM;嵌入式应用;开发模式

引言

嵌入式操作系统的引入大大提高了嵌入式系统的功能,方便了嵌入式应用软件的设计,但同时也占用了宝贵的嵌入式资源。

嵌入式操作系统大多采用组件化、模块化的设计思想,以搭积木的方式通过互连构造软件,因而是可配置的。但是由于操作系统的多样性,不同操作系统提供的配置方式迥异且繁简不一。而由于硬件平台的多样性,即使是相同的操作系统,其应用配置也有差别。结果是,应用程序开发者必须熟悉不同的硬件平台和操作系统才能进行有效的应用开发,增加了应用开发的难度。特别是网络化嵌入式应用一般出现在比较大型的项目中,复杂度和难度大大增加。因此,提高网络化嵌入式应用产品质量、缩短开发周期、降低开发成本是开发人员面临的迫切要求。

1 开发模式方案选择

面向对象的方法、设计模式的思想是当前实现软件模块化、提高软件可复用性的最优方法。面向对象编程语言、组件和构架是被广泛认可的、用以降低软件成本并提高软件质量的技术。

面向对象的主要好处在于它强调模块性和可扩展性,将易变的实现细节封装在稳定的接口后面,增强了软件的可复用性。但是,在目前的嵌入式实时系统中采用面向对象的方法进行上层软件的设计还有很多困难。最主要的,就是底层实时操作系统没有提供有力支持,即使上层软件勉强采用了面向对象的方法,代码的模块化、可移植性、可复用性也难有提高。

因此,为了避免采用传统操作系统的开发模式带来复杂问题,本文采用一种自定义的裸机开发模式。该模式避免了不同操作系统平台改变带来复杂的问题。其创建项目过程没有复杂的裁剪,只有根据需要添加相关驱动和编写适当应用层代码。即使是硬件平台的改变,也只是根据硬件配置不同改变其条件编译而已。

2 自定义裸机开发模式

自定义开发模式下的应用软件体系结构如图1所示。该体系结构包含管理层、应用层、控件层、虚设备层和实设备层。其中管理层处于类似于操作系统中“内核”的地位,为其他层的管理者。

图1
自定义开发模式下的应用软件体系结构
跟PC机上的Windows应用软件类似,应用层是由一个或者多个窗口组成的,有可视窗口和不可视窗口。其中各个窗口中又包含一个或者多个控件。控件为窗口提供各种服务,由设备层提供支撑。在控件层和实设备层中间有一个虚设备层。
根据设备功能的复杂程度,虚设备分为简单的虚设备和复合虚设备。实设备分为简单的实设备和复合实设备。其中复合设备是由简单设备组合而成。
从类的关系看,虚设备层就是含有虚函数的基类,该函数一般没有实现,只是声明了接口,实设备层就是从该基类继承下来的,具体实现是由该实设备层来完成。由于接口的稳定性,这就保证了底层硬件改变时,应用层的程序几乎可以没有改变或者改变甚小。
3
自定义开发模式下的W5100驱动编写
3.1
接口电路说明
本驱动设计采用W5100串行SPI接口。SPI接口模式只需要4个引脚进行数据通信,分别为SCLK、/SS(SPI从模式选择输入引脚,低电平有效)、MOSI、MISO。W5100
的SPI_EN 引脚高电平表示SPI
使能,/RESET引脚低电平实现W5100芯片的复位。本项目选择的MCU芯片为LPC2138,其中W5100与LPC2138对应引脚连线如表1所列。
表1 LPC2138与W5100对应引脚连线说明

3.2 W5100驱动分析
本驱动开发环境为:CodeWarrior for ARM Developer Suite
V1.2。
在自定义开发模式中,前期编写好的驱动类有引脚类、SPI类、外部中断类,就是所谓简单设备。这些类及其头文件的具体介绍略——编者注。
在使用W5100前需要操作其/SS引脚,选中W5100芯片SPI从模式。初次配置或者重新配置W5100相关参数前,需要操作其/RESET引脚,让所有原来配置复位。配置W5100相关参数是通过SPI读写操作来完成的。
W5100从网络上接收了一个数据包后,会让其/INT引脚从高电平变为低电平。在本项目中,把该引脚跟LPC2138的外部中断1引脚相连,如果开启了外部中断1,那么就触发一个外部中断。该外部中断服务里面应当有实现LPC2138访问W5100,并读取W5100里面接收到的数据包的功能。LPC2138获取W5100里面的数据包,必须通过SPI读写操作的配合才能实现。
综合上面的分析,该W5100驱动应当是由引脚类、外部中断类、SPI操作类互相配合完成,因此W5100驱动是一个复合设备。
3.3
W5100实设备驱动编写
本驱动针对W5100采用UDP协议进行网络通信功能来编写。

首先所有实设备都必须从一个虚设备下继承下来。创建一个名为Ip_NetWork_Virtual_Device网络虚设备,其部分头文件略——编者注。
由于网络通信应用的芯片有多种,但是无论是哪种芯片,实现的功能都离不开网络包的读和写。因此在该虚类里的声明都是共用的功能。基类里面含有虚函数,就是声明了接口,但是没有具体的实现,具体的实现由其具体的实设备来完成。在继承中,如果基类和派生类中定义了同名的成员函数,当用基类指针指向公有派生类的对象后,可以使用虚函数来实现通过基类指针找到相应的派生类成员函数[11]。
W5100的实设备NetWork_W5100类的部分头文件略——编者注。
3.4
W5100实设备驱动说明
3.4.1 虚设备类指针
在W5100实设备头文件中有:
Spi_Virtual_Device*
SpiPort;
OutEint_Virtual_Device* IntDevice;
PinDevice_Virtual_Device *
W5100_Cs;
PinDevice_Virtual_Device *
W5100_RESET;
由于W5100实设备需要几个简单设备配合来完成其功能,因此设计W5100实设备驱动拥有这些简单设备的指针,可以看出这些指针是指向简单虚设备对象的指针。
声明为指向基类对象的指针,当它指向公有派生类对象时,可以利用它来直接访问派生类中从基类继承下来的成员,不能直接访问公有派生类中特定的成员。
采用面向对象中模式编程法则中的依赖反转法则:依赖抽象而不依赖具体[12]。
在main.cpp首先声明如下的实设备,如下:

OutInt_2138 NetOutInt; //外部中断类实设备对象
NetWork_W5100
Net5100;//W5100实设备对象
Spi0_Driver_Lpc Spi0;//SPI实设备对象
Pin_LPC2138 PIN023;
//引脚实设备对象
Pin_LPC2138 PIN031;
//引脚实设备对象
接着在main.cpp采用如下代码完成Net5100和简单设备NetOutInt、Spi0、PIN023、PIN031等的关联:
NetOutInt.WorkModel=Fall_Eage;//表示下降沿触发
NetOutInt.SubDeviceName=Eint1;//表示使用外部中断1
NetOutInt.Ini();
NetOutInt.Father=&Net5100;
Net5100.SpiPort=&Spi0;//设置Spi0和SpiPort指针关联
Net5100.W5100_Cs=&
PIN023; //设置片选引脚关联
Net5100.W5100_RESET=& PIN031;
//设置复位引脚关联
在“Net5100.SpiPort=&Spi0”中SpiPort是指向某基类对象的指针,Spi0是该基类的派生类对象,该语句实现把该指针指向其派生类对象。因此就可以利用该指针直接访问该公有派生类从基类继承来的成员。同样,可以利用W5100_Cs和W5100_RESET等基类对象指针直接访问该基类的派生类——Pin_LPC2138类从基类继承下来的成员,即引脚的操作函数等。
在NetWork_W5100中有W5100_Send_Receive_Data函数就是利用这个技术,该函数如下:
char
NetWork_W5100::W5100_Send_Receive_Data(char dat){
char
i;
W5100_Cs->Clear();
i=SpiPort->SPI_Send_Receive_Data(dat);
W5100_Cs->Set();
return
i;
}
NetWork_W5100类对象能实现SPI读写操作,是因为其拥有一个SPI虚设备的指针。同理,能实现对引脚操作是因为其拥有一个引脚虚设备的指针。
3.4.2
外部中断实设备和W5100实设备关联
NetOutInt是一个外部中断类对象,使用前首先对该对象进行初始化,其中代码“NetOutInt.SubDeviceName=Eint1”表示该类对象和外部中断1产生了绑定。
在本项目测试中,W5100从网络接收到一个数据包后触发了一个外部中断1中断。该W5100实设备类对象Net5100感知该事件,从而对该事件进行处理,接着把该消息发布给其所支撑的控件。
main.cpp中有“NetOutInt.Father=&Net5100;”,其中Father是一个指针,该指针来源如下:
class
Object{
public:
……
Object
*Father;
……
};
由于所有设备类都是从该类间接继承下来,所以都拥有这个Father指针。
“NetOutInt.Father=&Net5100;”的目的是把Net5100对象地址赋给该指针,因此该指针就指向Net5100,说明NetOutInt拥有一个指向Net5100的指针。main.cpp中,外部中断1的服务程序代码如下:
void
__irq
IRQ_Eint1(){
NetOutInt.HardInt(Null);
VICVectAddr=0×00;
NetOutInt.ClearInt();
}
“NetOutInt.HardInt(Null);”其本质就是调用到HardInt函数,如下:
void
OutInt_2138::HardInt(Device*
IntDevice){
……
this->Msg.MsgID=Sys_Msg_OutInt;
this->Msg.Parm1=this->SubDeviceName;
this->Father->Message(Msg);
……
}
“this->Father->Message(Msg);”即中断服务最后把该工作交给Father指针指向的Net5100,接着该对象调用了其Message函数。NetWork_W5100类的Message函数伪代码如下:
void
NetWork_W5100::Message(MessageBody SystemMsg){
if
Socket3
SelectSocket(3);
if Socket2
SelectSocket(2);
if
Socket1
SelectSocket(1);
else
SelectSocket(0);
};
其中NetWork_W5100类的SelectSocket函数如下:
void
NetWork_W5100::SelectSocket(char socket){
uint16
address,inttype;
address=COMMON_BASE+0×100*socket+0×0402;
inttype=NetWork_Read(address);

if((inttype&0×04)==0×04){
//接收数据引起中断
S_UDP_RX_Process(socket,&ReceiveBuffer[0],&ReceiveBuffer[8]);
//从对应的Socket接收数据
Msg.MsgID=Sys_Msg_UdpGetData;
Msg.Msg=&ReceiveBuffer[0];
VclPointer[socket]->Message(Msg);
//向支撑控件发送消息
}
NetWork_Write(address,0xFF);//清除所有的中断
}
可见,W5100驱动最后把网络接收到数据包作为一个消息发给其所支撑的上层控件。
4
W5100驱动测试
4.1 测试方案
在PC机上,利用网络测试工具TCP/UDP
Socke调试工具V2.2,通过网络向W5100的终端发送一个数据包。当该终端接收到该数据包后,把该包往PC机终端发送。如果发送和接收的数据包一致,说明通信测试成功。
4.2
测试过程
PC机端的IP地址为192.168.1.103,某端口号为9000。W5100本身地址设置为192.168.1.101,某端口号为9000。PC机往W5100终端发送数据包,在如图2所示操作界面的数据发送窗口输入“Hello,
This is a happy word!”字符串后,点击“发送数据”,在操作界面的数据接收窗口接收到“Hello, This is a happy
word!”,并且在操作界面上方显示“对方IP:192.168.1.101,对方端口:9000”,这跟W5100终端设置是一致的,说明双方的通信成功。

结语
W5100驱动的创建过程非常复杂,但是对于编写好的驱动,应用者只需要了解该接口使用的说明,而不用关心其复杂的内部实现细节。如果其他项目需要用到W5100,只需要把该驱动添加到该项目中即可,从而实现驱动的复用,避免重复的工作,缩短项目开发周期。如果下次要使用W5100驱动的其他功能,如TCP协议通信,只需要在原来驱动上添加相应的函数即可,因此维护起来更加方便。

编者注:本文为期刊缩略版,全文见本刊网站www.mesnet.com.cn

转自: 《单片机与嵌入式系统应用》杂志

欢迎与我们更多交流!

可复用的基于ARM的W5100底层驱动设计相关推荐

  1. 基于ARM的嵌入式网络收音机的设计

    基于ARM的嵌入式网络收音机的设计 摘要:研究了一种基于ARM处理器的嵌入式网络收音机的设计方案.该系统以ARM处理器及其外围设备为硬件平台,以嵌入式Linux为操作系统,实现了网络收音.局域网共享音 ...

  2. 【2022集创赛】安谋科技杯三等奖:基于ARM处理器的无线SoC设计

    本篇文章是2022年第六届全国大学生集成电路创新创业大赛安谋科技杯三等奖作品分享,参加极术社区的**[有奖征集]分享你的2022集创赛作品,秀出作品风采**活动. 团队介绍 参赛单位:厦门大学 队伍名 ...

  3. 基于ARM IP的看门狗设计与功能验证

    看门狗是一个定时器, ARM提供了一个32位向下计数的看门狗IP,它会不断地计数.通过软件可以设置计数值,计数到某一设定值重新开始计数,这一过程也被称为喂狗,如果没有正常喂狗,说明出现系统故障,看门狗 ...

  4. 基于DirectFB的framebuffer底层驱动及应用程序架构原理分析

    本文作者为:铁匠Smith 先生 转载请在显著位置注明出处和链接,否则保留追究相关事务之权利. 一.DirecfFB架构下应用层fbdev系统的初始化 对任何一个dfb应用程序,它在初始化时一定会调用 ...

  5. android mipi数据,基于Android的MIPI设备驱动设计与实现

    摘要: 随着科技的进步和人们生活水平不断提高,人们越来越离不开移动应用设备,手机和平板作为Android系统的重要载体已经走进了千家万户,Android作为目前市场份额最大的嵌入式操作系统,跟Symb ...

  6. 基于ARM处理器的无线SoC实现

    随着新一代移动通信技术的快速发展,无线SoC已经成为物联网产业发展的基础,在嵌入式领域中占有越来越重要的地位.实际生活中,无线通信应用几乎无处不在,例如目前智能家居主流2.4G无线通信方案Zigbee ...

  7. linux 内核 scsi底层驱动程序,Linux系统下基于SCST的SCSI_Target驱动设计.doc

    Linux系统下基于SCST的SCSI target驱动设计 摘要 随着信息数字化的深入发展,数据存储的需求日益增长.存储虚拟化带给我们最直接的益处就是,提高存储利用率,降低成本,简化存储管理,而基于 ...

  8. 基于DSP的数字振荡器C语言编程,基于DSP的数字振荡器的设计与实现.pdf

    1 基于 DSP 的数字振荡器的设计与实现 基于 DSP 的数字振荡器的设计与实现 黄福莹 陈华 徐金隆 广西大学计算机与电子信息学院 南宁 530004 摘要 摘要 本文阐述了一种基于 DSP 芯片 ...

  9. 基于ARM+DSP进行应用开发-经验共享

    针对当前应用的复杂性,SOC芯片更好能能满足应用和媒体的需求,集成众多接口,用ARM做为应用处理器进行多样化的应用开发和用户界面和接口,利用DSP进行算法加速,特别是媒体的编解码算法加速,既能够保持算 ...

最新文章

  1. 计算机栈是什么,什么是数据栈?——线性表
  2. Xcode 如何使用旧版本SDK以保证程序兼容性
  3. Doxygen with Graphviz to generate call graph on Mac
  4. Android Studio 安装 PlantUML 插件
  5. Github上都没有的“网约车”项目,终于有人给写出来了!
  6. 【iOS】Tab Bar 的 Item 按钮的像素大小要求
  7. 设计模式之Prototype(原型)
  8. Python遗传算法部分匹配交叉(PMX)
  9. java上传文件服务器_java 实现文件上传到另一台服务器
  10. θ - γ耦合作为脑机接口调节慢性脑卒中运动恢复的皮质生物标志物
  11. 如何在IDM中设置代理服务器
  12. 李一男造车失败;马云卸任浙商总会会长;特斯拉或将迎来华人CEO | 每日大事件...
  13. 统计笔记3:statistical inference
  14. 神经网络:训练模型+转化为k210上跑的kmodel
  15. 均衡负载集群(LBC)-2
  16. C#发送企业内部邮件
  17. 公司破产了股需要东承担哪些责任
  18. 财政部将加强金融企业财务管理
  19. 关于React native Demo项目的总结
  20. c语言编辑问道注册登录程序,C语言实现简单的注册登陆功能

热门文章

  1. 网络***检查分析---破解安全隐患问题回答
  2. 欧盟将推出自己的互联网扩展域名
  3. C++-bit转hex(四位二进制转十六进制)
  4. 如何将两个php超链接,php超链接跳转
  5. java 图片地址,java中图片地址存入数据库
  6. cass参考手册_CASS9.2参考手册
  7. mysql索引级别快慢_面试小点-MySQL 的两种索引方法如何提高查询速度
  8. input位置_3分钟短文 | PHP 数组任意位置插入新元素,你是怎么处理的?
  9. java jexl_利用Jexl实现数据库的计算公式在Java中执行
  10. JavaScript进阶高级