嵌入式linux环境搭建-jz2440开发板

总览

环境及结论

  • 大环境的搭建思路如下:

    • gateway ip 10.0.0.138
    • PC windows: win10 64bit, ip 10.0.0.98
    • PC linux(最终版本): ubuntu desktop 16.04 32 bit, ip 10.0.0.100
    • Embedded Linux: jz2440v3 ip 10.0.0.111
  • 用 jLink 或 openJtag 烧录 uboot

  • 基于nfs服务烧录kernal

  • 使用nfs加载文件系统

  • 编译一个驱动模块并运行

  • 以上, 完成jz2440的环境搭建

  • 最新补充(2017-09-30). 根据实践, 建议的方式如下:

    • linux下使用samba实现文件共享, Ubuntu下配置支持Windows访问的samba共享
    • linux下安装NFS服务器, 便于让开发板linux通过网络加载文件系统. Ubuntu 16.04安装配置NFS
    • 如果开发板联网不方便, 则建议使用 uboot+dnw(linux下) 的方式进行烧录, 也非常方便.

PC linux 建议使用Ubuntu 32bit, 交叉编译工具必须使用 arm-linux-gcc-3.4.5-glibc-2.3.6

设置静态ip

uboot 设置静态ip

# 开发板 uboot

# 设置ip地址, 在OpenJTAG> 提示符下
set ipaddr 10.0.0.111 # 设置开发板的ip地址
set serverip 10.0.0.138
save # 保存
printenv # 打印环境变量, 查看设置结果

嵌入式linux下设置静态ip

# 开发板 shell

# 手工修改ip地址
ifconfig eth0 10.0.0.111 netmask 255.255.255.0

# 永久修改IP地址
vi /etc/init.d/rcS # 可以在windows下直接改
# ===== 文件内容, 添加如下内容: =====
ifconfig eth0 10.0.0.111
# ===== 结束修改, 保存退出vi =====

uboot 的编译和烧录

uboot 打补丁和编译

# ubuntu shell

tar xjvf u-boot-1.1.6.tar.bz2 # 解压uboot源码
cd u-boot-1.1.6 # 进入uboot源码目录
patch -p1 < ../u-boot-1.1.6_jz2440.patch # 打补丁文件, p1表忽略patch文件内的1层目录
# tar cjvf u-boot-1.1.6-patched.tar.bz2 dir # 可选, 压缩备份一下

# pwd = u-boot-1.1.6
make clean
make 100ask24x0_config # uboot config文件
make # uboot 编译, 得到u-boot.bin文件
# 不能用sudo make, 否则就是报错

uboot 的烧录和升级

一般而言, 开发板出厂时已经烧录好可用的uboot.
只要烧录好了uboot, 就不再需要 jLink 或 openJtag 这类烧录工具了!
若要烧录uboot, 可用 jLink 或 openJtag 烧录到norflash中, 略过不表.

基于dnw升级uboot:

# 开发板 uboot

# 打开 jz2440 开发板串口终端, 启动时输入空格键, 进入如下菜单
##### 100ask Bootloader for OpenJTAG #####
[n] Download u-boot to Nand Flash
...
Enter your selection: n # 输入n, 烧录uboot
USB host is connected. Waiting a download. # 提示连接成功



# 切换到 Ubuntu 终端, 输入
# pwd = ./u-boot-1.1.6 # 确保在 uboot 源码路径下
sudo dnw u-boot.bin # 使用dnw烧录uboot



# 要烧录其它如 kernel, filesystem 整个流程和 dnw 指令都是一样的. 譬如:
sudo dnw ./arch/arm/boot/uImage # 先输入k, 烧录kernel
sudo dnw fs_qtopia_ts.yaffs2 # 先输入y, 烧录文件系统
sudo dnw leds_0x31000000.bin 0x31000000 # 先输入d, 烧录代码到SDRAM并运行

或者基于nfs服务升级uboot, 指令较为复杂(dnw方式只是自动化运行这些指令了.):

# 开发板 uboot
# 要使用nfs功能, 必须正确设置uboot的ip地址
# 将 .../u-boot-1.1.6/u-boot.bin 拷贝到 /jz2440/

