摘要:本文提出了在uClinux操作统下,为以Freescale公司的32位控制芯片Cold
Fire 5307为CPU的嵌入式工业网络服务器开辟数据交换区的思想和解决方案。
引言
数据交换区就是指程序执行中使用到的各种数据所存放的内存空间。本文提出了在uClinux操作统下为嵌入式工业网络服务器开辟数据交换区的思想和解决方案。嵌入式工业网络服务器项目的开发目的是构建一个以Client/Server模式工作的工业远程监控系统,其前端是一个嵌入式服务器,它安装在工业现场,可以与三菱PLC组成的控制系统接口,对该系统实施实时监控。其中数据交换区部分起到承上启下的枢纽作用,向上负责对客户端交互现场设备数据,向下负责与接口缓冲区交互设备实时数据。系统以Freescale公司的32位控制芯片Cold
Fire 5307为CPU,使用两片现代公司的HY57V641620 的4M 16bit的SDRAM拼成4M 32bit的SDRAM,使系统具有16M
bytes的RAM空间。
uClinux操作系统
系统选取uClinux 操作系统为开发平台,为有两片4M 16bit的SDRAM的嵌入式工业网络服务器开辟数据交换区。
ColdFire 5307微处理器上可以运行很多操作系统,但是uClinux是最合适、性价比最高的操作系统。目前商业实时操作系统,比如VxWorks和Nuclesus等价格比较昂贵,而且需要附加的C编译器和相关的调试工具。而像uCOS等免费的实时操作系统,又没有很好的文件系统和TCP/IP协议的支持,就嵌入式工业网络服务器的应用特点而言,uClinux是最适合的操作系统。我们在uClinux下面实现了JFFS(Journaling
Flash File System)文件系统,每次子模块传送回来的数据都可以像日志一样记录下来,非常方便。另外还在主系统中的NAND
Flash接口中实现了FAT32文件系统,与PC机上Windows下面的FAT32文件系统兼容,因此非常方便数据的备份和更新。使用uClinux的同时,主控制系统的所有软件工作都在Linux(Red
Hat)系统下使用GCC交叉编译器来编译,使用GDB交叉调试器来调试工作。
uClinux内核采用模块化的设计,很多功能块可以独立地加载或卸载,在设计内核时可以把这些内核模块作为可选项,在编译系统内核时指定。一种较通用的做法是对uClinux内核重新编译,在编译时仔细选择嵌入式系统所需要的功能支持模块,同时删除不需要的功能模块。通过对内核的重新配置,可以使系统运行所需要的内核显著减小,从而缩减需要的控制器RAM和ROM资源。
uClinux同标准Linux的最大区别就在于内存管理,对SDRAM数据交换区的管理就属于内存管理范畴。标准Linux使用虚拟存储器技术,对于uClinux来说,其设计针对没有MMU(memory
management unit) 的处理器。但uClinux仍然采用存储器的分页管理,系统在启动时把实际存储器进行分页。在加载应用程序时程序分页加载。但是由于没有MMU管理,所以实际上uClinux采用实存储器管理策略(real
memory management)。uClinux系统对于内存的访问是直接的,它对地址的访问不需要经过MMU,而是直接送到地址线上输出,所有程序中访问的地址都是实际的物理地址。
uClinux对内存的管理从编译内核开始,从而系统将在启动的初始化阶段对内存进行分页,并且标记已使用的和未使用的内存。系统将在运行应用时使用这些分页内存。另外由于采用实存储器管理策略,用户程序同内核以及其他用户程序在一个地址空间,程序开发时要保证不侵犯其他程序的地址空间,以使得程序不至于破坏系统的正常工作,或导致其他程序的运行异常。
数据交换区硬件架构
ColdFire系列微处理器是Freescale公司延续其M68K系列微处理器推出的新一代32位高性能嵌入式微处理器。ColdFire系列微处理器继承了M68K系列优秀的指令集设计和CISC架构的优点,融入了RISC架构的优点,在速度和架构之间得到了很好的平衡。ColdFire
5307微处理器运行在外部总线时钟45MHz、内部总线时钟90 MHz时,可以达到75MIPS。
与Flash存储器相比较,SDRAM不具有掉电保存数据的特性,但其存取速度大大高于Flash存储器,且具有读/写的属性。因此,SDRAM在系统中主要用于程序的运行空间、数据交换区及堆栈区。当系统启动时,CPU首先从复位地址0x0处读取启动代码,在完成系统初始化后,程序代码一般应调入SDRAM中运行,以提高系统的运行速度,同时,系统及用户堆栈、运行数据也都放在SDRAM中。SDRAM具有单位空间存储容量大和价格便宜的优点,已广泛应用在各种嵌入式系统中。SDRAM的存储单元可以理解为一个电容,总是倾向于放电,为避免数据丢失,必须定时刷新(充电)。
嵌入式工业网络服务器项目中的数据交换区根据数据交换区配置文件生成,向上负责对客户端交互现场设备数据,向下负责与接口缓冲区交互设备实时数据。每片SDRAM是由4M
16bit的内部Bank组成,这个Bank的选择由SDRAM的外部引脚BA0和BA1来完成,在我们的系统中BA0和BA1都连接在ColdFire5307的高端地址线上;其他信号和ColdFire5307都一一对应。UDQM和LDQM是SDRAM的高低字节片选信号,因为每片SDRAM都是16位架构,所以我们将两片SDRAM拼在一起变成32位时,其他信号线对两片SDRAM来说都是共用的,唯有数据线和这两个信号不是共用的。这两个信号分别接ColdFire5307的CAS0、1和CAS2、3。SDRAM与MCF5307的连接关系如图1所示。
图1 MCF5307与SDRAM接口原理框图(略)
ColdFire 5307可以支持两个Bank的SDRAM,在系统中只使用了第一个Bank,另外一个Bank的控制信号悬空不使用。其中,SDRAM和Flash
RoM以及其他外设一同使用32位数据总线D0:31;SDRAM映射到内部物理地址,但是因为SDRAM的特殊性,并不需要所有的地址线信号A0:31,而是使用其中一部分信号线,这个地址映射的工作由DRAM控制器来完成;RAS0:1是Bank片选信号,我们只使用RAS0来片选所使用的SDRAM
Bank;CAS0:3是SDRAM 32位数据线中4个8位数据线(Byte)独立的片选信号;SCAS和SRAS分别是SDRAM的行、列地址锁存信号;DRAMW是DRAM写信号;BCLKO是系统时钟输出,连接到SDRAM的时钟输入引脚CLK端;SCKE是SDRAM时钟使能信号,来使能输入给SDRAM的时钟信号,高电平时SDRAM自动进入休眠状态。
数据交换区软件实现
服务器依据数据交换区配置文件生成设备数据交换区。数据交换区格式如表1所示。
表1: 数据交换区格式(略)
服务器进入运行模式之后首先检查生成数据交换区与底层缓冲区的配置文件是否存在。如果不存在则打印错误信息,存在则依据配置文件在系统SDRAM区开辟数据交换区与底层缓冲区。接着系统检查PLC通信协议文件是否存在,不存在则打印错误信息,存在则将COM2口置为PLC通信端口。一切就绪之后,系统启动任务调度,完成各种任务。
数据交换区生成及使用流程图如图2所示。
图2 数据缓冲区生成及使用流程图(略)
图3是生成数据缓冲区子程序流程图。
图3 数据缓冲区生成子程序(略)
在2.4版uClinux内核中,内核引导时,通过访问系统所有的物理内存,然后调用各个子系统的初始化函数进行初始化,允许初始化代码分配私有的缓冲区,并减少了留给常规系统操作的RAM数量。在2.4版uClinux内核中,这种分配通过调用下列函数之一进行:
# include< linux/ boot mem.h>
void*alloc_bootmem(unsigned long size);
void*alloc_bootmem_low(unsigned long size);
void*alloc_bootmem_low-pages(unsignedlong size);
分配内存空间所使用的函数调用如下:
# include<stdlib.h>
void*malloc(size_t size);
void*calloc(size_t nmemb,size_t size);
函数malloc和calloc都是用于分配动态内存空间的函数。
函数malloc的参数size表示申请分配的内存空间的大小,以字节记。
函数calloc的参数nmemb表示分配的内存空间占的数据项数目。参数size表示每一个数据项的大小,以字节记。也就是说,calloc函数分配大小为nmemb*size大小的内存空间。
calloc函数与malloc函数最大的区别是calloc函数将初始化所分配的内存空间,置所有位置为0。调用成功时,malloc函数与calloc函数的返回值都为被分配的内存空间的指针;调用失败时,返回值为NULL。动态内存被释放在C中,指针是处理许多数据结构的关键。没有指针,也许根本不能使用动态内存的诸多特性。在编写程序的时候,它允许程序员建立复杂的内存系统,提高了处理未知内容或者类型数据的灵活性。在C中还有一点对字符串处理和数据的输入输出很重要。对指针的彻底了解有助于写出更好、更高效的代码。
如果使用一种算法不够,链表可以解决这个问题。当从未知大小的数据块中读入数据时,用户不得不把数据读到内存中。这是因为处理读入数据的函数,必须把数据读到一块一定大小的内存中。在读入以后,必须找到一种接合分离数据的办法。
一般使用fgets( )把数据读到n个字节大小的内存中。缓冲区是n+1个字节大,但是请注意必须使用1个字节放结束标记。然后使用了一个简单的链表保存数据。这个链表有一个特殊项:一个名为iscontinuing的整型变量。如果这个变量有值,它表示当前结构中的数据不是字符串最后的部分,最后的部分将包含在以后的结构中。这个变量再把数据从内存中调出来,重新组装的时候使用。
还有一种更明智的保存数据的方法。逐步处理数据直到到达数据末尾。首先要修改的是结构的定义。在结构中包含字符串。在结构中定义一个指针,指向动态申请的内存区域。这样做的好处是,字符串可以很长。
现在产生输出的代码更简单了。它做的所有的事情就是计算和显示。不再需要合并字符串,因为它们已经被合并了。
结束语
数据交换区的生成和使用对嵌入式工业网络服务器项目尤为重要,它是WEB服务器正常运行的先决条件,起到承上启下的枢纽作用。向上负责对客户端交互现场设备数据,向下负责与接口缓冲区交互设备实时数据。日前,该部分设计工作已经完成,并在试运行期间情况良好,达到预期效果。
|