引言
目前,机械臂的控制系统普遍采用“PC/工控机+运动控制卡”的开发模式,但其体积较大、功耗高、携带不方便等不足之处成为其进一步发展的障碍。随着嵌入式技术的日益发展,ARM处理器的性能不断提高,因此可以考虑用ARM处理器来代替PC/工控机作为控制系统,使得系统具有体积小、重量轻、功耗低、便于携带的特点,同时将嵌入式操作系统Linux或者VxWorks移植到控制系统中,使其满足对实时性的要求。
PCI总线作为一种先进的高性能32/64位局部总线,非常适合于显示卡、网卡、多串口卡等高速外设。PCI总线具备32位的数据总线,时钟频率可达66 MHz,传输速率最高可达264 MBps,能够满足高速数据传输的需要。大多数数据处理模块、通信处理模块都具有PCI接口。本文采用Samsung公司基于ARM940T内核的处理器S3C2510A和带有PCI接口的运动控制卡的嵌入式架构,实现了深圳固高公司SCARA机械臂的控制系统。该方案省去了用的PCI接口芯片(如PLX9054),降低了电路设计难度。
1 系统 硬件设计
1.1 总体设计方案
系统整体结构如图1所示。控制系统可以划分为:以S3C2510A为核心的主控系统和带有PCI接口的运动控制卡。主控芯片S3C2510A具有4 KB的ICache和4 KB的DCache,其最高运行频率可达166 MHz。主控系统直接采用芯片内置的SDARM控制器、PCI控制器和10M/100M以太网控制器等。系统的外部时钟源为10 MHz,设置芯片引脚CLKMODO、CLKMODI、CPU_FREQ1、BUS_FREQ0为高电平,设置引脚CPU_FREQ0、CPU_FREQ2、BUS_FREQ1、BUS_FREQ2为低电平,然后经过S3C2510A的4个内置倍频器使系统内核的工作频率为133 MHz,PCI设备运行频率为66 MHz。

图1 系统整体结构
主控系统由主控芯片、存储系统和调试接口3部分组成。存储系统由2片16 MB、16位的SDRAM芯片K4S281632E和1片16 MB的Flash S29GL128M组成,除此之外,还包括1个高速UART、1个JTAG硬件调试接口和1个10M/100M的以太网接口。
S3C2510A内部集成的PCI总线控制器与PCI总线规范2.2版本相符合,具有32位地址/数据复用总线,支持非线性传输和突发传输,

图2 S3C2510A与PCI插槽的连接图
最高数据传输速率可达264 MBps/66 MHz或者132 Mbps/33 MHz。该处理器的引脚定义是根据PCI总线来命名的,因此只需将S3C2510A的PCI控制引脚引出,将引脚IDSEL与PCIAD12连接作为初始化设备选择信号。图2是S3C2510A与PCI插槽的连接图。
系统通电后,PCI插槽上的运动控制卡等待主控系统信号的输入;得到控制系统的控制信号后,运动控制卡便可控制SCARA机械臂的运动。控制系统调试可以通过UART串口来完成,通过系统上的网口可以实现控制系统的远程控制。
1.2 S3C2510A中PCI总线控制器
S3C2510A处理器内部集成了PCI/MINIPCI和PC Card控制器。根据该系统的需要,应将PCI控制器设置在PCI Host的工作模式,通过设置S3C2510A的PCI_PCCDM和PCI_HOSTM两个引脚来实现。S3C2510A中PCI总线控制器的工作模式如表1所列。

表1 S3C2510A中PCI总线控制器的工作模式
1.3 控制系统以及PCI总线控制器的启动顺序
系统上电后,系统PCI总线控制器的启动顺序如图3所示。在对PCI总线控制器的特殊功能寄存器进行配置时要关闭中断,即设置PCIINTEN=0。然后设置PCI控制和状态寄存器PCICON[ARB,ATS,SPL,IOP,MMP],在一些情况下还要设置PCI诊断寄存器。接着设置与基地址有关的寄存器PCIBAM0~1和PCIBATPA0~2,为了防止重启信号和时钟信号冲突,还要配置有关PCI重启和时钟寄存器PCIRCC[MSK]=0。
在PCI总线控制器侦测带有PCI接口的运动控制卡并初始化外围设备的寄存器时,需要完成以下工作:首先,读取所有的配置寄存器值,包括PCIHID、PCIHSC、PCIHSSID等;然后检查BAR(Backup Address Register)的范围,并一一分配空间;最后使能外部设备并激活总线。这些配置都是在PCI运动控制卡的驱动中程序完成的,因为已经把驱动程序加载到了μClinux的内核中,所以系统启动之后操作系统会自动配置PCI外部设备。