# uboot烧录: 用 jLink 烧录成功到nor flash后, 就可以用nfs进行升级或再烧录到nand flash中.
# uboot升级: 在OpenJTAG> 提示符下
nfs 30000000 10.0.0.98:/jz2440/u-boot.bin # nfs 加载 uboot 固件到ram中 (0x30000000是sdram的地址)
nand erase bootloader # 擦除 falsh 的 bootloader 区
nand write.jffs2 30000000 bootloader # 烧录 uboot (ram->flash)

# uboot 运行时, 已经被加载到ram中, 因此可以用uboot的nfs功能来擦除和升级flash中的uboot
# 看上去实在自己运行自己, 本质上是ram中的uboot读写flash内容.

kernel 的编译和烧录

kernel 打补丁和编译

# ubuntu shell

tar xjvf linux-2.6.22.6.tar.bz2 # 解压kernel源码
cd linux-2.6.22.6 # 进入kernel源码目录
patch -p1 < ../linux-2.6.22.6_jz2440.patch # 打补丁文件, p1表忽略patch文件内的1层目录

# pwd = linux-2.6.22.6
cp ../4.3寸LCD_mach-smdk2440.c arch/arm/mach-s3c2440/mach-smdk2440.c # 替换为4.3寸屏源码
make clean # 清空 (先清空再在SI内查看)
cp config_ok .config # 设置config文件
make uImage # 编译获得内核image



# 可能在make时, 提示如下错误信息. 原因是新版的make对老的Makefile规则不兼容
Makefile:1449: *** mixed implicit and normal rules. Stop.

vim Makefile
# 416行 config %config: scripts_basic outputmakefile FORCE
# 改为 -> %config: scripts_basic outputmakefile FORCE
# 1449行 / %/: prepare scripts FORCE
# 改为 -> %/: prepare scripts FORCE
# 保存后重新编译即可.

使用 dnw 烧录 kernel

网路配置比较繁琐和复杂, windows的dnw需要安装驱动, 而且会有问题!
因此最便捷的方式就是基于uboot, 使用 linux 的 dnw.
确保链接了开发板的串口和usb口, 并把usb口关联到Ubuntu上.

# 开发板 uboot

# 打开 jz2440 开发板串口终端, 启动时输入空格键, 进入如下菜单
##### 100ask Bootloader for OpenJTAG #####
[n] Download u-boot to Nand Flash
[o] Download u-boot to Nor Flash # 如果是Nand Flash启动的话,这个菜单项没有
[k] Download Linux kernel uImage
[j] Download root_jffs2 image
[y] Download root_yaffs image
[d] Download to SDRAM & Run
...

Enter your selection: k # 输入k, 烧录 kernel
USB host is connected. Waiting a download. # 提示连接成功



# 切换到 Ubuntu 终端, 输入
# pwd = ./linux-2.6.22.6 # 确保在 kernel 源码路径下
sudo dnw ./arch/arm/boot/uImage # 输入dnw指令, 指明烧录文件
# DNW usb device found! # 开始烧录
# 这样就成功把 kernel 烧录到 jz2440 开发板中了.



# 要烧录其它如 uboot, filesystem, 整个流程和 dnw 指令都是一样的. 譬如:
sudo dnw u-boot.bin # 先输入n, 烧录uboot
sudo dnw fs_qtopia_ts.yaffs2 # 先输入y, 烧录文件系统
sudo dnw leds_0x31000000.bin 0x31000000 # 先输入d, 烧录代码到SDRAM并运行

使用 nfs 烧录 kernel

如果配置好网路, 建议使用 nfs 进行烧录

# 开发板 uboot
# 要使用nfs功能, 必须正确设置uboot的ip地址
# 将 .../linux-2.6.22.6/arch/arm/boot/uImage 拷贝到 /jz2440/

# kernel: 在OpenJTAG> 提示符下
nfs 30000000 10.0.0.98:/jz2440/uImage # nfs 加载 kernel 固件到ram中 (0x30000000是sdram的地址)
nand erase kernel # 擦除 falsh 的 kernel 区
nand write.jffs2 30000000 kernel # 烧录 kernel (ram->flash)

