硬件设计
CPU:S5PV210
内存:1G
闪存:SLC 1G Nand
网卡:DM9000,100M
串口:2个,调试和数据通信
USB:4个,外接U盘和移动硬盘
DS18B20:温度传感器(单总线接口 1-Wire)
ADC:模数转换器,分辨率10位或者12位
独立式按键:8个
LED灯:2个
蜂鸣器:1个
AT24C02:EEPROM存储器,容量256字节
LCD显示屏:分辨率800*480
电容触摸屏:GT811
软件设计
交叉编译器
采用官方交叉编译器;
编译器版本:4.4.6
编译器路径:/workdir/toolchain/opt/S5PV210-crosstools/4.4.6
设置交叉编译器环境变量:
sudo vim /etc/environment,在“PATH”中添加如下信息:
添加之前:/usr/local/sbin: /usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
添加之后:
/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/bin:/usr/local/sbin: /usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
启动交叉编译器环境变量
source /etc/environment
验证:arm-linux-gcc –v //查看是否是4.4.6版本编译器
UBOOT移植
采用官方UBOOT源码;
源码包u-boot_CW210_1.3.4.tar.bz2
源码存放路径:/opt/uboot/
源码操作:
解压源码:tar –xvf u-boot_CW210_1.3.4.tar.bz2
清除源码配置文件和目标文件:make distclean
配置源码:make cw210_config
make all
USB烧写固化u-boot.bin
Linux内核移植
采用官方Linux内核源码;
源码包Kernel_2.6.35.7_CW210_for_Linux_v1.0.tar.gz
源码存放路径:/opt/kernel
源码操作:
解压源码:tar –xvf Kernel_2.6.35.7_CW210_for_Linux_v1.0.tar.gz
清除源码配置文件和目标文件:cd /opt/kernel && make distclean
配置源码:cp config_CW210_linux_V1.0 .config
make menuconfig //保存退出
make zImage
cp arch/arm/boot/zImage /tftpboot/
根文件系统制作
采用busybox开源软件制作
busybox源码包:busybox-1.21.1.tar.bz2
源码存放目录:/opt/busybox/
源码操作:
解压源码:tar –jxvf busybox-1.21.1.tar.bz2
cd busybox-1.21.1
配置源码:make menuconfig
重新定制模块操作命令
Linux Module Utilities --->
[*] Simplified modutils (NEW) //去掉
[*] insmod //添加
[*] rmmod //添加、
[*] lsmod//添加
[*] modprobe //添加
[*] Blacklist support//添加
[*] depmod //添加
取出闪存flash操作命令
Miscellaneous Utilities --->
[*] nandwrite (NEW) //去掉
[*] nanddump (NEW) //去掉
保存退出
修改Makefile文件
vim Makefile
将CROSS_COMPILE ?= 修改为CROSS_COMPILE=arm-linux-
将ARCH ?= $(SUBARCH)修改为ARCH=arm
编译和安装 make && make install
默认安装当前目录的_install目录:ls _install
用file命令检查编译结果busybox可执行文件的属性:file _install/bin/busybox,打印信息如下:ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped //红色字体的内容必须为ARM,而不是intel X86
进入安装目录:cd _install
创建目录:
mkdir dev lib etc/init.dproc syshome mnt var tmp root -p
添加系统启动配置文件
vim etc/inittab //添加如下内容
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a –r
保存退出
添加文件系统配置文件
vim etc/fstab //添加如下内容
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
说明:sysfs,procfs,tmpfs都是虚拟文件系统,文件系统相关的信息存在内存中。
保存退出
添加系统启动服务配置脚本
vim etc/init.d/rcS //添加内容如下
/bin/mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev –s
保存退出
修改rcS文件权限
chmod 777 etc/init.d/rcS
添加 busybox运行时所需动态库
动态库添加原则:应用软件需要哪些动态库,就添加,不相关不做添加,以便节省闪存空间
应用软件编译连接需要的动态库在交叉编译器中获取:
动态库路径:/home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/
查看busybox可执行程序所需的动态库
arm-linux-readelf -a bin/busybox | grep "Shared" //提示信息如下:
0x00000001 (NEEDED) Shared library: [libm.so.6]
0x00000001 (NEEDED) Shared library: [libc.so.6]
可知需要动态库为:libc和libm两个动态库
拷贝所需动态库到根文件系统lib目录下
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "libc-*"-o -name "libc.so*" \) -exec cp -frd {} lib/ \; //拷贝标准C库
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "libm-*"-o -name "libm.so*" \) -exec cp -frd {} lib/ \; //拷贝数学运算库
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "ld-*"\) -exec cp -frd {} lib/ \; //拷贝动态链接库
测试制作好的根文件系统
备份原有的根文件系统rootf:mv /opt/rootfs /opt/rootfs_bak
cp _install /opt/rootfs –frd //将安装制作好的根文件系统_install拷贝为/opt/rootfs
注意添加NFS网络服务的支持:sudo vim /etc/exports 添加如下语句:
/opt/rootfs *(rw,sync,no_root_squash)
保存退出
重启网络服务sudo /etc/init.d/nfs-kernel-server restart
uboot中设置NFS网络启动参数
setenv bootargs root=/dev/nfs nfsroot=192.168.1.8:/opt/rootfs ip=192.168.1.110:192.168.1.8:192.168.1.1:255.255.255.0::eth0:on init=/linuxrc console=ttySAC0,115200
saveenv
重启开发板测试挂接制作的rootfs
查看根文件系统的大小: du /opt/rootfs –lh (一般情况下为3.2M)
tslib移植
tslib作用:
在采用触摸屏的移动终端中,触摸屏性能的调试是个重要问题之一,因为电磁噪声的缘故,触摸屏容易存在点击不准确、有抖动等问题。tslib是一个开源的程序,能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能,通常作为触摸屏驱动的适配层,为上层的应用(例如QT)提供了一个统一的接口。
tslib源码包:tslib.tar.gz
源码存放目录:/opt/project/source/
源码移植:
进入源码目录:cd /opt/project/source
解压源码: tar –xvf tslib.tar.gz
cd tslib
执行./autogen.sh 生成配置文件configure
执行echo "ac_cv_func_malloc_0_nonnull=yes"> tmp.cache
执行./configure --host=arm-linux --cache-file=tmp.cache --prefix=/opt/project/tslib //指定安装的目录为/opt/project/tslib目录
执行make && make install //编译安装
编译安装成果: cd /opt/project/tslib && ls –lh 提示信息如下:
etc bin lib include //生成四个目录
etc:用于配置tslib
bin:tslib的测试程序,运行在ARM开发板上
lib:动态库,供QT使用,用于获取坐标等信息
include:头文件,用于编译源码
修改tslib的配置文件ts.conf
vim etc/ts.conf //打开配置文件,进行如下操作:
在“module pthres pmin=1”前一行添加“module_raw input”语句 (需要注意的是module开头的几行前面不能有空格. )
开发板测试tslib:
编译tslib生成目标文件存放目录:/opt/rootfs/home/tslib/
mkdir /opt/rootfs/home/tslib/
cp etc /opt/rootfs/home/tslib/ -frd //拷贝运行时配置文件
cp bin /opt/rootfs/home/tslib/ -frd //拷贝触摸屏测试软件
cp lib /opt/rootfs/home/tslib/ -frd //拷贝tslib动态库文件
连接触摸屏和开发板,获取触摸屏设备文件
开发板上执行hexdump /dev/input/event0,然后用手指点击触摸屏,看串口终端是否有打印信息,如果没有,event0不是触摸屏的设备文件,再执行:hexdump /dev/input/event1,同样点击屏幕看是否有打印信息,如果没有,再次更换设备文件为event2,直到找到触摸屏的设备文件,例如:hexdump /dev/input/event3,有打印信息,至此触摸屏的设备文件为/dev/input/event3.
添加使用tslib时的环境变量
vim /opt/rootfs/etc/profile 添加如下内容:
export TSLIBDIR=/home/tslib
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event3 //根据上一步骤找触摸屏的设备文件,不能有错!
export TSLIB_CALIBFILE=$TSLIBDIR/etc/pointercal
export TSLIB_CONFFILE=$TSLIBDIR/etc/ts.conf
export TSLIB_PLUGINDIR=$TSLIBDIR/lib/ts
export PATH=/home/tslib/bin:$PATH
export LD_LIBRARY_PATH=/home/tslib/lib:$LD_LIBRARY_PATH
保存退出
重启开发板
添加使用tslib时的标准系统库(libdl)
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "libdl-*"-o -name "libdl.so*"\) -exec cp -frd {}/opt/rootfs/lib/ \;重启开发板,进行触摸屏校准
开发板运行: ts_calibrate //此时屏幕有一个十字光标,用手指精确点击光标,点击光标5次,完成校准,生成一个校准文件保存在home/tslib/etc/pointercal
开发板运行:ts_test //点击屏幕”Draw”,写字,画画
至此tslib移植成功,触摸屏测试成功!
QT移植
QT介绍:
移植QT目的:
移植注意事项:必须先移植好tslib
源码包:qt-everywhere-opensource-src-4.8.4.tar.gz
源码包存放目录:/opt/project/source/
源码移植:
cd /opt/project/source/
解压源码
tar –xvf qt-everywhere-opensource-src-4.8.4.tar.gz
mv qt-everywhere-opensource-src-4.8.4 qt_src
cd qt_src
修改配置文件:
vim mkspecs/qws/linux-arm-g++/qmake.conf 操作如下:
原先的内容:
QMAKE_CC = arm-linux-gcc
QMAKE_CXX = arm-linux-g++
QMAKE_LINK = arm-linux-g++
QMAKE_LINK_SHLIB = arm-linux-g++
修改为: //添加tslib动态库的支持
QMAKE_CC = arm-linux-gcc -lts
QMAKE_CXX = arm-linux-g++ -lts
QMAKE_LINK = arm-linux-g++ -lts
QMAKE_LINK_SHLIB = arm-linux-g++ -lts
编译源码:
下载build.sh编译配置脚本,放置在源码目录/opt/project/source/qt_src中
执行./build.sh
会提示输入"c"或者"o",选择"o"开始配置
make //编译,大约3小时
make install //安装
交叉编译QT,生成的目标文件自动安装在/opt/project/qt目录中
ls /opt/project/qt/ 信息如下
bin include lib mkspecs plugins translations
安装中文字体库
字体库文件:wqy-zenhei.ttc
删除QT自带字体库
rm /opt/project/qt/lib/fonts/* -fr
安装中文字体库
cp wqy-zenhei.ttc /opt/project/qt/lib/fonts/
安装编译出来的QT库到跟文件系统/opt/rootfs中
QT库的存放目录:/opt/rootfs/home/qt
mkdir /opt/rootfs/home/qt
拷贝QT库
cp /opt/project/qt/lib /opt/rootfs/home/qt –frd
cp /opt/project/qt/plugins /opt/rootfs/home/qt -frd
添加QT运行时的环境变量
vim /opt/rootfs/etc/profile, 添加如下内容
export QTDIR=/home/qt
export QWS_MOUSE_PROTO="Tslib:/dev/input/event3" #dev/input/event3为触摸屏设备文件
export QWS_SIZE=800X480
export QT_QWS_FONTDIR=$QTDIR/lib/fonts
export QT_PLUGIN_PATH=$QTDIR/plugins
exportQWS_DISPLAY="LinuxFB:mmWidth180:0"
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
保存退出,重启开发板
执行env命令,查看环境变量是否生效
添加QT运行时的系统库
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "libpthread-*" -o -name "libpthread.so*" \) -exec cp -frd {} /opt/rootfs/lib/ \;
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "libstdc++-*" -o -name "libstdc++.so*" \) -exec cp -frd {} /opt/rootfs/lib/ \;
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "librt-*" -o -name "librt.so*" \) -exec cp -frd {} /opt/rootfs/lib/ \;
find /home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/arm-concenwit-linux-gnueabi/lib/ \( -name "libgcc_s-*" -o -name "libgcc_s.so*" \) -exec cp -frd {} /opt/rootfs/lib/ \;
开发板上测试QT
测试源码包:美女摇奖游戏 game.tar.bz2
源码存放目录:/opt/project/game
可执行文件存放目录:/opt/rootfs/home/apptest/
mkdir /opt/project/game
cd /opt/project/game
tar –jxvf game.tar.bz2
cd game
清除源码目标和配置文件:make clean
生成pro工程文件:/opt/project/qt/bin/qmake –project //注意不要直接qmake,为什么?
生成Makefile文件:/opt/project/qt/bin/qmake
编译:make
创建可执行文件存放目录:mkdir /opt/rootfs/home/apptest
cp game /opt/rootfs/home/apptest
开发板上运行: /home/apptest/game –qws //看QT游戏能否启动
驱动开发
需要开发的驱动如表所示:
硬件对象 |
2个LED |
1个蜂鸣器 |
1个DS18B20温度传感器 |
1个ADC |
8个按键 |
1个AT24C02存储器 |
功能 |
告警指示 |
报警 |
采集室内温度 |
用于采样电压模拟信号,转换电压值作为模拟烟雾浓度 |
用于玩游戏和模拟红外传感器 |
存储软件和硬件版本信息 |
驱动文件名 |
led_drv.c |
beep_drv.c |
ds18b20_drv.c |
adc_drv.c |
btn_drv.c |
at24c02_drv.c |
源码存放路径 |
/opt/project/drivers/led |
/opt/project/drivers/beep |
/opt/project/drivers/ds18b20 |
/opt/project/drivers/adc |
/opt/project/drivers/btn |
/opt/project/drivers/eeprom |
ko目标存放目录 |
/opt/rootfs/home/drivers |
封装底层硬件操作库函数
底层硬件库函数的作用:用于图形界面QT调用库函数间接操作访问硬件设备,是连接QT和设备的桥梁
软件操作流程:
LED设备底层硬件操作库实现过程:
用户需求:开发板运行QT软件,能够开关灯
源码存放目录:/opt/project/hwlib/led
mkdir /opt/project/hwlib/led -p
编写头文件led.h,源码如下:
#ifndef __LED_H
#define __LED_H
#ifdef __cplusplus
extern "C" {
#endif
/*头文件*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
/*调试宏*/
#define DEBUG
#ifdef DEBUG
#define pr_debug(fmt, ...) printf(fmt, ##__VA_ARGS__) //打开调试信息
#else
#define pr_debug(fmt, ...) //关闭调试信息
#endif //以后打印不用printf用pr_debug
/*设备文件名*/
#define LED_DEVFILE_NAME "/dev/myled"
/*LED数据结构
应用软件利用此数据结构进行访问设备
*/
struct led_cmd {
unsigned char whichled; //指定哪个灯,第一个灯此值为1,第二个灯此值为2
unsigned char cmd;//亮,灭命令;开灯此值设置为1,关灯此值设置为0
unsigned char reserved[2];
};
/*LED控制命令宏*/
#define LED_ON 0x100001
#define LED_OFF 0x100002
/*
函数功能:打开LED设备
参数:无
返回值:打开设备成功,返回设备文件描述符fd;失败返回-1
*/
extern int led_open(void);
/*
函数功能:关闭LED设备
参数:
@fd:设备文件描述符
返回值:无
*/
extern void led_close(int fd);
/*
函数功能:控制LED亮,灭
参数:
@fd:设备文件描述符;
@cmd:控制LED开关命令
返回值:开,关灯结果,操作成功,返回0,否则返回-1
*/
extern int led_config(int fd, struct led_cmd *cmd);
#ifdef __cplusplus
}
#endif
#endif
编写库函数实现源文件led.c,源码如下:
#include "led.h"
int led_open(void)
{
int fd = open(LED_DEVFILE_NAME, O_RDWR);
if (fd < 0) {
pr_debug("open led device failed.\n");
return -1;
}
pr_debug("open led device successfully!\n");
return fd;
}
void led_close(int fd)
{
pr_debug("close led device...\n");
close(fd);
}
int led_config(int fd, struct led_cmd *ledctrl)
{
int ret;
if (fd < 0) {
pr_debug("fd is invalid.\n");
return -1;
}
if (ledctrl == NULL) {
pr_debug("ledctrl is invalid.\n");
return -1;
}
if (ledctrl->whichled != 1 && ledctrl->whichled != 2) {
pr_debug("whichled is invalid.\n");
pr_debug("whichled value must be 1 or 2\n");
return -1;
}
if (ledctrl->cmd != 1 && ledctrl->cmd != 0) {
pr_debug("cmd is invalid.\n");
pr_debug("cmd value must be 1 or 0\n");
return -1;
}
if (ledctrl->cmd == 1)
ret = ioctl(fd, LED_ON, &ledctrl->whichled);
else
ret = ioctl(fd, LED_OFF, &ledctrl->whichled);
if (ret == -1) {
pr_debug("ioctl led device failed.\n");
}
pr_debug("ioctl led device successfully!\n");
return ret;
}
制作为动态库:
arm-linux-gcc -shared -fpic -o libled.so led.c led.h
动态库存放目录:/opt/rootfs/home/applib
mkdir /opt/rootfs/home/applib
cp libled.so /opt/rootfs/home/applib/
编写库函数测试用例ledlib_test.c,源码如下:
#include "led.h"
int main(int argc, char *argv[])
{
int fd;
struct led_cmd ledctrl;
if (argc != 3) {
printf("usage:\n %s <on|off><1|2>\n", argv[0]);
return -1;
}
fd = led_open();
if (fd < 0)
return -1;
ledctrl.whichled = strtoul(argv[2], NULL, 0);
if (!strcmp(argv[1], "on")) {
ledctrl.cmd = 1;
} else {
ledctrl.cmd = 0;
}
if (led_config(fd, &ledctrl) == -1)
return -1;
led_close(fd);
return 0;
}
编译测试用例:
arm-linux-gcc -o ledlib_test ledlib_test.c -L/opt/project/hwlib/led –lled
测试用例可执行文件存放目录:/opt/rootfs/home/apptest
mkdir /opt/rootfs/home/apptest
cp libled_test /opt/rootfs/home/apptest
添加动态库环境变量:
vim /opt/rootfs/etc/profile ,在文件最后添加如下内容:
export LD_LIBRARY_PATH=/home/applib:$LD_LIBRARY_PATH
重启开发板
运行测试用例:
/home/apptest/ledlib_test on 1 //开第一个灯
基于QT图形界面实现开关灯
图形界面包含操作元素:一个开灯按钮,一个关灯按钮
界面大小:800*480
界面图标:添加至/opt/project/ehome/images
功能:点击图形界面按钮,实现开关灯操作
源码存放目录:/opt/project/ehome
可执行文件ehome存放目录:/opt/rootfs/home/appbin
Tarena虚拟机安装QT开发环境
QT开发工具包:qt-ubuntu.tar.bz2
或者在windows下安装QT开发工具:qt-opensource-windows-x86-mingw482_opengl-5.3.2.exe
下载安装即可
ubuntu安装QT开发环境步骤:
mkdir /home/tarena/qt/
cp qt-ubuntu.tar.bz2 /home/tarena/qt
tar –xvf qt-ubuntu.tar.bz2
sudo dpkg –i *
打开qtcreator开发工具:
创建ehome工程
添加开,关按钮控件和背景图片,参看视频
添加硬件库函数使用的头文件
添加文件描述m_fd_led定义
构造函数中可以打开设备
槽函数中开关设备
具体参看视频
交叉编译:
cd /opt/project/ehome
/opt/project/qt/bin/qmake –project //生成工程文件,只需做一次,以后不需要再生成
修改工程文件,添加动态库的支持
vim /opt/project/ehome/ehome.pro
添加如下内容:
INCLUDEPATH += /opt/project/hwlib/led //头文件
LIBS += -L/opt/project/hwlib/led –lled //动态库
其他库依次按此法添加,例如beep:
INCLUDEPATH += /opt/project/hwlib/beep //头文件
LIBS += -L/opt/project/hwlib/beep –lbeep //动态库
保存退出
执行/opt/project/qt/bin/qmake 生成Makefile文件
make 编译
cp /opt/project/ehome/ehome /opt/rootfs/home/appbin
开发板测试/home/appbin/ehome –qws //实现开关灯
统软件部署
系统软件组成部分:
u-boot.bin:系统启动软件
zImage:内核软件
根文件系统rootfs:根文件系统,包含库,命令,配置文件等
userdata目录:包含用户软件,驱动模块,脚本,自己封装的动态库,测试用例,应用软件
注意:rootfs和userdata是两个目录,最后需要制作为镜像文件
rootfs根文件系统目录组成部分:
lib:存放系统标准库,不包含QT库,tslib库和自己封装的库
etc:系统启动配置文件,fstab,profile,inittab,rcS
bin,sbin,usr:系统运行命令
home:作为nandflash分区的挂节点
mnt:作为U盘或者SD卡挂节点
dev:存放设备文件
proc,sys,tmp,var:作为procfs,sysfs虚拟文件系统的挂节点
userdata用户数据软件目录组成部分:
userdata目录只包含自己产品软件内容
目录位置:/opt/project/
创建目录:mkdir /opt/project/userdata
创建userdata目录内容:
cd /opt/project/userdata
mkdir qt tslib appbin applib apptest scripts drivers
各个目录说明:
qt目录:包含移植生成的库文件
cp /opt/project/qt/lib qt/ -frd //qt标准库
cp /opt/project/qt/plugins qt/ -frd //图形处理库
tslib目录:包含移植tslib生成的库,命令和配置文件
cp /opt/project/tslib/bin tslib/ -frd//触摸屏校准测试工具
cp /opt/project/tslib/etc tslib/ -frd //配置文件
cp /opt/project/tslib/lib tslib/ -frd //动态库
appbin目录:存放ehome可执行文件
cp /opt/project/ehome/ehome appbin/
apptest目录:存放测试用例
find /opt/project/hwlib/ -name *_test -exec cp {} apptest/ \;
applib目录:存放自己制作封装的动态库
find /opt/project/hwlib/ -name *.so -exec cp {} applib/ \;
drivers目录:存放驱动目标文件
find /opt/project/drivers/ -name *.ko -exec cp {} drivers/ \;
scripts目录:存放应用软件启动命令
mv /opt/rootfs/etc/profile scripts/run.sh //复制profile脚本文件
chmod 777 scripts/run.sh
vim scripts/run.sh 在文件最后添加如下内容:
#自动加载模块
find /home/drivers/ -name *.ko -exec insmod {} \;
#自动运行可执行文件
/home/appbin/ehome -qws & //后台运行
根文件系统rootfs相关配置文件修改:
vim /opt/rootfs/etc/profile 添加如下内容
. /home/scripts/run.sh #注意“.”后要跟空格键
保存退出
利用NFS网络文件系统测试userdata是否能使用,是否能够实现软件自启动:
备份原先根文件系统rootfs/home/下的内容:
mv /opt/rootfs/home /opt/project/home_bak
cp /opt/project/userdata /opt/rootfs/home -frd
cd /opt/rootfs/home/
ls //可以看到userdata中的各个目录
重启开发板
看LCD是否显示ehome的界面
ps //查看进程信息
env //查看qt,tslib的环境变量是否生效
lsmod //查看驱动模块是否加载
如果测试成功,说明userdata没有问题,将/opt/rootfs/home/下的内容删除
rm /opt/rootfs/home/* -fr
至此rootfs和userdata彻底分开,根文件系统和用户软件彻底分开
将rootfs和userdata两个目录分别制作为镜像文件进行烧写:
镜像文件对应文件系统类型的选择,采用:
rootfs制作为rootfs.img镜像,采用的文件系统类型为cramfs,只读,用于保护根文件系统;
userdata制作为userdata.img镜像,采用的文件系统类型为yaffs2,可读写;
配置linux内核,支持两种文件系统:
cd /opt/kernel
make menuconfig
File Systems->
[*] Miscellaneous filesystems --->
<*>Compressed ROM file system support (cramfs) //支持cramfs文件系统
File Systems->
[*] Miscellaneous filesystems --->
<*> YAFFS2 file system support //已经支持
保存退出
make zImage
cp arch/arm/boot/zImage /tftpboot/
重启开发板
cat /proc/filesystems //查看是否支持cramfs和yaffs2
将rootfs和userdata分别制作为cramfs和yaffs2文件系统镜像:
目录 镜像文件 文件系统类型
rootfs rootfs.img cramfs
userdata userdata.img yaffs2
rootfs.img镜像制作步骤:
cd /opt/
mkfs.cramfs rootfs rootfs.img
cp rootfs.img /tftpboot
userdata.img镜像制作步骤:
从ftp下载mkyaffs2image工具到虚拟机中:
sudo cp mkyaffs2image /usr/sbin
sudo chmod 777 /usr/sbin/mkyaffs2image
cd /opt/project
mkyaffs2image userdata userdata.img
chmod 666 userdata.img
cp userdata.img /tftpboot
至此四个软件包都准备就绪:
u-boot.bin,zImage,rootfs.img,userdata.img
存放目录:/tftpboot
nandflash分区规划,用于部署镜像文件:
0----------2M----------7M----------17M------------剩余
uboot zImage rootfs.img userdata.img
注意:镜像文件大小要小于各个分区的大小!请确认!
修改nandflash的分区表
cd /opt/kernel
vim drivers/mtd/nand/s3c_nand.c 找到分区表,修改为如下分区表信息:
struct mtd_partition s3c_partition_info[ ] = {
//第一分区信息
{
.name = "uboot", //分区的名称
.offset = (0), //分区的起始地址
.size = (SZ_1M*2), //分区的大小
},
//第二分区信息
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND, //追加
.size = (SZ_1M*5),
},
//第三分区信息
{
.name = "rootfs",
.offset = MTDPART_OFS_APPEND,
.size = (SZ_1M*10),
},
//第四分区信息
{
.name = "userdata",
.offset =MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL //剩余
}
};
保存退出
make zImage
cp arch/arm/boot/zImage /tftpboot
重启开发板
cat /proc/mtd //查看分区表
ls /dev/mtd* -lh //查看字符设备文件和块设备文件
/dev/mtd0:第一个分区的字符设备文件
/dev/mtdblock0:第一个分区的块设备文件
将zImage,rootfs.img,userdata.img烧写到nand上:
烧写方法有两种,一种通过uboot,另一种通过mtd工具
利用uboot来进行烧写的步骤:
烧写zImage:
tftp 50008000 zImage
nand erase 200000 500000
nand write 50008000 200000 500000
烧写rootfs.img
tftp 50008000 rootfs.img
nand erase 700000 a00000
nand write 50008000 700000 a00000
烧写userdata.img
tftp 50008000 userdata.img
nand erase 1100000
nand write.yaffs 50008000 1100000 $filesize
或者
nand write.yaffs 50008000 1100000 $(filesize)
设置本地启动的参数信息:
setenv bootcmd nand read 50008000 200000 500000 \; bootm 50008000
setenv bootargs root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200 rootfstype=cramfs
saveenv
重启开发板,看rootfs是否能挂接,所在第三块分区
验证根文件系统是否为只读:
cd /
mkdir helloworld //看是否能创建目录
手动挂接存放userdata数据的第四块分区到根文件系统home目录:
在开发板上执行:
mount -t yaffs2 /dev/mtdblock3 /home
mount //看是否挂接成功
cd /home //进入第四块分区
ls //查看第四块分区的内容,是否有之前userdata目录的内容
. /home/scripts/run.sh //手动运行软件启动脚本,"."后跟一个空格
自动挂接存放userdata数据的第四块分区到根文件系统home目录:
vim /opt/rootfs/etc/init.d/rcS,在文件最后添加:
mount -t yaffs2 /dev/mtdblock3 /home
ifconfig eth0 192.168.1.110
ifcofig lo 127.0.0.1
保存退出
重新制作rootfs为rootfs.img镜像,然后重新烧写
重启开发板,看软件是否能够实现自启动
系统启动完毕,还可以手动挂接虚拟机的网络文件系统,进行软件调试:
一旦系统自启动完毕,进入开发板的终端,输入挂接命令:
mount –t nfs –o nolock 192.168.1.8:/opt/rootfs /mnt/ //挂接虚拟机的网络文件系统,挂接到开发板的mnt目录,以后开发板访问mnt目录就是在访问虚拟的/opt/rootfs目录,实现远程的软件测试,不需要为了更新一个软件而重新烧写镜像文件!
cd /mnt/
ls
以更新ehome和rootfs.img为例:
首先将要更新的ehome和rootfs.img拷贝到/opt/rootfs
cp /opt/project/ehome/ehome /opt/rootfs
cp /opt/rootfs.img /opt/rootfs
开发板执行mount挂接网络;
cp /mnt/ehome /home/appbin/ //更新ehome
flash_erase /dev/mtd2 0 0
nandwrite –p /dev/mtd2 /mnt/rootfs.img //更新rootfs.img
利用mtd工具烧写u-boot.bin,zImage,rootfs.img,userdata.img镜像文件:
mtd烧写工具:flash_erase,nandwrite,nanddump等