原文出处:刘建文 | 学术半·IT歌·文(http://arttech.us)
我是一位理论帝,想问题做事情更多的会从形而上的角度入手。这个结论的证据之一,是从我研究学习嵌入式Linux近一年后才决定购一台掌上电脑做实验。年初的时候就有朋友建议我购一块开发板,通过做实验快速掌握开发技术。但我并不以为然,首先,我认为基本功更重要,开发技术可短期内习得;什么是基本功,对内核结构的深度把握,对硬件的透彻理解;其次,我想我花三五百购块开发板做完后还有什么用?前一个想法的结果是十月底我才购一台机器做实验,后一想法的结果是我购的是诺基亚的n800,而不一次性的祼机板。
到目前为止我在n800上做了两个简单的实验,本文记录实验全程,不求同和,但求录之以照后来人。
第一个实验交叉编译一个hello模块到n800上,验证开发环境和开发硬件等的可用性;第二个实验是定制一个新内核到n800上,新内核中触摸屏和小键盘以模块形式加载,而非默认的内置。
Nokia N800 设备元信息
- OMAP2420 microprocessor
with a native speed of 400 MHz
-
Memory
: 128 MiB of RAM and 256 MiB of flash memory
-
Connectivity
: IEEE 802.11 b/g, Bluetooth 2.0 (DUN, OPP, FTP, HFP, HID profiles as well as A2DP/AVRCP and PAN via third party emulation), and USB 2.0 OTG high-speed.
-
Display
& resolution: pressure-sensitive resistive touch-screen LCD 4.1 inches 800×480 at 225 dpi
-
Expansion
: 2 full-sized Secure Digital card slots
-
Camera
: built-in pop-up rotating webcam.
-
Audio
: microphone, stereo speakers, FM radio tuner, 3.5-mm headphone jack (compatible with standard stereo headphones, but also containing a fourth pin with microphone input).
主要设备芯片(控制器)型号
- OMAP2420 N8x0 System-on-chip
- TMS320 C55x N8x0 DSP
- OMAP video N8x0 Video output
- PowerVR MBX N8x0 OpenGL ES and OpenVG acceleration
- OMAP Boot Tags N8x0 Provides boot information from bootloader (NOLO)
- OMAP MMC N8x0 SD/MMC cards
- tcm825x N8x0 Webcam + i2c bus
- tea5761 N800 FM radio
- blizzard N8x0 LCD controller
- menelaus N8x0 GPIO extender + i2c bus + ???
- tmp105 N8x0 Temperature sensor (menelaus GPIO)
- McSPI N8x0 SPI bus
- Sharp LS041Y3 N8x0 LCD panel (compatible with MIPID)
- cx3110x / stlc4550 N8x0 802.11b/g WiFi
- tsc2301 N800 Touchscreen + Keypad + GPIO + Audio
- OneNAND N8x0 Flash memory
- TUSB6010 N8x0 USB
开发过程
- 搭建开发环境
- 定义项目布局
- 搭建交叉编译开发环境
- 通过USB互联n800和开发PC
- 实验一——hello测试模块
- 实验二——定制模块化内核
搭建开发环境
定义项目布局
- 项目主目录:~/n800
- kernel src:~/n800/maemo/kernel-source-diablo/kernel-source
- 交叉编译工具链:~/n800/cross-tools
- 辅助构建工具:~/n800/build-tools
- 测试项目:~/n800/projects/hello_module | modulize_kernel
搭建交叉编译开发环境
1. 下载maemo4.1源码和补丁 :
http://repository.maemo.org/pool/maemo4.1.2/free/k/kernel-source-diablo/
2. 解包并进补:
$ patch -p2 < kernel-source-diablo_2.6.21-200842maemo1.diff
3. 安装pre-build交叉编译工具链 :
http://www.codesourcery.com/sgpp/lite/arm/releases/2005q3-2
这是一个商业免费版预编译工具链,直接解压到~/n800/cross-toolchain/下即可
4. 添加shell搜索路径
$ export PATH=~/n800/cross-toolchain/bin:$PATH
5. 测试源码树与交叉编译工具链的可用性
$cd ~/n800/maemo/kernel-source-diablo/kernel-source
$cp arch/arm/configs/nokia_2420_defconfig .confg
$make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- bzImage
此官方源码竟然有一个符号声明丢失:scripts/mod/sumversion.c PATH_MAX undeclared
修复办法:modifying linux-2.6.x/scripts/mod/sumversion.c, and adding #include fixes this issue.
成功编译内核后证明交叉编译工具链和源码树可用。编译源码树一遍为编译外部模块作准备(也可以通过执行kbuild接口 make modules_prepare) ,因为编译外部模块会对内核的一些信息有依赖,像内核输出符号(Module.symvers)。详见内核文档Document/kbuild/modules.txt
--- 2.4 Preparing the kernel tree for module build
To make sure the kernel contains the information required to build external modules the target 'modules_prepare' must be used. 'modules_prepare' exists solely as a simple way to prepare a kernel source tree for building external modules. Note: modules_prepare will not build Module.symvers even if CONFIG_MODVERSIONS is set. Therefore a full kernel build needs to be executed to make module versioning work.
通过USB互联n800和开发PC(我用的是fedora 13)
fedora 一端
1.enable USB networking support in the kernel.
# # USB Network Adapters #
CONFIG_USB_USBNET=m
CONFIG_USB_NET_CDCETHER=m
2.安装usbnet模块
Linux-PC: $ modprobe usbnet
3.配置usb网络接口
通过ifup的配置文件(/etc/sysconfig/network-scripts/ifcfg-usb0)实现:
DEVICE=usb0
BOOTPROTO=static
IPADDR=192.168.2.14
# IPADDR=10.0.1.2/24 should imply this ...
# but its support code seems to be buggy.
BROADCAST=192.168.2.255
NETMASK=255.255.255.0
NETWORK=192.168.2.0
# this is likely to break sometime
GATEWAY=192.168.2.1
ONBOOT=yes
4.启用网络接口
Linux-PC: $ ifup usb0
n800一端
1.取得root权限并安装ether_over_usb模块(g_ether.ko):
取得root权限的方法有两种,第一,开启机器的R&D模式,使用gainroot;第二种这是安装rootsh包,直接用root命令最得权限:
Nokia-N800: $ id uid=29999(user) gid=29999 (users)
#if use r&d mode
Nokia-N800: $ sudo /usr/sbin/gainroot
#or use rootsh
Nokia-N800: $ root
Nokia-N800: # insmod /mnt/initfs/lib/modules/2.6.18-omap1/g_ether.ko
2.启用网络接口
Nokia-N800: # ifup usb0
3.测试连通性
Nokia-N800: # ping 192.168.2.14
如果不通,再插拔一下USB线
使用ssh登陆
Linux-PC $ssh -l root 192.168.2.15
pw:111111 (此密码在安装OpenSSH时设置)
传送文件 Linux-PC $ scp ~/n800/projects/modulize_kernel/tsc2301_kp.ko root@192.168.2.15:
实验一——hello测试模块
1. 编写源文件hello_mod.c
01
/* hello_mod.c */
02
#include
03
#include
04
#include
05
06
static int
hello_init
(
void
)
07
{
08
printk
(
KERN_ALERT
"Hello, world
"
);
09
return
0
;
10
}
11
12
static void
hello_exit
(
void
)
13
{
14
printk
(
KERN_ALERT
"Goodbye, cruel world
"
);
15
}
16
17
module_init
(
hello_init
);
18
module_exit
(
hello_exit
);
19
MODULE_LICENSE
(
"GPL"
);
2. 编写kbuild Makefile
01
# Makefile for the hello module
02
obj-m
:=
hello_mod.o
03
KDIR
:=
~
/
n800
/
maemo
/
kernel-source-diablo
/
kernel-source
04
PWD
:= $(
shell
pwd
)
05
default
:
06
$(
MAKE
) -
C
$(
KDIR
)
M
=$(
PWD
)
modules
3. 编译
$ cd ~/n800/projects/hello_module
$ export PATH=~/n800/cross-toolchain/bin:$PATH
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
4.测试把编译得到的hello_mod.ko 通过ssh下载到n800进行测试,过程略。
实验二——定制模块化内核
编译内核及驱动模块
1. 配置内核
配置任务是把小键盘和触摸屏的驱动改为模块,官方内核是build-in 的。
$ cd ~/n800/maemo/kernel-source-diablo/kernel-source
$ cp arch/arm/configs/nokia_2420_defconfig .config
# 配置文件库(arch/arm/configs)还有一个n800_defconfig,此配置不适合OS2008
$ make menuconfig
2. 配置项如下,可以在配置程序内查找其所在位置,配置过程略
CONFIG_KEYBOARD_TSC2301=m
CONFIG_TOUCHSCREEN_TSC2301=m
3. 检查配置结果:
$ cat .config | grep TSC2301
CONFIG_KEYBOARD_TSC2301=m
CONFIG_TOUCHSCREEN_TSC2301=m
CONFIG_SPI_TSC2301=y
CONFIG_SPI_TSC2301_AUDIO=y
4. 编译内核
$ export PATH=~/n800/cross-toolchain/bin:$PATH
$ export ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
$ make zImage
$ cp arch/arm/boot/zImage ~/n800/projects/modulize_kernel
5. 编译模块
$ INSTALL_MOD_PATH=~/n800/projects/modulize_kernel
$ make modules
$ make modules_install
修改initramfs
initramfs是kernel 的[前根文件系统]引导功能(他们用了一个新概念叫early-userspace)的2.6版新实现,前2.6版的是众所周知的initrd。 initramfs不再是核外的一个虚拟盘,而是核内的内存根文件系统一个镜像,filesystem是使用缓存机制实现的tempfs。简单的理解是,initramfs是正在内存中运行的内核的根文件系统被转存(object dump)到磁盘上的映像。为了实现更好灵活性,新版内核的[前根文件系统]还是提供了[核内核外]配置的方式。核外配置的表象与initrd很像,但是完全不同的概念,内核使用完全不同的代码解读前根文件系统,initramfs只是一个cpio档,被bootloader调入内存后,内核会自动识别,进行链接。
1. 下载固件(
http://tablets-dev.nokia.com/nokia_N800.php
)并解包至 ~/n800/firmware
2. 下载并安装官方的擦写程序flash3.5(这里也可以使用一个开源的擦写程序0xFFFF)直接解压到~/n800/build-tools/flasher/即可
3. 解包固件至./firmware/43-7-fiasco
$ cd ~/n800/firmware
$ mkdir 43-7-fiasco;cd 43-7-fiasco
$ ~n800/build-tools/flasher-3.5 -F ~/n800/firmware/RX-34_DIABLO_5.2008.43-7_PR_COMBINED_MR0_ARM.bin -u
4. initramfs.jffs2 是jffs2镜像,先作成虚拟盘
$ mknod /tmp/mtdblock0 b 31 0
$ mkdir /mnt/initfs
$ modprobe loop
$ losetup /dev/loop0 ~/n800/firmware/43-7-fiasco/initfs-0.95.22-200842maemo1w38b3
$ modprobe mtdblock
$ modprobe block2mtd
# Note the ,128KiB is needed (on 2.6.26 at least) to set the eraseblock size.
$ echo "/dev/loop0,128KiB" > /sys/module/block2mtd/parameters/block2mtd
$ modprobe jffs2
$ mount -t jffs2 /tmp/mtdblock0 /mnt/initfs/
5. 虚拟盘不能直接修改,必须拷出来,修改后再用MTD tool(mkfs.jffs2)重制作initramfs 镜像
$ mkdir /mnt/tmp/initramfs
$ cp -a /mnt/initfs/ /mnt/tmp/initramfs
6. 拷贝驱动模块并修改启动脚本linuxrc
$ cp ~/n800/projects/modulize_kernel/tsc2301_kp.ko /mnt/tmp/initramfs/lib/modules/omapXXX/
$ cp ~/n800/projects/modulize_kernel/tsc2301_ts.ko /mnt/tmp/initramfs/lib/modules/omapXXX/
$ echo "insmod $MODULE_PATH/tsc2301_kp.ko" >> /mnt/tmp/initramfs/linuxrc
$ echo "insmod $MODULE_PATH/tsc2301_kp.ko" >> /mnt/tmp/initramfs/linuxrc
7. 重制作initramfs 镜像(
http://sources.redhat.com/jffs2/
)
$ mkfs.jffs2 -n -r /mnt/tmp/initramfs -e 20000 -o rootfs.jffs2
P.S. 事后发现原来可以直接在n800的maemo上修改,要修改,得行把initramfs闪存分区重挂接为可读写:
Nokia-N800: # mount -o remount,rw /dev/mtdblock3 /mnt/initramfs
烧制
$ cd ~/n800/build-tools/
$ flash3.5 -k ~/n800/projects/modulize_kernel/zImage -f
#提示接入n800,把n800接好USB线,按住HOME键再开机
$ flash3.5 -n ~/n800/projects/modulize_kernel/initramfs.jffs2 -f -R
重启后测试,测试过程略。
参考