加载 filesystem

提供了如下几个文件系统

  1. fs_mini.tar.bz2 是最小的根文件系统. 不推荐, 需要手工建立设备节点
  2. fs_mini_mdev.tar.bz2 是最小的根文件系统. 推荐, 启动后使用mdev自动建立设备节点
  3. fs_qtopia.tar.bz2 是JZ2440使用的支持触摸屏的根文件系统
  4. fs_xwindow.tar.bz2 是基于X的根文件系统

这里以 fs_mini_mdev.tar.bz2 为例进行开发. 无UI, shell操作.

制作 filesystem

# ubuntu shell

sudo tar xjf fs_mini_mdev.tar.bz2 # 解压缩, 必须加sudo
mkyaffs2image fs_mini_mdev fs_mini_mdev.yaffs # 生成文件系统 fs_mini_mdev.yaffs

使用 dnw 烧录 filesystem

# 开发板 uboot

# 打开 jz2440 开发板串口终端, 启动时输入空格键, 进入如下菜单
##### 100ask Bootloader for OpenJTAG #####
[n] Download u-boot to Nand Flash
[o] Download u-boot to Nor Flash # 如果是Nand Flash启动的话,这个菜单项没有
[k] Download Linux kernel uImage
[j] Download root_jffs2 image
[y] Download root_yaffs image
[d] Download to SDRAM & Run
...

Enter your selection: y # 输入k, 烧录 root_yaffs
USB host is connected. Waiting a download. # 提示连接成功



# 切换到 Ubuntu 终端, 输入
sudo dnw fs_mini_mdev.yaffs2 # 输入dnw指令, 指明烧录文件
# DNW usb device found! # 开始烧录
# 这样就成功把文件系统烧录到 jz2440 开发板中了.


# 要烧录其它如 uboot, kernel, 整个流程和 dnw 指令都是一样的. 譬如:
sudo dnw u-boot.bin # 先输入n, 烧录uboot
sudo dnw ./arch/arm/boot/uImage # 先输入k, 烧录kernel
sudo dnw leds_0x31000000.bin 0x31000000 # 先输入d, 烧录代码到SDRAM并运行

使用 nfs 烧录 filesystem

# 开发板 uboot
# 要使用nfs功能, 必须正确设置uboot的ip地址
# 将 .../fs_mini_mdev.yaffs 拷贝到 /jz2440/

# fs: 在OpenJTAG> 提示符下 (实际不用, 用nfs加载fs)
nfs 30000000 10.0.0.98:/jz2440/fs_mini_mdev.yaffs2
nand erase root
nand write.yaffs 30000000 260000 ‭88AC40‬ # 要算文件大小, 很麻烦.

# 设置为从flash启动 file system. 在OpenJTAG> 提示符下
set bootargs noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0
save
reset

直接加载 nfs 文件系统

# 开发板 uboot
# 要使用nfs功能, 必须正确设置uboot的ip地址

# uboot, 从NFS加载文件系统. 在OpenJTAG> 提示符下
set bootargs noinitrd root=/dev/nfs nfsroot=10.0.0.98:/fs ip=10.0.0.111:10.0.0.98:10.0.0.138:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
# (简化ip: 'set bootargs noinitrd root=/dev/nfs nfsroot=10.0.0.98:/fs ip=10.0.0.111 init=/linuxrc console=ttySAC0' 也可以工作)
save # 保存修改
reset # 重启. (稍后再重启, 先修改好 filesystem 内的初始化文件)

# 参数简要说明:
# 'root=/dev/nfs' 加载nfs文件系统
# 'nfsroot=10.0.0.98:/fs' nfs文件系统的来源, 此处是由win10当nfs服务器, 共享出/fs文件夹
# 'ip=10.0.0.111:10.0.0.98:10.0.0.138:255.255.255.0::eth0:off' 分别表示:
# ip= 开发板ip : nfs服务器ip: 网关ip : 子网掩码 :: 开发板网口 : off

加载其它nfs文件

为了方便开发调试, 可以加载其它nfs文件到开发板linux中

