系统移植手册
实验一 交叉工具链的安装
实验二 u-boot的烧写及使用
实验三 u-boot-2010.03的移植
实验四 内核的配置和编译
实验五 网卡驱动的移植
实验六 LED驱动的移植
实验七 Nand flash驱动的移植
实验八 LCD驱动的移植
实验九 USB驱动的移植
实验十 SD卡驱动的移植
实验十一 yaffs2文件系统的移植
实验十二 内核调试
实验十三 内存调试
实验十四 文件系统的移植
实验一 交叉工具链的安装
【实验目的】
了解交叉工具链的编译过程及其使用。
说明:在实验中命令行提示符为“$”表示在主机上运行,“#”表示在目标板上运行
【实验环境】
1、 ubuntu 10.10发行版
2、 FS_S5PC100平台
【实验步骤】
1、如果要自己编译工具链,从以下链接下载源码
crosstools-ng下载地址
http://ymorin.is-a-geek.org/download/crosstool-ng/
同时对每一个版本都有相应的补丁我们尽量把这些补丁打上,这些补丁的下载地址是
http://ymorin.is-a-geek.org/download/crosstool-ng/01-fixes/
2、工具的安装
在使用之前先安装下列软件
$ sudo apt-get install gawk autotools-dev automake texinfo libtool cvs patch bison flex libncurses5-dev
为了节约时间,我们已下载了相关的安装包,大家可以在本地安装
$ sudo dpkg -i tools/*.deb
3、 解压工具链压缩包
$ cd ~
$ tar xvf arm-cortex_a8-linux-gnueabi.tar.bz2
$ mv arm-cortex_a8 toolchain
4、 环境变量的添加
修改文件/etc/bash.bashrc添加如下内容
export PATH=$PATH:/home/linux/toolchain/bin
重启配置文件
$ source /etc/bash.bashrc
5、 工具链的测试
$ arm-cortex_a8-linux-gnueabi-gcc –v
Using built-in specs.
Target : arm-cortex_a8-linux-gnueabi
Configured with: /home/linux/src/gcc-4.4.6/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-cortex_a8-linux-gnueabi --prefix=/home/linux/toolchain --with-sysroot=/home/linux/toolchain/arm-cortex_a8-linux-gnueabi//sys-root --enable-languages=c,c++,fortran --disable-multilib --with-arch=armv7-a --with-float=soft --with-pkgversion=crosstool-NG-1.12.4-none --disable-sjlj-exceptions --enable-__cxa_atexit --disable-libmudflap --with-gmp=/home/linux/toolchain/toolchain-build/targets/arm-cortex_a8-linux-gnueabi/build/static --with-mpfr=/home/linux/ toolchain/toolchain-build/targets/arm-cortex_a8-linux-gnueabi/build/static --enable-threads=posix --enable-target-optspace --with-local-prefix=/home/linux/toolchain/arm-cortex_a8-linux-gnueabi//sys-root --disable-nls --enable-symvers=gnu --enable-c99 --enable-long-long
Thread model: posix
gcc version 4.4.6 (crosstool-NG 1.12.4)
这样我们的交叉工具链就安装好了
实验二 u-boot的烧写及使用
【实验目的】
了解u-boot的常用命令和linux内核的引导。
【实验环境】
1、 ubuntu 10.10发行版
2、 u-boot-2010.03
3、 FS_S5PC100平台
4、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
1、 u-boot的烧写
先认真阅读FS_S5PC100平台用户手册
运行串口通信程序(putty)
关闭开发板电源,将拨码开关SW1调至0001(usb启动模式)后打开电源
加载运行USB Installer_DDR2.bin
USB Port à Transmit à Transmit,选中image目录下的USB Installer_DDR2.bin
加载运行u-boot.bin
USB Port à Transmit à Transmit,选中image目录下的u-boot.bin 如下图所示
串口终端下能看到如下内容(如果有倒计时数字,按任意键出现提示符)
设置并保存环境变量
# printenv // 查看环境变量的值并按如下设置
# setenv baudrate 115200
# setenv ethaddr 11:22:33:44:55:66
# setenv gatewayip 192.168.1.1
# setenv serverip 192.168.1.100 // serverip要和虚拟机的ip相同
# setenv ipaddr 192.168.1.200 // ipaddr也可以是192.168.1.x其他值
# setenv netmask 255.255.255.0
保存环境变量
# saveenv
拷贝image/u-boot.bin到虚拟机/tftpboot目录下
测试网络是否连通 // 只能通过u-boot去ping虚拟机
#ping <serverip>
烧写u-boot.bin到nand flash起始地址
# tftp 20008000 u-boot.bin
# nand erase 0 40000
# nand write 20008000 0 40000
关闭开发板电源,将拨码开关SW1调至0000(nand启动模式)后打开电源
2、 通过网络加载内核和文件系统
设置内核启动参数
# setenv bootargs root=nfs nfsroot=192.168.1.100:/source/rootfs ip=192.168.1.200 init=/linuxrc console=ttySAC0,115200
# saveenv
设置虚拟机
拷贝/image/zImage到虚拟机/tftpboot目录下
解压rootfs.tgz到虚拟机/source目录下
修改虚拟机nfs配置文件/etc/exports,添加如下内容并重启nfs服务
/source/rootfs *(rw,sync,no_subtree_check,no_root_squash)
$sudo /etc/init.d/nfs-kernel-server restart
下载、启动内核
# tftp 20008000 zImage
# go 20008000
3、 从nand flash加载内核和文件系统
拷贝rootfs.cramfs到虚拟机/tftpboot目录下
烧写内核镜像到nand flash
# tftp 20008000 zImage
# nand erase 100000 300000
# nand write 20008000 100000 300000
烧写文件系统镜像到nand flash
# tftp 20008000 rootfs.cramfs
# nand erase 400000 400000
# nand write 20008000 400000 400000
设置启动参数
# setenv bootdelay 3
# setenv bootcmd nand read 20008000 100000 300000\; go 20008000
# setenv bootargs root=/dev/mtdblock2 ip=192.168.1.200 init=/linuxrc console=ttySAC0,115200
# saveenv
4、 重新启动开发板,u-boot自动加载、执行内核
5、 u-boot其他命令
u-boot支持的命令我们可以通过在终端上输入”?”查看
6、 交叉编译和交叉调试
- 编辑程序源码myapp.c
- 交叉编译后复制到/source/rootfs (编译时添加选项-g)
- 复制gdbserver到/source/rootfs/bin (gdbserver在工具链安装路径下查找)
- 在开发板上如下运行
# gdbserver 192.168.1.200:1234 myapp &
- 在主机上运行交叉调试器
$ arm-cortex_a8-linux-gnueabi-gdb myapp
- 在交叉调试器下和开发板gdbserver建立连接
(gdb) target remote 192.168.1.200:1234
- 设置断点,输入命令c开始调试程序(注意观察串口输出)
实验三 u-boot-2010.03的移植
【实验目的】
了解u-boot-2010.03的代码结构及移植方法。
【实验环境】
1、 ubuntu 10.10发行版
2、 u-boot-2010.03
3、 FS_S5PC100平台
4、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
说明:后面实验中的命令行提示符是($)则为主机命令(主机上执行),(#)则为开发板命令(开发板上执行)
一、建立自己的平台
1、 下载源码
我们可以在下面这个网站上下载最新的和以前任一版本的uboot
2、 解压uboot源码并进入目录
$ tar xvf u-boot-2010.03.tar.gz
$ cd u-boot-2010.03
3、 添加fsc100平台信息
我们关心的板级相关文件或目录
u-boot-2010.03/Makefile
u-boot- 2010.03/include/configs/smdkc100.h
u-boot- 2010.03 /cpu/arm_cortexa8/start.S
u-boot- 2010.03 /board/samsung/smdkc100
u-boot- 2010.03 /lib_arm
smdkc100是使用s5pc100芯片的参考板,我们在其基础之上移植fsc100
$ cd board/samsung/
$ cp –a smdkc100 fsc100
$ cd fsc100
$ mv smdkc100.c fsc100.c
$ vim Makefile
修改
COBJS-y := smdkc100.o
为
COBJS-y := fsc100.o
$ cd include/configs
$ cp smdkc100.h fsc100.h
修改u-boot顶层目录下的Makefile,指定交叉工具链
$ vim Makefile
在
ifeq ($(HOSTARCH, $(ARCH))
CROSS_COMPILE ?=
endif
下添加:
ifeq (arm, $(ARCH))
CROSS_COMPILE ?= arm-cortex_a8-linux-gnueabi-
endif
在u-boot顶层目录下的Makefile中添加fsc100配置信息
$ vim Makefile
在
smdkc100_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm_cortexa8 smdkc100 samsung s5pc1xx
下添加:
fsc100_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm_cortexa8 fsc100 samsung s5pc1xx
4、 编译u-boot-2010.03
$ make distclean
$ make fsc100_config
$ make
编译完成后生成的u-boot.bin就是可执行的镜像文件。但是该文件只能在smdkc100平台上运行,我们需要对u-boot源代码进行相应的修改。
二、针对我们的fsc100平台进行相应的移植
1、 修改include/configs/fsc100.h
修改内存基址
#define CONFIG_SYS_SDRAM_BASE 0x30000000
为
#define CONFIG_SYS_SDRAM_BASE 0x20000000
把
#undef CONFIG_CMD_NAND
改成
#define CONFIG_CMD_NAND
把
#undef CONFIG_CMD_NET
改成
#define CONFIG_CMD_NET
在
#define CONFIG_CMD_NAND
后添加
#define CONFIG_SYS_ICACHE_OFF 1
注释以下内容
#define CONFIG_CMD_ONENAND
注释以下内容
#define MTDIDS_DEFAULT “onenand…”
……
#define CONFIG_UPDATEB “updateb=……”
注释以下内容
#define CONFIG_EXTRA_ENV_SETTINGS \
……
“ubi=enabled”
修改提示符
#define CONFIG_SYS_PROMPT “SMDKC100 # ”
为
#define CONFIG_SYS_PROMPT “FSC100 # ”
修改
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE+0x5e00000)
为
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE+0x10000000)
修改内核加载地址
#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_SDRAM_BASE
为
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE+0x8000)
修改内存容量
#define PHYS_SDRAM_1_SIZE (128 << 20)
为
#define PHYS_SDRAM_1_SIZE (256 << 20)
修改环境变量存放位置
#define CONFIG_ENV_IS_IN_ONENAND 1
为
#define CONFIG_ENV_IS_IN_NAND 1
注释以下内容
从
#define CONFIG_USE_ONENAND_BOARD_INIT
到
#define CONFIG_SYS_ONENAND_BASE 0xE7100000
在
#define CONFIG_DOS_PARTITION 1
下面添加如下信息
添加NAND信息
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_MAX_CHIPS 1
#define CONFIG_SYS_NAND_BASE 0xE7200000
#define CONFIG_NAND_S5PC100 1
#define CONFIG_NAND_BL1_8BIT_ECC 1
#define CFG_NAND_HWECC 1
#define NAND_ENABLE_CE() (NFCONT_REG &= ~(1<<1))
#define NAND_DISABLE_CE() (NFCONT_REG |= (1<<1))
#define NF_TRANSRnB() do {while (! (NFSTAT_REG & (1<<0)) );} while(0)
添加网卡信息
#ifdef CONFIG_CMD_NET
#define CONFIG_NET_MULTI
#define CONFIG_CMD_PING 1
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x88000000
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE + 4)
#define CONFIG_DM9000_USE_16BIT
#define CONFIG_DM9000_NO_SROM 1
#define CONFIG_ETHADDR 11:22:33:44:55:66
#define CONFIG_IPADDR 192.168.1.200
#define CONFIG_SERVERIP 192.168.1.100
#define CONFIG_GATEWAYIP 192.168.1.1
#define CONFIG_NETMASK 255.255.255.0
#endif
2、 复制lowlevel_init.S mem_setup.S到board/samsung/fsc100
上述代码专门针对fsc100使用的内存进行初始化,可参考相关芯片手册
3、 复制fsc100.c到board/smsung/fsc100 覆盖原来的fsc100.c
fsc100.c 包含的是板级初始化函数
4、 在board/samsung/fsc100/目录下添加nand_cp.c
#include <common.h>
#ifdef CONFIG_S5PC1XX
#include <asm/io.h>
#include <linux/mtd/nand.h>
#define _REG__(x) (*(volatile unsigned long *)(x))
#define _REGb__(x) (*(volatile unsigned char *)(x))
#define NFCONT_REG _REG__(0xE7200004)
#define NFCMD_REG _REG__(0xE7200008)
#define NFADDR_REG _REG__(0xE720000C)
#define NFDATA8_REG _REGb__(0xE7200010)
#define NFSTAT_REG _REG__(0xE7200028)
#define NAND_CONTROL_ENABLE() (NFCONT_REG |= (1 << 0))
static int nandll_read_page (uchar *buf, ulong addr, int large_block)
{
int i;
int page_size = 512;
if (large_block) page_size = 2048;
NAND_ENABLE_CE();
NFCMD_REG = NAND_CMD_READ0;
/* Write Address */
NFADDR_REG = 0;
if (large_block) NFADDR_REG = 0;
NFADDR_REG = (addr) & 0xff;
NFADDR_REG = (addr >> 8) & 0xff;
NFADDR_REG = (addr >> 16) & 0xff;
if (large_block) NFCMD_REG = NAND_CMD_READSTART;
NF_TRANSRnB();
for (i=0; i<page_size; i++) {
*buf++ = NFDATA8_REG;
}
NAND_DISABLE_CE();
return 0;
}
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
{
uchar *buf = (uchar *)dst_addr;
int i, pages;
uint page_shift = 9;
if (large_block) page_shift = 11;
pages = size >> page_shift;
for (i=0; i<pages; i++) {
nandll_read_page(buf, i, large_block);
buf += (1 << page_shift);
}
return 0;
}
int copy_uboot_to_ram (void)
{
int i, large_block = 0;
vu_char id;
NAND_CONTROL_ENABLE();
NAND_ENABLE_CE();
NFCMD_REG = NAND_CMD_READID;
NFADDR_REG = 0x0;
/* wait for a while */
for (i=0; i<200; i++);
id = NFDATA8_REG;
id = NFDATA8_REG;
if (id > 0x80) large_block = 1;
return nandll_read_blocks(0x2ff80000, 0x40000, large_block);
}
#endif
5、 修改board/samsung/fsc100/Makefile
把
SOBJS := lowlevel_init.o
改成
SOBJS := lowlevel_init.o mem_setup.o
把
COBJS-y := fsc100.o
改成
COBJS-y := fsc100.o nand_cp.o
6、 修改board/samsun/fsc100/config.mk
把
TEXT_BASE = 0x34800000
改成
TEXT_BASE = 0x2FF80000
7、 修改cpu/arm_cortexa8/start.S
在
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
之后添加如下代码
/* 判断uboot是否在内存中运行 */
ldr r0, =_TEXT_BASE
adr r1, _TEXT_BASE
cmp r0, r1
beq stack_setup
ldr sp, =(0x22000000)
bl copy_uboot_to_ram
b stack_setup
8、 链接文件的修改
修改cpu/arm_cortexa8/u-boot.lds为:
……
.text :
{
cpu/arm_cortexa8/start.o (.text)
board/samsung/fsc100/lowlevel_init.o
board/samsung/fsc100/mem_setup.o
board/samsung/fsc100/nand_cp.o
*(.text)
}
……
9、 复制s5pc100.h s5pc1x0.h hardware.h 到 include/asm-arm/arch-s5pc1xx/
10、 复制s5p_nand.c到drivers/mtd/nand/
11、 修改drivers/mtd/nand/Makefile
在
COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
后面添加
COBJS-$(CONFIG_NAND_S5PC100) += s5p_nand.o
12、 修改include/linux/mtd/mtd-abi.h
struct nand_ecclayout {
……
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
uint32_t useecc;
uint32_t reserved;
};
13、 在lib_arm/board.c中添加网卡初始化代码
在
eth_initialize(gd->bd);
后面添加
eth_init(gd->bd);
14、 修改网卡驱动drivers/net/dm9xxx.c
在函数dm9000_init中,
DM9000_iow(DM9000_IMR, IMR_PAR);
之后的内容都注释掉,直到该函数结束(return 0之前)
15、 修改include/net.h
static inline int is_multicast_ether_addr(const u8 *addr)
{
return (0x01 == addr[0]);
}
16、 修改net/net.c
在 int NetArpWaitTry; 后添加如下代码
ulong timer_clk;
void ArpTimeoutCheck(void)
{
……
把
t = get_timer(0);
改成
t = get_timer(0) / (timer_clk / CONFIG_SYS_HZ);
}
extern unsigned long (*get_pclk)(void);
int NetLoop(proto_t protocol)
{
bd_t *bd = gd->bd;
添加如下代码:
timer_clk = get_pclk() / (16 * 2);
……
注释以下代码
eth_halt();
eth_set_current();
if (eth_init(bd) < 0) {
eth_halt();
return -1;
}
把
if (timeHandler && ( … > timeDelta) {
改成
ulong t;
t = get_timer(0) / (timer_clk / CONFIG_SYS_HZ);
if (timeHandler && (t - timeStart) > timeDelta) {
……
}
void NetSetTimeout(ulong iv, thand_f *f)
{
把
timeStart = get_timer(0);
改成
timeStart = get_timer(0) / (timer_clk / CONFIG_SYS_HZ);
}
int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
{
……
把
NetArpWaitTimerStart = get_timer(0);
改成
NetArpWaitTimerStart = get_timer(0) / (timer_clk / CONFIG_SYS_HZ);
……
}
int PingSend(void)
{
……
把
NetArpWaitTimerStart = get_timer(0);
改成
NetArpWaitTimerStart = get_timer(0) / (timer_clk / CONFIG_SYS_HZ);
……
}
注释该文件中所有的eth_halt()
17、 go命令的优化
修改该common/cmd_boot.c
int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
ulong addr, rc;
int rcode = 0;
if (argc < 2) {
return cmd_usage(cmdtp);
}
/**************** added by farsight 2011-12-18 *****************/
char *cmdline = getenv("bootargs");
struct param_struct *kernel_params=(struct param_struct *)0x20000100;
printf("setup linux parameters at 0x20000100\n");
memset(kernel_params, 0, sizeof(struct param_struct));
kernel_params->u1.s.page_size=4096;
kernel_params->u1.s.nr_pages=0x10000000>>12;
memcpy(kernel_params->commandline, cmdline, strlen(cmdline)+1);
printf("linux command line is: \"%s\"\n",cmdline);
/***************************************************************/
addr = simple_strtoul(argv[1], NULL, 16);
printf ("## Starting application at 0x%08lX ...\n", addr);
/******************* added by farsight 2011-12-18 ******************/
__asm__(
"ldr r1, =1826\n"
"mov ip, #0\n"
"mcr p15, 0, ip, c8, c7, 0\n"
"mcr p15, 0, ip, c7, c5, 0\n"
"mcr p15, 0, ip, c7, c5, 6\n"
"mcr p15, 0, ip, c7, c10, 4\n"
"mcr p15, 0, ip, c7, c5, 4\n"
"mrc p15, 0, ip, c1, c0, 0\n"
"bic ip, ip, #0x00002000\n"
"bic ip, ip, #0x00000007\n"
"orr ip, ip, #0x00000002\n"
"orr ip, ip, #0x00000800\n"
"bic ip, ip, #0x00001000\n"
"mcr p15, 0, ip, c1, c0, 0\n"
"mov pc, %0\n"
"nop\n"
:
:"r"(addr)
);
/***************************************************************/
rc = do_go_exec ((void *)addr, argc - 1, argv + 1);
if (rc != 0) rcode = 1;
printf ("## Application terminated, rc = 0x%lX\n", rc);
return rcode;
}
三、重新编译
$ make distclean
$ make fsc100_config
$ make
这样我们就得到能够在fsc100平台上使用的u-boot.bin
实验四 内核的配置和编译
【实验目的】
了解内核的编译过程及配置选项的内容
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
- 解压内核
将linux-2.6.35.tar.bz2拷贝到/home/linux下并解压
$tar xvf linux-2.6.35.tar.bz2
$ cd linux-2.6.35
- 修改内核顶层目录下的Makefile
$ vim Makefile
修改:
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
为:
ARCH ?= arm
CROSS_COMPILE ?= arm-cortex_a8-linux-gnueabi-
- 拷贝标准板配置文件
$ cp arch/arm/configs/s5pc100_defconfig .config
- 配置内核
$ make menuconfig
该命令执行时会弹出一个菜单,我们可以对内核进行详细的配置。这里我们先查看一下,内核都提供了那些功能!
- 编译内核
$ make zImage
通过上述操作我们能够在arch/arm/boot目录下生成一个zImage文件,这就是经过压缩的内核镜像。
实验五 网卡驱动的移植
【实验目的】
通过上面的实验我们能够获得一个内核,但是这个内核只是一个最基本的配置,很多的功能并没有包含。
网卡是嵌入式产品最常用的设备,这里我们需要完成网卡驱动的移植。FS_S5PC100使用的是DM9000网卡,我们通过这个实验能够了解如何在内核中添加网卡驱动及网络功能的基本配置。
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
- 平台代码修改
vim arch/arm/mach-s5pc100/mach-smdkc100.c
- 添加需要的头文件(注:由于linux的头文件之间也有依赖关系,所以应该讲将下面的头文件加到原来头问价的最后)
#if defined (CONFIG_DM9000)
#include <linux/dm9000.h>
#include <linux/irq.h>
#endif
- 平台设备的添加
/* DM9000 Support */
#if defined(CONFIG_DM9000)
static struct resource dm9000_resources[] = {
[0] = {
.start = 0x88000000,
.end = 0x88000000 + 0x3,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0x88000000 + 0x4,
.end = 0x88000000 + 0x4 +0x3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_EINT(10),
.end = IRQ_EINT(10),
.flags = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_HIGH,
},
};
static struct dm9000_plat_data s5pc100_dm9000_platdata = {
.flags = DM9000_PLATF_16BITONLY,
.dev_addr[0] = 0x00,
.dev_addr[1] = 0x00,
.dev_addr[2] = 0x3e,
.dev_addr[3] = 0x26,
.dev_addr[4] = 0x0a,
.dev_addr[5] = 0x00,
};
static struct platform_device s5pc100_device_dm9000 = {
.name = "dm9000",
.id = -1,
.num_resources = ARRAY_SIZE(dm9000_resources),
.resource = dm9000_resources,
.dev = {
.platform_data = & s5pc100_dm9000_platdata,
}
};
#endif
- 平台设备列表的添加:
在smdkc100_devices[]结构体数组中添加如下内容:
#if defined(CONFIG_DM9000)
&s5pc100_device_dm9000,
#endif
- 配置内核
$ make menuconfig
- 网络配置:
[*] Networking support (NEW) --->
Networking options --->
<*> Packet socket
<*> Unix domain sockets
[*] TCP/IP networking
[*] IP: multicasting
[*] IP: kernel level autoconfiguration
[*] IP: BOOTP support
- 网卡驱动配置
Device Drivers --->
[*] Network device support --->
[*] Ethernet (10 or 100Mbit) --->
<*> DM9000 support
- 网络文件系统的配置
File systems --->
[*] Network File Systems --->
<*> NFS client suppor
[*] NFS client support for NFS version 3
[*] NFS client support for the NFSv3 ACL protocol extension
[*] Root file system on NFS
- 编译内核,并拷贝到tftpboot目录下
$ make zImage
$ cp arch/arm/boot/zImage /tftpboot
- 启动开发板,修改内核启动参数,通过NFS方式挂载根文件系统
实验六 LED驱动的移植
【实验目的】
- 驱动程序的静态编译和动态编译
- 应用程序如何打开/操作设备
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
- 修改内核配置
$ make menuconfig
Kernel Features --->
[*] Use the ARM EABI to compile the kernel
[*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL)
添加驱动文件
将实验代码LED_TEST/fsc100_led_drv.c拷贝到drivers/char下
修改drivers/char/Kconfig
在menu "Character devices"下面
添加如下内容:
config FSC100_LED
tristate "FSC100 LED Device Support"
depends on ARCH_S5PC100
help
support led device on FS_S5PC100 develop board
修改drivers/char/Makefile
在 obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o 下一行添加:
obj-$(CONFIG_FSC100_LED) += fsc100_led_drv.o
交叉编译测试程序fsc100_led_test.c
arm-cortex_a8-linux-gnueabi-gcc fsc100_led_test.c –o fsc100_led_test
sudo cp fsc100_led_test /source/rootfs
设置u-boot环境变量
# setenv serverip 192.168.1.100
# setenv ipaddr 192.168.1.200
# setenv bootcmd tftp 20008000 zImage\; go 20008000
# setenv bootargs root=nfs nfsroot=192.168.1.100:/source/rootfs console=ttySAC0,115200 init=/linuxrc ip=192.168.1.200
# saveenv
1、 静态编译LED驱动
- 配置内核时按“空格”选择,配置完成后保存退出
$ make menuconfig
Device Drivers --->
Character devices --->
<*> FSC100 LED Device Support
- 保存退出,重新编译后把zImage拷贝到tftpboot下
$ make zImage
$ cp arch/arm/boot/zImage /tftpboot
重新启动开发板,加载内核并运行。在终端下执行下面操作
- 创建设备节点
# mknod /dev/led c 252 0
- 运行测试程序并观察现象
# ./fsc100_led_test
2、 动态编译LED驱动
- 配置内核时按“空格”选择,配置完成后保存退出
$ make menuconfig
Device Drivers --->
Character devices --->
<M> FSC100 LED Device Support
- 保存退出,重新编译后把zImage拷贝到tftpboot下,把驱动模块拷贝到/source/rootfs下
$ make zImage modules
$ cp arch/arm/boot/zImage /tftpboot
$ cp drivers/char/fsc100_led_drv.ko /source/rootfs
重新启动开发板,linux运行起来后在终端下操作
- 创建设备节点
# mknod /dev/led c 252 0 //c表示 字符设备,252是主设备号,0是次设备号
- 加载LED驱动模块
#insmod fsc100_led_drv.ko
- 运行测试程序并观察现象
# ./fsc100_led_test
实验七 Nand flash驱动的移植
【实验目的】
Nand flash 是嵌入式系统最常用的外部存储设备,这里介绍Nand flash驱动移植的过程。
说明:在本系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
添加针对我们平台的Nand flash驱动
拷贝s3c_nand.c到drivers/mtd/nand下
拷贝regs-nand.h到arch/arm/mach-s5pc100/include/mach下
针对平台上的nand flash设备,修改drivers/mtd/nand/nand_base.c第2812行
for (i = 0; i < 5; i++)
- 添加内核配置选项
修改drivers/mtd/nand/Kconfig,在if mtd_nand下面添加如下内容:
config MTD_NAND_S3C
tristate "NAND Flash support for S3C SoC"
depends on (ARCH_S3C64XX || ARCH_S5P64XX || ARCH_S5PC1XX || ARCH_S5PC100) && MTD_NAND
help
This enables the NAND flash controller on the S3C.
No board specfic support is done by this driver, each board
must advertise a platform_device for the driver to attach.
config MTD_NAND_S3C_DEBUG
bool "S3C NAND driver debug"
depends on MTD_NAND_S3C
help
Enable debugging of the S3C NAND driver
config MTD_NAND_S3C_HWECC
bool "S3C NAND Hardware ECC"
depends on MTD_NAND_S3C
help
Enable the use of the S3C's internal ECC generator when
using NAND. Early versions of the chip have had problems with
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
If you lay down a device with the hardware ECC, then you will
currently not be able to switch to software, as there is no
implementation for ECC method used by the S3C
修改drivers/mtd/nand/Makefile添加如下内容:
obj-$(CONFIG_MTD_NAND_S3C) += s3c_nand.o
- 修改平台代码
修改arch/arm/mach-s5pc100/mach-smdkc100.c添加如下内容:
- 添加头文件
#if defined (CONFIG_MTD_NAND_S3C)
#include <linux/mtd/partitions.h>
#include <linux/mtd/mtd.h>
#include <plat/nand.h>
#endif
- 添加平台设备
#if defined(CONFIG_MTD_NAND_S3C)
/* Nand Flash Support */
static struct mtd_partition s5pc100_nand_part[] = {
[0] = {
.name = "bootloader",
.size = SZ_1M,
.offset = 0,
},
[1] = {
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_1M*3,
},
[2] = {
.name = "rootfs",
.offset = MTDPART_OFS_APPEND,
.size = SZ_4M,
},
[3] = {
.name = "usrfs",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
struct s3c_nand_mtd_info s5pc100_nand_mtd_part_info = {
.chip_nr = 1,
.mtd_part_nr = ARRAY_SIZE(s5pc100_nand_part),
.partition = s5pc100_nand_part,
};
static struct resource s5pc100_nand_resource[] = {
[0] = {
.start = 0xE7200000,
.end = 0xE7200000 + SZ_1M,
.flags = IORESOURCE_MEM,
}
};
struct platform_device s5pc100_device_nand = {
.name = "s5pc100-nand",
.id = -1,
.num_resources = ARRAY_SIZE(s5pc100_nand_resource),
.resource = s5pc100_nand_resource,
.dev = {
.platform_data = &s5pc100_nand_mtd_part_info,
}
};
#endif
- 添加平台设备列表
在smdkc100_device[]结构体数组中添加如下内容:
#if defined(CONFIG_MTD_NAND_S3C)
&s5pc100_device_nand,
#endif
- 修改arch/arm/plat-samsung/include/plat/nand.h添加如下内容:
struct s3c_nand_mtd_info {
uint chip_nr;
uint mtd_part_nr;
struct mtd_partition *partition;
};
- 配置内核
$ make menuconfig
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
[*] MTD partitioning support
<*> Caching block device access to MTD devices
<*> NAND Device Support --->
<*> NAND Flash support for S3C SoC
[*] S3C NAND Hardware ECC
File Systems --->
Partition Types --->
[*] Advanced partition selection
[*] PC BIOS (MSDOS partition tables) support
[*] BSD disklabel (FreeBSD partition tables) support
- 编译内核并拷贝到tftpboot下
$ make zImage
$ cp arch/arm/boot/zImage /tftpboot
- 测试
启动目标板,在目标板上完成如下操作:
# cat /proc/partitions
dev: size erasesize name
mtd0: 00100000 00020000 "bootloader"
mtd1: 00300000 00020000 "kernel"
mtd2: 00400000 00020000 "rootfs"
mtd3: 0f800000 00020000 "usrfs"
实验八 LCD驱动移植
【实验目的】
了解交叉工具链的编译过程及其使用。
说明:在本系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
- 修改arch/arm/mach-s5pc100/mach-smdkc100.c
修改smdkc100_fb_win0结构体内容为:
static struct s3c_fb_pd_win smdkc100_fb_win0 = {
/* this is to ensure we use win0 */
.win_mode = {
.pixclock = 1000000000000ULL / ((8+43+1+480)*(4+10+12+272)*80),
.left_margin = 8,
.right_margin = 43,
.upper_margin = 4,
.lower_margin = 12,
.hsync_len = 1,
.vsync_len = 10,
.xres = 480,
.yres = 272,
},
.max_bpp = 32,
.default_bpp = 16,
};
- 修改drivers/video/Kconfig
修改:
depends on (FB && ARCH_S3C64XX)
为:
depends on (FB && ARCH_S3C64XX) || (FB && ARCH_S5PC100)
- 配置内核
$ make menuconfig
Device Drivers --->
Graphics support --->
<*> Support for frame buffer devices --->
<*> Samsung S3C framebuffer support
Console display driver support --->
<*> Framebuffer Console support
[*] Bootup logo --->
- 编译内核并拷贝到tftpboot下
$ make zImage
$ cp arch/arm/boot/zImage /tftpboot
- 测试
插上屏,启动开发板,能够看到屏幕上显示一个小企鹅就是移植成功了!
实验九 USB驱动的移植
【实验目的】
USB接口是现在计算机系统中最通用的一种接口,
说明:在本系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
- 添加针对我们板子的USB驱动及相关头文件
拷贝ohci-s3c2410.c 到drivers/usb/host/下
拷贝regs-clock.h 到 arch/arm/mach-s5pc100/include/mach/下
- 修改drivers/usb/Kconfig
在:
default y if ARCH_S3C2410
后添加:
default y if ARCH_S5PC100
- 修改drivers/usb/host/ohci-hcd.c
修改:
#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX)
为:
#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_ARCH_S5PC100)
- 修改arch/arm/mach-s5pc100/include/mach/map.h
添加如下内容:
#define S3C_PA_USBHOST (0xED400000)
- 修改arch/arm/plat-samsung/dev-usb.c
修改
[1] = {
.start = IRQ_USBH,
.end = IRQ_USBH,
.flags = IORESOURCE_IRQ,
}
为:
[1] = {
.start = IRQ_UHOST,
.end = IRQ_UHOST,
.flags = IORESOURCE_IRQ,
}
- 添加平台设备
修改arch/arm/mach-s5pc100/Kconfig
在
select S3C_PL330_DMA
后添加
select S3C_DEV_USB_HOST
修改arch/arm/mach-s5pc100/mach-smdkc100.c
添加头文件
#if defined (CONFIG_USB_SUPPORT)
#include <plat/pll.h>
#include <linux/usb/ch9.h>
#include <mach/regs-clock.h>
#endif
添加平台设备
#if defined(CONFIG_USB_SUPPORT)
void usb_host_clk_en(void) {
/* Setting the epll clk to 48 MHz, P=3, M=96, S=3 */
writel((readl(S5P_EPLL_CON) & ~(S5P_EPLL_MASK)) | (S5P_EPLL_EN \
| S5P_EPLLVAL(96,3,3)), S5P_EPLL_CON);
writel((readl(S5P_CLK_SRC0) | S5P_CLKSRC0_EPLL_MASK), S5P_CLK_SRC0);
writel((readl(S5P_CLK_SRC1)& ~S5P_CLKSRC1_UHOST_MASK), S5P_CLK_SRC1);
/* USB host clock divider ratio is 1 */
writel((readl(S5P_CLK_DIV2)& ~S5P_CLKDIV2_UHOST_MASK), S5P_CLK_DIV2);
writel(readl(S5P_CLKGATE_D10)|S5P_CLKGATE_D10_USBHOST, S5P_CLKGATE_D10);
writel(readl(S5P_SCLKGATE0)|S5P_CLKGATE_SCLK0_USBHOST, S5P_SCLKGATE0);
}
EXPORT_SYMBOL(usb_host_clk_en);
#endif
添加平台设备列表
在smdkc100_device[]结构体数组中添加如下内容:
#if defined(CONFIG_USB_SUPPORT)
& s3c_device_ohci,
#endif
- 配置内核
$ make menuconfig
USB控制器支持
Device Drivers --->
[*] USB support --->
<*> Support for Host-side USB
<*> OHCI HCD support
U盘支持
Device Drivers --->
SCSI device support --->
<*> SCSI device support
<*> SCSI disk support
<*> SCSI generic support
<*> SCSI media changer support
Device Drivers --->
[*] USB support --->
<*> USB Mass Storage support
文件系统及语言配置:
File systems --->
DOS/FAT/NT Filesystems --->
<*> VFAT (Windows-95) fs support
-*- Native language support --->
<*> Codepage 437 (United States, Canada)
<*> Simplified Chinese charset (CP936, GB2312)
<*> NLS ISO 8859-1 (Latin 1; Western European Languages)
<*> ASCII (United States)
<*> NLS UTF-8
- 编译内核并拷贝到tftpboot下
$ make zImage
$ cp arch/arm/boot/zImage /tftpboot
- 测试
启动目标板并在目标板上完成如下操作:
# mount -t vfat /dev/sda1 /mnt
# ls
可以查看到U盘内容,即完成实验。
实验十 SD卡驱动移植
【实验目的】
SD卡是嵌入式系统最常用的外部扩展存储设备,这里介绍SD驱动移植的过程。
说明:在系统移植课程实验中命令行提示符 “$”表示是在主机上执行,“#”表示在目标板执行
【实验环境】
- 主机:ubuntu 10.10发行版
- 目标机:FS_S5PC100平台
- 交叉编译工具:arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
- 修改配置文件
修改drivers/mmc/host/Kconfig
修改:
depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)
为:
depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX || ARCH_S5PC100)
修改driver/mmc/host/sdhci.c
修改:
mmc->f_min = host->max_clk / 256;
为
mmc->f_min = host->max_clk / 512;
- 配置内核
$ make menuconfig
SD卡驱动配置:
Device Drivers --->
<*> MMC/SD/SDIO card support --->
<*> SDHCI support on Samsung S3C SoC
[*] DMA support on S3C SDHCI
- 编译内核并拷贝到tftpboot下
$ make zImage
$ cp arch/arm/boot/zImage /tftpboot
- 测试
启动目标板并在目标板上完成如下操作:
# mount -t vfat /dev/mmcblk0p1 /mnt
# ls
可以查看到SD卡内容,即完成实验。
实验十一 yaffs2文件系统的移植
【实验目的】
yaffs2文件系统是嵌入式系统中常用到的一种文件系统,并且在主要用在nand flash上,这里我们在内核里添加yaffs2的支持
【实验环境】
1、 ubuntu 10.10发行版
2、 FS_S5PC100平台
3、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
1、 源码下载
$ wget http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/yaffs2.tar.gz
2、 解压到内核源码linux-2.6.35同级目录下
$ tar xvf yaffs2.tar.gz
3、 往内核打yaffs2补丁
$ cd yaffs2
$ ./patch-ker.sh c ../linux-2.6.35
4、 配置内核
$ cd ../linux-2.6.35
$ make menuconfig
File systems --->
[*] Miscellaneous filesystems --->
<*> YAFFS2 file system support
-*- 512 byte / page devices
-*- 2048 byte (or larger) / page devices
[*] Autoselect yaffs2 format
[*] Cache short names in RAM
5、 重新编译内核
$ make zImage
6、 拷贝内核到开发板上
$ cp arch/arm/boot/zImage /tftpboot
7、 重新启动开发板
# cat /proc/filesystems
nodev sysfs
nodev rootfs
nodev bdev
nodev proc
nodev tmpfs
nodev sockfs
nodev usbfs
nodev pipefs
nodev anon_inodefs
nodev rpc_pipefs
nodev devpts
ext3
ext2
cramfs
nodev ramfs
vfat
msdos
iso9660
nodev nfs
nodev jffs2
romfs
yaffs
yaffs2
nodev mtd_inodefs
实验十二 内存调试
【实验目的】
段错误和内存错误是C语言编程经常遇到的问题,使用memwatch是由johan lindh编写,是一个开发源代码C语言内存错误检测工具。能检测双重释放,错误释放,没有释放内存,溢出等等情况。
【实验环境】
1、 ubuntu 10.10发行版
2、 FS_S5PC100平台
3、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
1、 解压memwatch.-2.7.1.tar.gz,在解开的目录下添加代码memtest.c
#include <stdlib.h>
#include <stdio.h>
#include "memwatch.h"
int main(int argc,char **argv)
{
char *ptr1;
char *ptr2;
ptr1 = malloc(512);
ptr2 = malloc(512);
ptr1[512]="A";
ptr2 = ptr1;
free(ptr2);
free(ptr1);
return 0;
}
2、 修改 Makefile
Makefile文件为:
CC=arm-cortex_a8-linux-gnueabi-gcc
memtest:
$(CC) -DMEMWATCH -DMW_STDIO memtest.c memwatch.c
5、运行make并将编译生成的可执行程序a.out拷贝到开发板的根目录下执行,会生成一个记录文件memwatch.log,内容如下:
============= MEMWATCH 2.71 Copyright (C) 1992-1999 Johan Lindh =========
Started at Thu Jan 1 00:08:33 1970
Modes: __STDC__ 32-bit mwDWORD==(unsigned long)
mwROUNDALLOC==4 sizeof(mwData)==32 mwDataSize==32
- overflow: <3> memtest.c(12), 512 bytes alloc'd at <1> memtest.c(8)
double-free: <4> memtest.c(13), 0x1a1b4 was freed from memtest.c(12)
Stopped at Thu Jan 1 00:08:33 1970
unfreed: <2> test.c(9), 512 bytes at 0x1a3e4 {FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE FE ................}
Memory usage statistics (global):
N)umber of allocations made: 2
L)argest memory usage : 1024
T)otal of all alloc() calls: 1024
U)nfreed bytes totals : 512
//overflow: <3> memtest.c(12)缓冲区溢出,当程序执行到第15行free(ptr2)才检测到的;
512 bytes alloc'd at <1> memtest.c(9)
//表示出错缓冲区的大小为512字节,是在memtest.c的第9行分配的。很容易发现代码的ptr1[512]="A"出现错误。
double-free: <4> memtest.c(13), 0x1a7f4 was freed from memtest.c(12)
//double-free: <4> memtest.c(16)是一个双重释放的错误,表示程序执行到16行的时候才检测到。
0x1a7f4 was freed from memtest.c(12)
//表示首地址为 0x1a7f4的内存在15行已经被释放。
Stopped at Wed Dec 31 19:00:38 1969
unfreed: <2> memtest.c(10), 512 bytes at 0x1aa24 {FE FE FE FE FE FE FE FE
//表示一块内存没有释放,表示这块内存是在memtest.c的第10行分配,大小为512字节,首地址为0x1aa24。
Memory usage statistics (global):
N)umber of allocations made: 2
L)argest memory usage : 1024
//程序结束时能够是使用的最大动态内存
T)otal of all alloc() calls: 1024 //总共分配的动态内存
U)nfreed bytes totals : 512
//表示未释放的内存
实验十三 内核调试
【实验目的】
由于在驱动开发中经常看到内核崩溃的问题,最常见的就是OOPS错误,本实验要求学员掌握这种调试方法。
【实验环境】
1、 ubuntu 10.10发行版
2、 FS_S5PC100平台
3、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
1、通过OOPS信息中PC寄存器的值可以知道出错指令的地址,通过栈回朔信息可以知道出错时的函数调用的关系,根据这两点可以很快定位错误。
2、 修改drivers/video/s3c-fb.c,在s3c_fb_probe函数中int ret=0;下增加下面语句:
int *ptr = NULL;
*ptr = 0xff;
3、编译内核下载到开发板上,内核启动会出现如类似下信息:
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1]
Modules linked in:
CPU: 0 Not tainted (2.6.35 #6)
PC is at s3c_fb_probe+0xc/0x67c
LR is at platform_drv_probe+0x1c/0x24
pc : [<c0290a28>] lr : [<c01a44e4>] psr: a0000013
sp : cfc29f0c ip : cfc457c0 fp : 00000000
r10: 00000000 r9 : 00000000 r8 : c03ad4f8
r7 : c03a93d0 r6 : c03a93d0 r5 : c0395258 r4 : 00000000
r3 : 000000ff r2 : cfc28000 r1 : 00000000 r0 : c0395250
4、Unable to handle kernel NULL pointer dereference at virtual address 00000000
可以看出使用了空指针。找出函数调用关系:PC is at s3c_fb_probe+0xc/0x67c
,表示出错指令为 s3c_fb_probe函数中偏移为0xc的指令。pc : [<c0290a28>] 表示出错指令的地址为c0290a28.
5、结合内核源代码和反汇编代码定位问题。
arm-cortex_a8-linux-gnueabi-objdump -D vmlinux > vmlinux.dis // 文件vmlinux.dis非常大
出错地址c001abc4附近的部分汇编代码如下:
c0290a1c <s3c_fb_probe>:
c0290a1c: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
c0290a20: e3a030ff mov r3, #255
c0290a24: e3a04000 mov r4, #0
c0290a28: e5843000 str r3, [r4]
c0290a2c: e590106c ldr r1, [r0, #108]
……
对应C代码如下:
struct device *dev = &pdev->dev;
struct s3c_fb_platdata *pd;
struct s3c_fb *sfb;
struct resource *res;
int win;
int ret = 0;
int *ptr = NULL;
*ptr = 0xff;
6、对于大多数情况,从反汇编代码定位到C代码并不会如此容易,需要有较强的阅读汇编代码的能力。
7、另外一种方法是通过addr2line去定位
arm-cortex_a8-linux-gnueabi-addr2line 0xc0290a28 -e vmlinux -f
重要 :该实验完成后不要忘记恢复被修改的代码
实验十四 文件系统的移植
【实验目的】
熟悉Linux文件系统目录结构,创建自己的文件系统,通过NFS方式测试;用文件系统工具生成ramdisk文件系统映象文件。
【实验环境】
1、 ubuntu 10.10发行版
2、 FS_S5PC100平台
3、 交叉编译器 arm-cortex_a8-linux-gnueabi-gcc
【实验步骤】
一、根文件系统制作
1、 源码下载
我们选择的版本是busybox-1.17.3.tar.bz2下载路径为:
2、 解压源码
$ tar xvf busybox-1.17.3.tar.bz2
3、 进入源码目录
$ cd busybox-1.17.3
4、 配置源码
$ make menuconfig
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs)
[ ] Force NOMMU build
[ ] Build with Large File Support (for accessing files > 2 GB)
(arm-cortex_a8-linux-gnueabi-) Cross Compiler prefix
() Additional CFLAGS
5、 编译
$ make
6、 安装
busybox默认安装路径为源码目录下的_install
$ make install
7、 进入安装目录下
$ cd _install
$ ls
bin linuxrc sbin usr
8、 创建其他需要的目录
$ mkdir dev etc mnt proc var tmp sys root
9、 添加库
- 将工具链中的库拷贝到_install目录下
$ cp /home/linux/toolchain/arm-cortex_a8-linux-gnueabi/lib ./ -a
- 删除静态库和共享库文件中的符号表
$ rm lib/*.a
$ arm-cortex_a8-linux-gnueabi-strip lib/*
- 删除不需要的库,确保所有库大小不超过4M
$ rm lib/libstdc++*
$ du -mh lib/
10、 添加系统启动文件
在etc下添加文件inittab,文件内容如下:
#this is run first except when booting in single-user mode.
:: sysinit:/etc/init.d/rcS
# /bin/sh invocations on selected ttys
# start an "askfirst" shell on the console (whatever that may be)
::askfirst:-/bin/sh
# stuff to do when restarting the init process
::restart:/sbin/init
# stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
在etc下添加文件fstab,文件内容如下:
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
这里我们挂载的文件系统有三个proc、sysfs和tmpfs。在内核中proc和sysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持
修改内核配置:
File systems --->
Pseudo filesystems --->
[*] Virtual memory file system support (former shm fs)
[*] Tmpfs POSIX Access Control Lists
重新编译内核
在etc下创建init.d目录,并在init.d下创建rcS文件,rcS文件内容为:
#!/bin/sh
# This is the first script called by init process
/bin/mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
为rcS添加可执行权限:
$ chmod +x init.d/rcS
在etc下添加profile文件,文件内容为:
#!/bin/sh
export HOSTNAME=farsight
export USER=root
export HOME=root
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
11、 设备文件创建
根文件系统中有一个设备节点是必须的,在dev下创建console节点
$ sudo mknod dev/console c 5 1
重要:新制作的文件系统尺寸若超出8M,删除不需要的库文件
二、NFS测试
1、删除原先的/source/rootfs
$ sudo rm -rf /source/rootfs
2、将我们新建的根文件系统拷贝到/source/rootfs目录下
$sudo mkdir /source/rootfs
$ sudo cp _install/* /source/rootfs –a
3、设置uboot环境变量
# setenv bootcmd tftp 20008000 zImage\; go 20008000
# setenv bootargs root=nfs nfsroot=192.168.1.100:/source/rootfs init=/linuxrc console=ttySAC0,115200 ip=192.168.1.200
# saveenv
重新启动开发板,查看是否能够正常挂载,功能是否正常
将NANDFLASH的用户文件系统分区以yaffs2的方式挂载到/mnt目录下:
在/etc/init.d/rcS添加:
mount -t yaffs2 /dev/mtdblock3 /mnt
这样,就可以以yaffs2文件系统的方式管理nandflash的第四个分区(0~3)了。当然这里的yaffs2也可以换成cramfs、jffs2。但前提是linux内核支持该文件系统。
三、制作ramdisk文件系统
通过NFS测试以后,就可以制作ramdisk文件系统了,具体如下:
1、制作一个大小为8M的镜像文件
$ cd ~
$ dd if=/dev/zero of=initrd.img bs=1k count=8192 (initrd.img为8M)
2、格式化这个镜像文件为ext2
$ mkfs.ext2 -F initrd.img
3、在mount下面创建initrd目录作为挂载点
$ sudo mkdir /mnt/initrd
4、将这个磁盘镜像文件挂载到/mnt/initrd下
注意这里的initrd.img不要和ubuntu根目录下的initrd.img弄混了,同时initrd.img不能存放在rootfs目录中
$ sudo mount -t ext2 -o loop initrd.img /mnt/initrd
5、将我们的文件系统复制到initrd.img中
将测试好的文件系统里的内容全部拷贝到 /mnt/initrd目录下面
$ sudo cp /source/rootfs/* /mnt/initrd –a
6、卸载initrd
$ sudo umount /mnt/initrd
7、压缩initrd.img为initrd.img.gz并拷贝到/tftpboot下
$ gzip --best -c initrd.img > initrd.img.gz
$ cp initrd.img.gz /tftpboot
8、配置内核支持RAMDISK
制作完 initrd.img.gz后,需要配置内核支持RAMDISK作为启动文件系统
Device Drivers
SCSI device support --->
<*> SCSI disk support
Block devices --->
<*>RAM block device support
(1)Default number of RAM disks
(8192) Default RAM disk size (kbytes) (修改为8M)
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
重新编译内核,复制到/tftpboot
9、在U-BOOT命令行重新设置启动参数:
# setenv bootcmd tftp 20008000 zImage \; tftp 20800000 initrd.img.gz \; go 20008000
# setenv bootargs root=/dev/ram rw init=/linuxrc initrd=0x20800000,8M console=ttySAC0,115200
# saveenv
重新启动开发板查看能否正常启动
四、制作cramfs文件系统
1、cramfs文件系统镜像制作
由于系统提供制作cramfs文件系统的工具,可以直接使用。具体操作如下;
$ mkfs.cramfs /source/rootfs rootfs.cramfs
2、将rootfs.cramfs拷贝到/tftpboot目录下
$ sudo cp rootfs.cramfs /tftpboot
3、将rootfs.cramfs烧写到nand flash的第三个分区上
u-boot下执行如下命令
# tftp 20008000 rootfs.cramfs
# nand erase 400000 400000
# nand write 20008000 400000 400000
4、重新设置u-boot启动参数
# setenv bootcmd tftp 20008000 zImage\; go 20008000
# setenv bootargs root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
# saveenv
启动开发板,测试是否成功。
[root@farsight /root] # ls /
bin etc linuxrc sbin tmp var
dev lib mnt proc test usr
[root@farsight /root] # mkdir test
mkdir: Cannot create directory `test': Read-only file system
注意:cramfs格式的文件系统是只读的。
五、制作jffs2文件系统
1、配置内核支持jffs2文件系统
File systems --->
[*] Miscellaneous filesystems --->
<*> Journalling Flash File System v2 (JFFS2) support
重新编译内核并拷贝到/tftpboot下
2、zlib的编译
解压zlib-1.2.3.tar.bz2并进入zlib-1.2.3配置编译安装
$ tar xvf zlib-1.2.3.tar.bz2
$ cd zlib-1.2.3
$ ./configure
$ make
$ sudo make install
3、mtd工具编译
解压mtd-snapshot-20050519.tar.bz2 并进入mtd/util编译安装
$ tar xvf mtd-snapshot-20050519.tar.bz2
$ cd mtd/util
$ make
$ sudo make install
这样我们的系统里就有了mkfs.jffs2这个工具了
4、jffs2文件系统镜像制作
$ mkfs.jffs2 -r /source/rootfs -o rootfs.jffs2 -e 0x20000 --pad=0x400000 -n
$ sudo cp rootfs.jffs2 /tftpboot
5、jffs2文件系统烧写
# tftp 20008000 rootfs.jffs2
# nand erase 400000 400000
# nand write 20008000 400000 400000
6、设置u-boot启动参数
# setenv bootcmd tftp 20008000 zImage\; go 20008000
# setenv bootargs root=/dev/mtdblock2 rootfstype=jffs2 rw init=/linuxrc
console=ttySAC0,115200
# saveenv
重新启动开发板,查看是否成功
本文来自博客园,作者:dolinux,未经同意,禁止转载