关键词:PCI总线;S3C2510A;嵌入式系统;Boot loader;μClinux,
Abstract: With the wide application of embedded system and PCI devices, many products need to run on both platforms of embedded system and systems with PCI interface. The design of the embedded video transmission system, for example, is presented in the paper. The hardware design of the embedded motherboard of 2 PCI slots with processor S3C2510A of ARM9; transplantation of Boot loader and methods of constructing device driver is also described. The application of the newly developed motherboard will eliminate the necessity of repeated development of embedded system and kinds of ready-made PCI device can apply to the embedded system conveniently.
Key words: PCI Bus; S3C2510A; embedded system; Boot loader; μClinux
1. 引言
使用ARM微处理器构建嵌入式系统已经广泛应用于工业控制、视频音频采集、安防监控、消费类手持移动产品、家庭网关设备等各个领域[1]。目前的嵌入式系统大多是针对某项特定应用来开发的,通常分为两个部分:主控部分和数据处理部分;不同的嵌入式系统的主控部分功能基本类似,区别大多集中在数据处理部分。例如一个视频采集处理系统和一个设备运行状态监测系统的不同就是前者的数据处理是对视频数据进行采集处理,而后者的数据处理部分则是对监测的设备运行参数(如压力、温度、流量等)进行采集处理,所以两个系统的主控部分可以完全一致。基于这种现状,我们开发设计了一个通用嵌入式主板来完成嵌入式系统的主控部分功能。这样,在进行系统开发时可以把主要的工作精力放在数据处理卡的开发上,而减少主控部分的重复开发。
另一方面,基于PCI总线的广泛应用,且PCI总线具备32Bit数据总线,时钟频率可达66Mhz,最快传输速率达到264MB/s,能够满足高速数据传输的需要;加之大多数数据处理模块、通信处理模块都具有PCI接口,因此嵌入式主板主控部分和数据处理部分的接口设计采用PCI总线(设计的主板可提供两个PCI插槽)。利用带有PCI接口的通用嵌入式主板,加上根据功能需要开发或选定的数据处理板卡,使嵌入式系统运行在“独立工作模式”,便能够完成原本需要设计整个嵌入式系统才能够完成的任务,而现在只需编写PCI设备的驱动程序就可以直接将现有的PCI设备应用到通用嵌入式主板中。
2. 硬件电路设计
图1是以视频传输系统为例,介绍了通用嵌入式主板的应用。系统处理器采用三星公司的S3C2510A,
图1. 视频传输系统框图
Fig.1 video transmit system
芯片为ARM 940T内核,最高运行频率可达200Mhz。主板设计直接采用芯片内置的SDRAM控制器、PCI控制器、USB控制器和10M/100M以太网控制器等一系列接口控制器。主板的外部时钟源为10Mhz,通过S3C2510A的4个内置倍频器,设置引脚CLKMOD0、CLKMOD1、CPU_FREQ1、BUS_FREQ0为高; 设置引脚CPU_FREQ0、CPU_FREQ2、BUS_FREQ1、BUS_FREQ2为低,使系统内核运行频率为133Mhz,
PCI设备运行频率为66Mhz,USB设备运行频率为48Mhz。
主板采取最小系统核心板和外围接口扩展板分层的设计思想,两块板之间通过高速连接器件相连,从而使主板的应用更加方便、灵活。最小核心板由主控芯片、存储系统和调试接口三部分组成。其中主控芯片采用内置PCI控制器的S3C2510A;为了满足视频传输需要大量内存空间和存储嵌入式Linux操作系统的需要,存储模块由2片32MByte、16Bit的K4S561632E SDRAM芯片和2片8MByte、16Bit的AM29LV640MT FLASH;调试接口是1个RS232串口和1个Jtag硬件调试接口。外围接口扩展卡由2个10M/100M的以太网络接口,1个RS232串口,1个RS485串口,2个USB HOST接口可以外接硬盘等存贮设备,1个USB DEVICE接口可以将主板设置为PC机的目标设备。这里将着重介绍有关PCI总线接口部分的硬件设计。图2是S3C2510A与PCI插槽之间的连接原理框图。
图2. S3C2510A的PCI实现原理框图
Fig2. The hardware design of S3C2510A PCI
系统上电后,PCI插槽上视频音频处理卡将等待模拟视频信号和模拟音频信号的输入,当处理卡得到模拟数据后便对模拟数据进行压缩、编码,处理后的数据通过S3C2510A内部AHB总线传输到以太网端口,利用主板上嵌入式Linux系统中的视频服务程序通过以太网将压缩后的数据传输到客户端PC,客户端只需使用解码播放器就可以收看到视频。同时也可以传输到USB端口,把视频文件保存在硬盘存贮介质上。开发板的系统调试可以通过RS232串口来完成,而且通过RS232可以外接GPRS无线调制解调器,在无法通过以太网进行数据传输的情况下可以无线上网,将重要资料传输出去。RS485串口可以实现某些特殊协议的传输,例如云台控制协议。
2.1 自带PCI总线控制器的S3C2510A
Table1. Operation Mode According to Mode Pin Setting
三星的S3C2510A ARM处理器,内部集成了PCI(MINI-PCI)& PC Card控制器,根据应用需要将S3C2510A的PCI(MINI-PCI)& PC Card控制器设置为PCI Host工作模式,这是通过设定PCI_PCCDM和PCI_HOSTM两个配置引脚的电平来实现的[2]。见上页表1所示。
S3C2510A内嵌的PCI总线控制器符合PCI总线规范2.2版本,具有32bit地址/数据复用总线,支持非线性传输和突发传输,最高数据传输速度可以达到264MB/s@66Mhz(132MB/s@33Mhz) 。而且带有地址变换机制,可以将内部的PCI总线地址映射到内存或者外围设备。2510A的引脚定义是根据
PCI总线来命名的,因此设计者只需将S3C2510A的PCI控制引脚接出即可。 在设计中设定PCI总线的时钟频率为66Mhz,因此主板上PCI总线的最高传输速度可以达到264MB,能够满足数据的快速传输。在这里需要利用时钟反馈来弥补PCI的时钟延迟。
图3. S3C2510A的PCI控制器时钟反馈机制
Fig3. PCI Clock Schemes
如上图所示,当PCI控制器工作在PCI HOST模式下时,其时钟源是由系统内部提供的,S3C2510A有3个PCI时钟输出信号PCICLK1,PCICLK2和PCICLK3,将PCI设备诊断寄存器PCIDIAG0的DC3位设置为1,即将PCICLK3设置为输出无效,此时PCICLK1与PCICLK3相连,通过PCICLK3将时钟信号反馈给处理器内核,这样可以使外部PCI设备与PCI时钟保持一致,从而弥补时钟延迟[3]。
2.2 系统以及PCI控制器的工作启动顺序
系统上电之后,系统以及PCI控制器的启动顺序如图4所示:其中在对PCI控制器的特殊功能寄存器进行配置时需要首先关闭中断,即设置PCIINTEN=0。然后设置PCI控制和状态寄存器PCICON[ARB,ATS,SPL,IOP,MMP],某些需要的情况下还要设置PCI诊断寄存器,这个寄存器是针对测试功能的,在PCMCIA Host工作模式下不需要进行设置。然后要对与基地址有关的寄存器PCIBAM0~1和PCIBATPA0~2进行设计,设置完之后要配置有关PCI重启和时钟的寄存器,其中关键的一步是设置PCI重启和时钟寄存器PCIRCC[MSK]=0,这是为了防止重启信号和时钟信号的冲突[3]。
图4.PCI控制器及外围设备的启动顺序
Fig4. PCI Controller’s Booting Sequence
在PCI控制器侦测外围设备并初始化外围设备的寄存器时,需要完成以下工作:
1) 读取所有的配置寄存器值,包括PCIHID,PCIHSC,PCIHSSID等等。
2) 检查BAR(Backup Address Register)的范围并一一分配空间。
3) 使能外部设备并激活总线。
以上配置都是在PCI视频处理卡的驱动中完成的,因为已经把驱动程序加载到了uClinux的内核中,所以系统启动之后,操作系统会自动配置PCI外部设备。
3. 系统软件设计
系统的软件主要由Boot Loader和嵌入式uClinux两大部分组成,其中Boot Loader相当于PC机的BIOS,是在操作系统内核运行前运行的一段程序,其主要作用在于初始化硬件设备,建立系统的内存空间映射,然后再调用操作系统内核。嵌入式uClinux是这个系统的OS,主要包括设备驱动程序和上层应用程序。这里主要介绍一下移植Boot Loader的方法和uClinux中设备驱动程序的实现。
3.1 Boot Loader的移植
Boot Loader是和硬件紧密连接的,系统是通过Boot Loader来调用操作系统内核并最终运行操作系统的。本系统采用了U-Boot(Universal Boot Loader,)作为Boot Loader,下面围绕U-Boot的移植来介绍如何建立主板的BootLoader。
U-Boot相当于一个小型的Linux系统,其工作涉及到硬件系统的初始化,存储空间分配等等,因此其移植工作需要认真地阅读相关芯片的硬件手册,在设计过程中主要完成了以下工作,相关的程序编写可以根据U-Boot提供的例程来完成:
1) 修改Makefile配置文件,添加针对目标板的编译命令行。
2) 在CPU目录下建立arm940t目录,主要包括系统入口函数start.S,中断设置函数代码interrupts.c,CPU相关代码文件cpu.c以及串口初始化代码相关文件serial.c等。
3) 在Board目录下建立S3C2510目录,主要包括FLASH初始化代码flash.c,内存分配代码memsetup.S,连接器文件u-boot.lds等。
4) 编写配置文件,即:include/configs/s3c2510.h,完成了寄存器的定义等系统配置,大部分工作是参考S3C2510的数据手册来进行的。
5) 编写flash.c文件,根据使用的AMD的NOR Flash来编写Flash的驱动,主要有flash芯片的型号,容量大小,打印信息,flash擦除函数等。
6) 修改SDRAM的大小,只要修改前面建立的配置文件include/configs/s3c2510.h中的#define PHYS_SDRAM_SIZE 0X200000即可。其大小是根据实际应用中SDRAM的大小来确定的。
7) 修改串口参数文件serial.c。包括设置串口波特率,其中波特率是由下式计算得出:
RUBRDIV0=( (int)(MCLK/16./(gd ->baudrate) + 0.5) -1 )。
8) 修改start.S文件,一个可执行的Image 必须有一个入口点并且只能有一个唯一的全局入口,通常这个入口放在Rom(flash)的0x0 地址。例如start.S 中的.globl _start_start: 。
完成上面工作后就可以将U-Boot编译,通过Jtag口下载到目标板进行调试。
3.2 uClinux设备驱动编写
Linux的内核是由设备管理、进程管理、内存管理和文件系统一起组成,Linux设备驱动可以分为字符类(Character)设备,块类(Block)设备,网络接口类设备和其他非标准驱动。其中PCI设备被看作是字符型设备[5]。
每个PCI外设都由一个总线号、一个设备号和一个功能号来标示,共有三个访问空间,即内存空间、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(…..) //写配置空间
下面通过添加系统的PCI设备驱动来介绍uClinux设备驱动的实现步骤:
1) 创建1个PCI设备,命令如下:
mknod pci_dev c 245 0
其中c表示字符设备,245表示主设备号,0代表次设备号。
2) 初始化外部设备,将函数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);}
3) 设备驱动文件pci_dev.c的编写。设备注册接口函数,中断处理函数等构成了PCI设备驱动主要代码。即file_operations中的函数。设备驱动与内核关系紧密,在编写过程中需要注意库函数的使用和I/O空间分配。在嵌入式系统编程过程中无法使用LibC提供的标准库。I/O空间检查。要根据S3C2510A的PCI配置寄存器所给定的基址来读写数据。因为PCI定义的I/O空间是32位地址空间,因此,内存和I/O可以使用相同的配置接口。
4) PCI设备的加载。
因为uClinux不支持设备驱动的动态加载,因此需要把驱动编译到uClinux内核中,首先需修改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设备驱动就加载到了uClinux系统中。
4. 小结
使用该主板和PCI接口视频处理卡组成的视频传输系统在局域网内进行视频传输时画面流畅、画质清晰。带有PCI接口的通用嵌入式主板的开发可以减少嵌入式系统的重复开发,缩短开发周期。核心板和扩展接口板的设计使主板的应用更加方便、灵活,只需根据具体应用将不同的数据处理卡与该主板结合,便能构成不同的功能系统,应用于各种具体需求。
参考文献
[1] 李善平.刘文峰.王焕龙.Linux与嵌入式系统[M].北京:清华大学出版社,2003.1-4
[2] 李贵山, 威德虎. PCI局部总线开发者指南[M]. 西安:西安电子科技大学出版社, 1997
[3] snmsung electronics. S3C2510A 32bit RISC Microprocessor user’s manual[M], 2003.3, 43-47
[4] 李驹光.聂雪媛.江泽明.王兆卫.ARM应用系统开发详解[M] .北京:清华大学出版社,2003.202-205
[5] Alessandro rubini, Jonathan corbet著,魏永明,骆刚, 姜军译.Linux 设备驱动程序(第2版)[M],中国电力出版社,2002.11 502-526