# 开发板 shell

# 开发板手动加载nfs文件
mkdir /mnt/jz2440
mount -t nfs -o nolock,vers=2 10.0.0.98:/jz2440 /mnt/jz2440

// 开机自动加载nfs文件
mkdir /mnt/jz2440
vi /etc/init.d/rcS # 可以在windows下直接改
# ===== 文件内容, 末尾加入如下语句: =====
# mkdir /mnt/jz2440 # 建议手动创建, 需要容错的话, 可加上这句
mount -t nfs -o nolock,vers=2 10.0.0.98:/jz2440 /mnt/jz2440
ln -s /mnt/jz2440 /jz2440
# ===== 结束修改, 保存退出vi =====

基于 fs_mini_mdev 制作 qt

这部分没有自己验证过, 步骤繁琐, 不确定是否有问题.
因为本质上和使用最小系统是一样的, 只是加上了图形界面, 这个要到应用层开发UI才会用到!

编译qt依赖的库文件

注意修改--prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux 为实际的gcc-3.4.5-glibc-2.3.6绝对路径.

# ubuntu shell
# 编译qt依赖的库文件


# 1. 编译jpeg库
# 源码位于 '.../qtopia/deps/jpegsrc.v6b.tar.gz'
tar xzf jpegsrc.v6b.tar.gz # 解压得到jpeg-6b目录
cd jpeg-6b # 进入源码目录进行配置
./configure --enable-shared --enable-static --prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux --build=i386 --host=arm

# 会生成 Makefile 文件, 修改编译工具(需要改为arm-linux-xxx, 交叉编译):
vim Makefile # 可以在windows下直接改
# ===== 文件内容, 修改如下内容: =====
CC= arm-linux-gcc # CC= gcc
AR= arm-linux-ar rc # AR= ar rc
AR2= arm-linux-ranlib # AR2= ranlib
# ===== 结束修改, 保存退出vim =====
make
make install-lib
# .../gcc-3.4.5-glibc-2.3.6/arm-linux/lib 中生成jpeg库文件


# 2. 编译uuid库
# 源码位于 '.../qtopia/deps/e2fsprogs-1.40.2.tar.gz'
tar xzf e2fsprogs-1.40.2.tar.gz # 解压
cd e2fsprogs-1.40.2 # 进入源码目录进行配置
mkdir build
cd build
# 指定编译工具, 配置编译环境
../configure --with-cc=arm-linux-gcc --with-linker=arm-linux-ld --enable-elf-shlibs--host=arm-prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux
make
make install-lib
# .../gcc-3.4.5-glibc-2.3.6/arm-linux/lib 中生成 libuuid.so


# 3. 编译zlib库
# 源码位于 '.../qtopia/deps/zlib-1.2.3.tar.gz'
tar xzf zlib-1.2.3.tar.gz # 解压
cd zlib-1.2.3 # 进入源码目录进行配置
./configure --shared --prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux

# 会生成 Makefile 文件, 修改编译工具(需要改为arm-linux-xxx, 交叉编译):
vim Makefile # 可以在windows下直接改
# ===== 文件内容, 修改如下内容: =====
CC=arm-linux-gcc # CC=gcc
# ......
#LDSHARED=gcc -shared -Wl,-soname,libz.so.1
LDSHARED=arm-linux-gcc -shared -Wl,-soname,libz.so.1
# ......
CPP=arm-linux-gcc -E # CPP=gcc -E
# ......
AR=arm-linux-ar rc # AR=ar rc
# ......
RANLIB=arm-linux-ranlib # RANLIB=ranlib
# ===== 结束修改, 保存退出vim =====
make
make install
# .../gcc-3.4.5-glibc-2.3.6/arm-linux/lib 中生成zlib库文件


# 4. 编译png库
# 源码位于 '.../qtopia/deps/libpng-1.2.23.tar.bz2'
tar xjf libpng-1.2.23.tar.bz2 # 解压
cd libpng-1.2.23 # 进入源码目录进行配置
cp scripts/makefile.linux ./Makefile # 复制makefile