图3 系统PCI总线控制器的启动顺序
2 系统软件设计
系统软件主要由Bootloader和嵌入式μClinux两大部分组成。在嵌入式系统中,通常并没有像BIOS那样的固件程序,整个系统的加载启动任务完全由Bootloader来完成。简单地说,Bootloader就是在操作系统内核运行之前运行的一小段程序。通过这段程序,可以初始化硬件设备、建立内存空间的映射图,从而将软件的软、硬件环境设置到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。本系统采用通用的Uboot。嵌入式μClinux是这个系统的操作系统,主要包括设备驱动程序和上层应用程序。这里主要介绍一下Uboot的移植方法和uClinux中PCI设备驱动程序的实现。
2.1 Bootloader的移植
Bootloader的具体移植步骤如下:
① 下载并解压Uboot,修改主目录下的Makefile,改变交叉编译的路径,即CROSS_COMPILE =/home/lvlang/arm2510a/crosstoll/gcc4.1.1glibc2.3.2/arm9tdmilinuxgnu/bin/arm9tdmilinuxgnu。
② 在/board子目录中建立自己的硬件系统目录,在include/configs/中建立配置头文件,把支持S3C2510A的配置头文件s3c2510x.h改成系统的名字lvlang2510A.h,并测试编译能否成功,即Make lvlang2510A_config。若出现Configuring for lvlang board ...,则说明Uboot的第一步移植成功。
③ 根据硬件系统的具体情况进行源码修改,包括相关寄存器、Flash和SDRAM的相关配置,根据RUBRDIV0=( (int)(MCLK/16./(gd >baudrate)+05) 1 )来修改串口的波特率。
④ 将start.s中镜像的入口点设置为0x0地址,然后编译Uboot生成Uboot镜像文件,通过JTAG下载到Flash中并重启系统,即可通过串口在超级终端中看到启动信息了,至此移植Uboot成功。
2.2 μClinux设备驱动程序的编写
Linux的内核是由设备管理、进程管理、内存管理和文件系统组成,Linux设备驱动可以分为字符类设备、块类设备、网络接口类设备和其他非标准驱动。PCI设备被看作是字符型设备。
每个PCI外设都由1个总线号、1个设备号和1个功能号来标识,共有3个访问空间,即内存空间、I/O端口和配置寄存器。PCI配置空间由256个字节组成,且每个设备功能都有一个配置空间,用于决定PCI器件的工作方式和映射到系统中的地址。相关函数如下:
int pci_present(void) //系统是否支持PCI
struct pci_dev //PCI设备的软件对象
int pci_find_device(……)//寻找指定的PCI设备
int pci_find_class(……) //寻找指定的PCI属类
int pci_read_config_byte(……) //读配置空间
int pci_write_config_byte(……) //写配置空间
下面介绍在μClinux中添加带有PCI运动控制卡驱动的步骤。
① 创建一个PCI设备,命令为mknod pci_dev c 245 0。其中,c表示字符设备,245表示主设备号,0代表次设备号。
② 初始化外部设备,将函数pci_dev_init()添加到uClinux/linux/drivers/char/mem.c文件的chr_dev_init()中,chr_dev_init()将在系统启动时被调用,会完成设备驱动的初始化工作。
/*修改file_operations数据结构*/
Struct file_operations pci_dev_fops={
read: pci_dev_read;
write:pci_dev_write;
open:pci_dev_open;
release:pci_dev_release;};/*初始化PCI外部设备*/
int pci_dev_init(void){
int result;
printk("pci_dev_init()\\n");/*设备注册*/
result =register_chrdev(245,"pci_dev",&pci_dev_fops);
}
③ 编写设备驱动文件pci_dev.c。设备注册接口函数和中断处理函数等构成了PCI设备驱动主要代码,即file_operations中的函数。设备驱动与内核关系紧密,在编写过程中需要注意库函数的使用和I/O空间分配。在嵌入式系统编程过程中无法使用LibC提供的标准库。要根据S3C2510A的PCI配置寄存器所给定的基址来读写数据。因为PCI定义的I/O空间是32位地址空间,因此内存和I/O可以使用相同的配置接口。
④ 加载PCI设备。因为μClinux不支持设备驱动的动态加载,因此需要把驱动编译到μClinux内核中。首先需修改makefile文件,添加obj_$(CONFIG_PCI_DEV)+=pci_dev.o;接着修改config.in,添加bool ′pci_dev install′ CONFIG_ PCI_DEV,以便在配置目标板Linux系统内核时对这个设备进行选择;最后在目标系统的makefile中添加设备节点pci_dev,c,245,0。这样在配置Linux内核时就可以选择pci_dev install,然后进行编译,这样PCI设备驱动就加载到了μClinux系统中。
3 结论
使用本文设计的控制系统以及带有PCI接口的运动控制卡和液晶屏组成的系统,即可实现对SCARA机械臂的运动控制,可以代替传统的以PC机或工控机作为控制系统的控制方式,在不失实时性的要求下对SCARA机械臂进行准确的控制。本设计创新之处是:系统采用嵌入式μClinux操作系统和32位带有PCI接口的嵌入式处理器,在不影响系统性能的同时降低了电路的设计难度,减小了系统的体积、功耗。该系统除了用于带有PCI接口的运动控制卡外,还可以用于其他任何带有PCI接口的设备,具有较强的通用性。