雷金奎, 赵 晨, 陈 浩
(1.西北工业大学 第365研究所,陕西 西安 710065;2.西北工业大学 陕西 西安 710072)
近年来,无人机[1]以其独有的低成本、低损耗、零伤亡、可重复使用和高机动等优势,在军用和民用领域的应用范围不断扩大,使得人们对无人机提出了更高的要求,因此作为无人机核心的飞行控制器的研究也越来越受到重视。高精度要求无人机控制系统的精度高,稳定性好,能适应复杂的环境,计算速度快,精度高[2],小型化则对控制系统的重量和体积提出了更高的要求。此外,还要具备实时、可靠的特点。
本设计的无人机飞行控制平台是基于ARM+DSP双处理器协同工作来实现的,总体结构图如图1所示。平台选用SAMSUNG公司的ARM9处理器S3C2440作为主处理器,选用TI公司的DSP处理器TMS320F2812作为从处理器。双口RAM芯片IDT7028L实现双处理器之间的通讯,AD7490芯片将机载传感器采集的信号由模拟量转换为数字量,AD5628芯片用于输出模拟控制量。平台外扩32M SDRAM,8路串口通信电路,具有30路离散I/O口,JTAG调试接口。主要实现的功能:
1)ARM主处理器采集各传感器信号,包括角速度、高度、飞行器姿态等参数,经调理电路滤除干扰后送入A/D转换电路,将转换后的数字量存入双口RAM。
2)DSP从处理器通过双口RAM获取数据,进行控制律解算,产生PWM控制信号送入舵机,保证无人机平稳飞行。
图1 系统总体结构图Fig.1 Structure diagram of the small UAV flight platform
根据平台任务划分,分别对ARM、DSP处理器进行软件设计。针对ARM主处理器需要完成U-boot内核引导程序、Linux内核、yaffs根文件系统的移植,建立起嵌入式ARMLinux系统,基于此开发环境进行驱动及应用程序开发。针对DSP从处理器主要基于CCS集成开发环境,使用C语言与汇编语言完成数据处理。
ARM处理器主要包括初始化模块、数据采集模块,其中数据采集模块包括A/D转换、串行通讯和无线通讯等。初始化模块主要完成对ARM系统时钟、中断寄存器、外部存储器的操作,保证串口、AD7490等的正常工作。数据采集模块使用计数方式产生不同时间间隔的定时中断,在中断服务程序中完成对A/D转换、串口等数据的采集并存入双口RAM IDT7028L。
DSP处理器主要包括初始化模块、控制律解算模块。初始化模块保证DSP系统正常工作。为满足系统的实时性要求,控制律解算模块通过设置合理的定时间隔读取双口RAM中的数据,进行控制律解算,向舵机输出PWM控制信号。在解算过程中考虑到A/D转换、串行通讯、无线传输具有不同的刷新速率,刷新速率较慢的数据使用历史值作为当前值。软件设计流程图如图2所示。
图2 软件设计流程图Fig.2 Flow chart of the software design
飞控平台软件设计的关键是移植Linux操作系统,并在此基础上实现底层驱动的开发。
3.1.1 Bootloader的移植
文中选用U-boot-1.1.6作为系统的Bootloader,在源码基础上修改添加开发板硬件相关文件、配置选项。首先修改最顶层Makefile,在其中添加如下两行:
smdk2440_config:unconfig
@$ (MKCONFIG) $ (@:_CONFIG= ) arm arm920t smdk2440 NULL s3c24x0
修改board/smdk2440/lowlevel_init.S完成SDRAM的配置,修改board_init函数完成对S3C2440系统时钟的改动,修改board/s3c2440/flash.c完成对Nor Flash的支持,修改driver/nand/nand.c等驱动函数完成对Nand Flash等设备的支持,增加串口xmodem协议以便使用SecureCRT工具,增加“nand write”和“nand write.yaffs”等命令以烧写内核和 yaffs文件系统映像文件。 执行“make s3c2440_config”和“make all”命令,对U-boot重新编译,生成二进制映像文件u-boot.bin,将其烧写进Nor Flash。
3.1.2 内核的移植
首先配置内核,确保内核可以正确编译。修改顶层Makefile,将如下代码:
ARCH ?=$(SUBARCH)
CROSS_COMPILE?=
改为:
ARCH ?=arm
CROSS_COMPILE?=arm-linux-
根据U-boot对Flash的分区情况修改linux2.6.32/arch/
arm/mach-s3c2440/目录下的mach-smdk2440.c等文件。修改drivers/mtd/nand下的s3c2440.c文件和arch/arm/plats3c24xx下的common-smdk.c文件,将相关设备注册进内核,完成MTD分区。将yaffs2代码通过脚本文件patch-der.sh给内核打补丁的方式加入内核。用make menuconfig命令进入内核配置界面,对内核进行裁剪,然后执行“make dep”“make clean”“make zImage”命令生成内核映像文件zImage。当U-boot启动后就可以将内核烧写进Nand Flash。
3.1.3 根文件系统的移植
鉴于访问速度快的优点,选择YAFFS文件系统进行移植。利用Busybox-1.7.0来创建/bin、/sbin等目录下的可执行文件,并在/dev目录下创建必需的设备节点、在/etc目录下创建必需配置文件、在/lib目录下包含库文件。
在Busybox-1.7.0目录下执行“make menuconfig”命令可进入配置界面对Busybox进行相关配置。修改Busybox根目录的Makefile,使用交叉编译器,修改后为:
ARCH ?=arm
CROSS_COMPILE?=arm-linux-
然后执行 “make”命令编译Busybox,执行命令“make CONFIG_PREFIX=dir_path install”将其安装在指定目录dir_path下,再加载glibc库。创建etc目录下的etc/inittab、etc/init.d/rcS和etc/fstab文件,在/dev目录下静态创建各种节点,如/dev/mtdblock*、/dev/ttySAC*等。使用mdev初始化/dev和动态更新,修改etc/fstab和etc/init.d/rcS使内核启动时自动运行 mdev。 最 后 创 建 proc、mnt等 空 目 录 。 使 用 命 令“mkyaffsimage”创建YAFFS文件系统映像文件,进而烧写到目标板。
3.2.1 AD7490驱动的实现
AD7490作为字符设备,其读写是以字节为单位的,采用可加载模块化机制来开发设备驱动程序。首先对设备进行初始化,AD7490设备的初始化包括两部分,一是对SPI工作方式、各控制寄存器和模式寄存器等配置参数,并将PIO配置为引脚外设控制;二是完成设备驱动程序向Linux内核注册,调用函数register_chrdev()实现驱动模块的注册,调用函数unregiste_chrdev()实现驱动模块注销。
对于字符设备驱动程序是通过file_operations结构体中的成员函数实现对Linux的系统调用的。file_operations结构体如下:
static struct file_operations AD7490_fops={
.owner= THIS_MODULE;
.llseek= NULL;
.read= ad7490_rd;
.write= ad7490_wr;
.open= ad7490_open;
.release=ad7490_close;
};
构造file_operations结构中用到的各个成员函数,每个成员都对应一个系统调用,当用户操作设备文件时系统调用通过设备文件的主设备号找到相应设备驱动程序,再通过file_operations中相应函数指针,由该函数进行相应控制。
最后编写Makefile文件,执行“make”命令进行编译,生成可执行的.ko文件。编译成功后在目标板的映射目录下执行“insmod”命令进行动态加载,执行“rmmod”命令实现动态卸载。驱动程序加载后,还需编写A/D测试程序来验证驱动程序是否实现了相应功能。经验证,该驱动成功实现了预期功能。
3.2.2 IDT7028L驱动的实现
将双口RAM IDT7028L作为块设备编写驱动程序,利用一块系统内存作为缓冲区,当用户进程对设备进行读写请求时驱动程序先查看缓冲区内容,若能满足要求就返回相应数据,否则就调用相应的请求函数进行实际的I/O操作。
首先对双口RAM进行初始化,配置寄存器、分配地址资源并初始化数据结构、申请中断和注册设备[4]。调用函数register_blkdev()实现驱动注册,不使用请求队列而是使用制造请求的方式实现I/O请求处理,分配gendisk,初始化gendisk,添加gendisk到系统中,调用函数unregister_blkdev()实现驱动注销。
类似于字符设备驱动中的file_operations结构体,在块设备驱动中有block_device_operations结构体。定义结构体如下:
static struct block_device_operations IDT7028L_fops={.owner= THIS_MODULE;
.open= idt7028_open;
.release=idt7028_close;
.ioctl= idt7028_ioctl;
.media_changed= idt7028_media_changed;
.revalidate_disk=idt7028_revalidate_disk;
.getgeo=idt7028_getgeo;
};
实现block_device_operations结构体中的各个函数,编写Makefile文件,编译、加载该驱动模块。经测试程序验证,该驱动成功实现了预期功能。
文中研究了ARM+DSP架构的小型无人机飞行控制平台软件设计,分析了系统功能模块,给出了系统软件设计流程和关键技术的解决方法。实践证明该方案合理可行,软件可靠性高,系统具有抗干扰能力强、实时处理效果好的优点。
[1]张小林,赵宇博.新一代高性能无人机飞控系统的研究与设计[J].计算机测量与控制,2010,18(11):2588-2590.ZHANG Xiao-lin,ZHAO Yu-bo.Research and design of new generation high performance unmanned aerial vehicle flight controlsystem[J].Computer Measurement& Control,2010,18(11):2588-2590.
[2]王昱辉,雷金奎.基于SmartFusion的无人机飞行控制系统设计[J].现代电子技术,2012,35(10):129-131.WANG Yi-hui,LEI Jin-kui.Design of smartfusion-based flight control system forUAVs[J].Modern Electronics Technique,2012,35(10):129-131.
[3]杨小兵.基于双ARM的飞控计算机核心系统的研究与设计[D].南京:南京航空航天大学,2012.
[4]孙习波,阳富民.嵌入式系统双口RAM应用及驱动开发[J].计算机工程与设计,2005,26(8):2257-2259.SUN Xi-bo,YANG Fu-min.Application and driver development of dual-port ram in embedded system[J]. Computer Engineering and Design,2005,26(8):2257-2259.
[5]张绮文.ARM嵌入式常用模块与综合系统设计实例精讲[M].北京:电子工业出版社,2007.
[6]苏奎峰.TMS320F2812原理与开发[M].北京:电子工业出版社,2005.