# 打开 Makefile 文件, 修改编译工具(需要改为arm-linux-xxx, 交叉编译):
vim Makefile # 可以在windows下直接改
# ===== 文件内容, 修改如下内容: =====
AR_RC=arm-linux-ar rc # AR_RC=ar rc
CC=arm-linux-gcc # CC=gcc
# ......
RANLIB=arm-linux-ranlib # RANLIB=ranlib
# ......
prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux
# ===== 结束修改, 保存退出vim =====
make
make install-lib
# .../gcc-3.4.5-glibc-2.3.6/arm-linux/lib 中生成png库文件


# 5. 编译ts库
# 源码位于 '.../qtopia/deps/tslib-1.3.tar.bz2'
tar xjf tslib-1.3.tar.bz2 # 解压
cd tslib-1.3 # 进入源码目录进行配置
./autogen.sh
echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure --host=arm-linux --cache-file=arm-linux.cache --enable-inputapi=no --prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux

vim ./src/ts_read_raw.c # 修改触摸芯片型号
# ===== 文件内容, 修改如下内容: =====
#char *defaulttseventtype="UCB1x00"; # 此句修改为:
char *defaulttseventtype="H3600";
# ===== 结束修改, 保存退出vim =====

# 防止出现 "libtool:link: only absolute run-paths are allowed" 的错误
vim ./plugins/Makefile # 修改为绝对路径
# ===== 文件内容, 修改如下内容: =====
#LDFLAGS :=$(LDFLAGS) -rpath $(PLUGIN_DIR)
LDFLAGS :=$(LDFLAGS) -rpath `cd $(PLUGIN_DIR) && pwd`
# ===== 结束修改, 保存退出vim =====

make
make install
# .../gcc-3.4.5-glibc-2.3.6/arm-linux/lib 中生成ts库文件

制作QT文件系统

# ubuntu shell


# 1. 创建qt文件夹
# tar要加上sudo. 因为解压出来的dev目录下有一些设备节点要用到root权限
sudo tar xjf fs_mini_mdev.tar.bz2 # 解压 fs_mini_mdev 最小fs
sudo cp -rf fs_mini_mdev fs_qtopia # 重命名为 fs_qtopia
# sudo chown -R root:root fs_qtopis # 更改用户和组


# 2. 复制Qtopia 依赖的库文件
cd .../gcc-3.4.5-glibc-2.3.6/arm-linux/lib/
cp libpng.so* .../fs_qtopia/lib/ -d
cp libjpeg.so* .../fs_qtopia/lib/ -d
cp libuuid.so* .../fs_qtopia/lib/ -d
cp libz.so* .../fs_qtopia/lib/ -d


# 3. 安装触摸屏所需的文件
cd .../tslib-1.3 # 编译ts库时, 解压出来的文件目录
make prefix=.../fs_qtopia/usr/ install # 修改为绝对路径!
cd .../fs_qtopia
cp ./usr/etc/ts.conf ./etc/ # 复制 ts.conf 文件
vim ./etc/ts.conf # 可以在windows下直接改
# ===== 文件内容, 修改如下内容: =====
# module mousebuts
module variance xlimit=50 ylimit=50 pthreshold=3
# module dejitter xdelta=1 ydelta=1 pthreshold=3 # 注释掉了这一行!
module linear
# ===== 结束修改, 保存退出vim =====


# 4. 复制字库和opt文件夹到开发板根目录
cd .../qtopia/qtopia-free-2.2.0/
cp -rf qt2/lib/fonts qtopia/image/opt/Qtopia/lib/
cp -rf qtopia/image/opt/ .../fs_qtopia


# 5. 创建时区文件, 直接使用ubuntu中的时区文件
cd .../fs_qtopia
mkdir -p usr/share/zoneinfo/
cp -rf /usr/share/zoneinfo/America usr/share/zoneinfo/
cp /usr/share/zoneinfo/zone.tab usr/share/zoneinfo/


