因特网正进入一个新纪元,它正通过渗透到家庭、办公室甚至汽车中那些以前没有连网的普通设备,逐渐步入我们的日常生活。
Rene Trenado
应用工程师
摩托罗拉半导体公司
可惜,对大多数电子产品而言,在开放的因特网标准基础上实现与因特网随时随地的连接并非易事。例如,大多数家用电器都是基于非常便宜的8位微控制器技术,但很可能这些宿主微控制器既没有网络端口,也没有在不破坏其主要功能的前提下支持TCP/IP和其它因特网协议的硬件资源。
要实现完整的因特网通讯堆栈要求基于微处理器的系统具有大量的存储空间和很多的处理资源。不过,最近能使各种设备上网的技术逐渐增多:从在资源受限的系统中实现有限的TCP/IP功能,到单芯片堆栈,再到设备目标服务器(device object server)。每种方法都各有优缺点。
我们的经验是,即便是资源有限的8位微控制器也能实现与因特网的连接,而且无需拥有比MC68-HC908GP32微控制器更大的存储空间就能实现完全连接。通过正确地组合指令和外设功能,8位微控制器可以实现目前最流行的因特网协议?PPP点对点协议,并且通过这种协议与因特网上其它主机交换UDP/IP(用户数据报协议/IP协议)数据。实现这一协议所需的C代码不超过6,310字节,其中230 字节存放在RAM,6,080字节存放在ROM。
在我们的实现方案中,程序被分成好几个C模块。主要的C模块包括Main.C、CommDrv.C、 ModemDrv.C、PPP.C、SLIP.C、IP.C、UDP.C和ICMP.C,此外,还有一个混合C模块,这些模块的主要目的是便于代码借用和扩展,以便M68HC08程序员在采用M68HC08微控制器系列其它成员开发特定应用时能借用或修改这些源代码来满足设计需要。或者在开发过程中,以链接目标代码的形式创建一套能集成到将来应用中的库和功能。
数据报包
包含在IP.C中的IP协议,定义了数据报包或数据块,外加一个符合因特网通讯基本单元标准的IP报头。报头包含源设备和目标设备的数字地址,也就是通常所称的IP地址。该地址是因特网上每台主机的唯一标识,路由器根据这个地址将数据报送达目的地。通常而言,路由器并不关心数据报的具体内容,因为它们的工作只是把数据报尽快地发送到目的地。
一个完整的IP实现通常应该具备一些支持分段和重组的特性。但是,实现这些特性所需的CPU带宽和更多的RAM及ROM资源远远超过一个8位微控制器可能有的资源和能力,更不用说因此而增加的软件实现复杂性了。这就是为什么我们不在软件堆栈中实现任何一种功能的原因。如果由于某种原因,远端计算机给M68HC08发送了一个不完整的数据包,那么PPP将会拒绝并忽略它。
IP协议实现了一种机制来去除旧的数据报。在每个IP包的报头有一个8位生存时间域,它定义了一个数据包在被丢弃之前到达目的地的过程中所经历的最大路由数。这是因为没有路由的数据包可能一直在因特网上传来传去,从而可能一直占用宝贵的带宽资源。
UDP.C模块包含的是用户数据报协议的代码,它可被当作连接IP的应用程序接口,因为应用程序从来不直接使用IP。可以认为UDP层非常薄,它只有8字节的报头,因此它的开销很低。但是它需要应用层来完成错误修复或其他功能。
在ICMP.C模块中,采用因特网控制消息协议来提供一种机制,以确定我们正向其发送或读取数据报的因特网某一部分是否处于激活状态。
PPP.C模块包含点对点协议,这是今天用于串行连接的主要连接类型。PPP是业内广泛采纳的一套完整标准协议,它允许在多家供应商网络中采用诸如RS-232串行连接的两个主机能互相操作。
在一个PPP通讯中,对等体之间没有谁是服务器、谁是客户端之分,两个端点地位平等。但是出于实际应用的目的,在微控制器环境下,一台PPP服务器可以定义为位于ISP端的终点,而一台PPP客户端则可定义为该连接的起始端点。
SLIP.C模块实现串行线路IP协议(SLIP),与担任路由或网关的主机直接通讯。SLIP规定了在常规串行通讯线路上压缩原始IP数据报的方式。
CommDrv.C模块负责完成正确的系统串行通讯,它实现了一种访问串口硬件的伪标准方法。对于应用程序而言,串口可以被看作是一种API,类似那些执行直接逻辑操作的程序,例如OpenCommDrv.C 、CloseCommDrv.C 及 WriteCommDrv等。
ModemDrv.C模块代码假定使用了标准的Hayes兼容外置调制解调器。到目前为止基于M68HC08的系统都仅把外置调制解调器当作一个与它相连接的串行设备。从软件的角度看,调制解调器在串行口驱动程序的上层运行。换言之,它依靠CommDrv.C模块提供服务。调制解调器与微控制器之间的连接线包括信号地、发送信号线和接收信号线。
在一个嵌入式应用、外部服务器、网关或PC浏览器之间的典型UDP/IP连接中,程序命令MC68HC908-GP32担任消息发起人的角色。它一直等待,直到程序定义的条件满足为止。事先定义的条件可能是一个因被触发而发出信号的安全系统、一个达到预定义阈值的空调及一个门铃等。
系统首先给ISP拨号以建立PPP连接,ISP将对系统进行认证,并分配一个唯一的IP地址。之后,MC68HC908GP32就可以通过PPP/UDP/IP向因特网发送一个通告。一旦上网,一条消息实际上可以漫游到世界各地。毋需太多的工作,一个运行在目的地主机上的程序就可以传播UDP数据报。
运行在微控制器上的UDP/IP软件堆栈由main程序组成(标准C 的main函数),它分为两部分代码。第一部分初始化通讯端口以及所有其它软件模块。第二部分是一个调用ModemEntry() 和PPPEntry()函数的无限循环。Modem握手和PPP协调要分别用到这两部分。
CommDrv.C模块定义了针对中断的中断服务程序(ISR)代码,该中断在每次接收单字节字符时发生。不过,这个ISR要经过编译生成链接器能识别的目标代码,并放在闪存里。这意味着ISR源代码是在链接时被装入,而不是在运行时装入。由于微控制器的串行口在运行时将被各模块共用以执行不同的任务,因此必须找到一种使不同的模块能共享ISR的方法。
例如,MCU必须通过一个调制解调器拨号到一个ISP,在ISP响应之后,需要执行SLIP脚本或PPP协商对话。Modem.C和PPP.C必须依赖于CommDrv.C ISR。
实现灵活性所需的一种方法是,把ISR指向RAM中一个地址,该地址指向最终的中断服务处理程序。换句话说,指向ISR的指针最后被转换为一个指向某函数的指针。通过这种方法,程序员可以通过串口控制输入的字符流。