# 6. 建立脚本, 用来校验触摸屏
# QT自带的触摸屏程序不好用. 想再次较验时, 把 /etc/pointercal 删掉后重启就可以了
cd .../fs_qtopia
vim bin/ts_cal.sh # 建立script文件
# ===== 文件内容如下: =====
#!/bin/sh
export HOME=/root
export QTDIR=/opt/Qtopia
export QPEDIR=/opt/Qtopia
export QWS_DISPLAY=LinuxFb:/dev/fb0
export QWS_KEYBOARD="TTY:/dev/tty1"
#export QWS_MOUSE_PROTO="USB:/dev/mouse0"
export QWS_MOUSE_PROTO="TPanel:/dev/ts0"
export PATH=$QPEDIR/bin:$PATH
export LD_LIBRARY_PATH=$QPEDIR/lib:$LD_LIBRARY_PATH
export TSLIB_TSDEVICE=/dev/ts0
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/usr/share/ts/plugins
export TSLIB_TSEVENTTYPE="H3600"
/usr/bin/ts_calibrate
# ===== 结束修改, 保存退出vim =====

chmod +x bin/ts_cal.sh # 修改为可执行


# 7. 建立脚本, 用来运行qtopia
cd .../fs_qtopia
mkdir -p root # 给 export HOME=/root 使用
vim bin/qpe.sh # 建立script文件
# ===== 文件内容如下: =====
#!/bin/sh
export HOME=/root
export QTDIR=/opt/Qtopia
export QPEDIR=/opt/Qtopia
export QWS_DISPLAY=LinuxFb:/dev/fb0
export QWS_KEYBOARD="TTY:/dev/tty1"
#export QWS_MOUSE_PROTO="USB:/dev/mouse0"
export QWS_MOUSE_PROTO="TPanel:/dev/ts0"
export PATH=$QPEDIR/bin:$PATH
export LD_LIBRARY_PATH=$QPEDIR/lib:$LD_LIBRARY_PATH
export TSLIB_TSDEVICE=/dev/ts0
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/usr/share/ts/plugins
export TSLIB_TSEVENTTYPE="H3600"

if [ ! -e /etc/pointercal ] then # 若不存在ts校验文件
/bin/ts_cal.sh # 执行校验脚本 (步骤6的文件)
fi

$QPEDIR/bin/qpe &
# ===== 结束修改, 保存退出vim =====

chmod +x bin/qpe.sh # 修改为可执行


# 8. 修改根文件系统的启动脚本
# 需要用到临时目录/tmp,为减少对Flash的擦写,在/tmp目录上挂接tmpfs文件系统
cd .../fs_qtopia
mkdir -p tmp # 建立/tmp目录
vim etc/fstab # 挂载 tmpfs
# ===== 文件内容, 加入如下语句: =====
tmpfs /tmp tmpfs defaults 0 0
# ===== 结束修改, 保存退出vi =====
vim etc/init.d/rcS # 开机自动执行 qpe.sh 脚本
# ===== 文件内容, 末尾加入如下语句: =====
/bin/qpe.sh &
# ===== 结束修改, 保存退出vi =====


9. 至此, fs_qtopia已经是一个完整的, 可支持QT的根文件系统了.
mkyaffs2image fs_qtopia fs_qtopia.yaffs2 # 制作映像文件

编译驱动程序

# ubuntu shell
# 源码位于 '.../drivers_and_test/first_drv'

# pwd = 驱动程序目录下
vim Makefile # 修改Makefile
# ===== 文件内容, 找到 'KERN_DIR', 配置内核位置: =====
KERN_DIR = /mnt/nfs/study/jz2440/kernel/linux-2.6.22.6
# ===== 结束修改, 保存退出vim =====
make # 获得 first_drv.ko
arm-linux-gcc -o firstdrvtest firstdrvtest.c # 交叉编译测试程序,
# -o 表示目标文件, 所以 'arm-linux-gcc firstdrvtest.c -o firstdrvtest' 也可以


# 切换到 开发板 shell

# 假设使用nfs加载的系统, 上述编译好后, 直接能在开发板上看到更改
# pwd = 驱动程序目录下
insmod first_drv.ko # 加载驱动模块
./firstdrvtest on # 执行测试
./firstdrvtest off # 执行测试

原创于 DRA&PHO