開發環境:
gcc cross compiler version: 3.4.1
開發主機:at920
開發板:Friendly-arm 2440
1 內核移植過程
1.1 下載linux內核
從http://www.kernel.org/pub/linux/kernel/v2.6/linux2.6.14.1.
tar.bz2
下載linux2.6.14.1
內核至home/arm/dev_home/kernel.
[root@localhost ~]#su arm
[arm@localhost ~]#cd $KERNEL
[arm@localhost kernel]#tar xzvf
linux2.6.14.1.
tar.gz
[arm@localhost kernel]# pwd
/home/arm/dev_home/kernel
[arm@localhost kernel]# cd linux2.6.14
進入內核解壓後的目錄,以後示例中,只要是相對路徑全部是相對於
/home/arm/dev_home/kernel/linux2.6.14/
此目錄
1.2 修改Makefile
修改內核目錄樹根下的的Makefile,指明交叉編譯器
[arm@localhost linux2.6.14]#
vi Makefile
找到ARCH和CROSS_COMPILE,修改
ARCH ?= arm
CROSS_COMPILE ?= armlinux
然後設置你的PATH環境變量,使其可以找到你的交叉編譯工具鏈
[arm@localhost linux2.6.14]#
echo $PATH
/usr/local/arm/3.4.4/bin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/ly/bin
如果/usr/local/arm/3.4.4/bin搜索路徑, 加入下面語句在~/.bashrc中
[arm@localhost linux2.6.14]#
vi ~/.bashrc
export PATH=/usr/local/arm/3.4.4/bin:$PATH
再重新登陸.
[arm@localhost linux2.6.14]#
su arm
1.3 設置flash分區
此處一共要修改3個文件,分別是:
1.3.1指明分區信息
在arch/arm/machs3c2410/
devs.c文件中:
[arm@localhost linux2.6.14]$
vi arch/arm/machs3c2410/
devs.c
添加如下內容:
#i nclude <linux/mtd/partitions.h>
#i nclude <linux/mtd/nand.h>
#i nclude <asm/arch/nand.h>
...
/* NAND Controller */
1.建立Nand Flash分區表
/* 一個Nand Flash總共64MB, 按如下大小進行分區 */
static struct mtd_partition partition_info[] ={
{ /* 1MB */
name: "bootloader",
size: 0x00100000,
offset: 0x0,
},{ /* 3MB */
name: "kernel",
size: 0x00300000,
offset: 0x00100000,
}, { /* 40MB */
name: "root",
size: 0x02800000,
offset: 0x00400000,
}, { /* 20MB */
name: "user",
size: 0x00f00000,
offset: 0x02d00000,
}
};
name: 代表分區名字
size: 代表flash分區大小(單位:字節)
offset: 代表flash分區的起始地址(相對於0x0的偏移)
目標板計劃分4個區,分別存放bootloader, kernel, rootfs以及以便以後擴展使用的用戶文件系統空間。
各分區在Nand flash中起始地址. 分區大小. 記錄如下:
bootloader:
start: 0x00000000
len: 0x00100000
1MB
kernel:
start: 0x00100000
len: 0x00300000
3MB
rootfs:
start: 0x00400000
len: 0x02800000
40MB
User:
start: 0x02c00000
len: 0x01400000
20MB
2. 加入Nand Flash分區
struct s3c2410_nand_set nandset ={
nr_partitions: 4, /* the number of partitions */
partitions: partition_info, /* partition table */
};
nr_partitions: 指明partition_info中定義的分區數目
partitions: 分區信息表
3. 建立Nand Flash芯片支持
struct s3c2410_platform_nand superlpplatform={
tacls:0,
twrph0:30,
twrph1:0,
sets: &nandset,
nr_sets: 1,
};
tacls, twrph0, twrph1的意思見S3C2410手冊的63,
這3個值最後會被設置到NFCONF中,見S3C2410手冊66.
sets: 支持的分區集
nr_set:分區集的個數
4. 加入Nand Flash芯片支持到Nand Flash驅動
另外,還要修改此文件中的s3c_device_nand結構體變量,添加對dev成員的賦值
struct platform_device s3c_device_nand = {
.name = "s3c2410nand",
/* Device name */
.id = 1,
/* Device ID */
.num_resources = ARRAY_SIZE(s3c_nand_resource),
.resource = s3c_nand_resource, /* Nand Flash Controller Registers */
/* Add the Nand Flash device */
.dev = {
.platform_data = &superlpplatform
}
};
name: 設備名稱
id: 有效設備編號,如果只有唯一的一個設備爲1,
有多個設備從0開始計數.
num_resource: 有幾個寄存器區
resource: 寄存器區數組首地址
dev: 支持的Nand Flash設備
1.3.2 指定啓動時初始化
kernel啓動時依據我們對分區的設置進行初始配置
修改arch/arm/machs3c2410/
machsmdk2410.
c文件
[arm@localhost linux2.6.14]$
vi arch/arm/machs3c2410/
machsmdk2410.
c
修改smdk2410_devices[].指明初始化時包括我們在前面所設置的flash分區信息
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
/* 添加如下語句即可 */
&s3c_device_nand,
};
保存,退出。
1.3.3 禁止Flash ECC校驗
我們的內核都是通過UBOOT寫到Nand Flash的, UBOOT通過的軟件ECC算法產生ECC校驗碼, 這與內核
校驗的ECC碼不一樣, 內核中的ECC碼是由S3C2410中Nand Flash控制器產生的. 所以, 我們在這裏選擇禁止
內核ECC校驗.
修改drivers/mtd/nand/s3c2410.c 文件:
[arm@localhost linux2.6.14]$
vi drivers/mtd/nand/s3c2410.c
找到s3c2410_nand_init_chip()函數,在該函數體最後加上一條語句:
chip>
eccmode = NAND_ECC_NONE;
保存,退出。
OK.我們的關於flash分區的設置全部完工.
1.4 配置內核
1.4.1 支持啓動時掛載devfs
爲了我們的內核支持devfs以及在啓動時並在/sbin/init運行之前能自動掛載/dev爲devfs文件系統,修改
fs/Kconfig文件
[arm@localhost linux2.6.14]$
vi fs/Kconfig
找到menu "Pseudo filesystems"
添加如下語句:
config DEVFS_FS
bool "/dev file system support (OBSOLETE)"
default y
config DEVFS_MOUNT
bool "Automatically mount at boot"
default y
depends on DEVFS_FS
1.4.2配置內核產生.config文件
[arm@localhost linux2.6.14]$
cp arch/arm/configs/smdk2410_defconfig .config
[arm@localhost linux2.6.14]$
make menuconfig
在smdk2410_defconfig基礎上,我所增刪的內核配置項如下:
Loadable module support >
[*] Enable loadable module support
[*] Automatic kernel module loading
System Type >
[*] S3C2410 DMA support
Boot options >
Default kernel command string:
noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200
#說明:mtdblock2代表我的第3個flash分區,它是我的rootfs
# console=ttySAC0,115200使kernel啓動期間的信息全部輸出到串口0上.
# 2.6內核對於串口的命名改爲ttySAC0,但這不影響用戶空間的串口編程。
# 用戶空間的串口編程針對的仍是/dev/ttyS0等
Floating point emulation >
[*] NWFPE math emulation
This is necessary to run most binaries!!!
#接下來要做的是對內核MTD子系統的設置
Device Drivers >
Memory Technology Devices (MTD) >
[*] MTD partitioning support
#支持MTD分區,這樣我們在前面設置的分區纔有意義
[*] Command line partition table parsing
#支持從命令行設置flash分區信息,靈活
RAM/ROM/Flash chip drivers >
<*> Detect flash chips by Common Flash
Interface (CFI) probe
<*> Detect nonCFI
AMD/JEDECcompatible
flash chips
<*> Support for Intel/Sharp flash chips
<*> Support for AMD/Fujitsu flash chips
<*> Support for ROM chips in bus mapping
NAND Flash Device Drivers >
<*> NAND Device Support
<*> NAND Flash support for S3C2410/S3C2440 SoC
Character devices >
[*] Nonstandard
serial port support
[*] S3C2410 RTC Driver
#接下來做的是針對文件系統的設置,本人實驗時目標板上要上的文件系統是cramfs,故做如下配置
File systems >
<> Second extended fs support #去除對ext2的支持
Pseudo filesystems >
[*] /proc file system support
[*] Virtual memory file system support (former shm fs)
[*] /dev file system support (OBSOLETE)
[*] Automatically mount at boot (NEW)
#這裏會看到我們前先修改fs/Kconfig的成果,devfs已經被支持上了
Miscellaneous filesystems >
<*> Compressed ROM file system support (cramfs)
#支持cramfs
Network File Systems >
<*> NFS file system support
保存退出,產生.config文件.
.config文件能從提供的2.4.14.1的內核包中找到,文件名爲config.back.
1.4.3編譯內核
[arm@localhost linux2.6.14]$
make zImage
注意:若編譯內核出現如下情況
LD .tmp_vmlinux1
armlinuxld:
arch/arm/kernel/vmlinux.lds:1439: parse error
make: *** [.tmp_vmlinux1] Error 1
解決方法:修改arch/arm/kernel/vmlinux.lds
[arm@localhost linux2.6.14]$
vi arch/arm/kernel/vmlinux.lds
將文件尾2條的ASSERT註釋掉(1439行)
/* ASSERT((__proc_info_end __
proc_info_begin), "missing CPU support") */
/* ASSERT((__arch_info_end __
arch_info_begin), "no machine record defined") */
然後重新make zImage即可
1.4.4 下載zImage到開發板
CRANE2410 # tftp 0x30008000 zImage
TFTP from server 192.168.1.6; our IP address is 192.168.1.5
Filename 'zImage'.
Load address: 0x30008000
Loading: #################################################################
#################################################################
#################################################################
#############################
done
Bytes transferred = 1142856 (117048 hex)
CRANE2410 # bootm 0x30008000
1.4.5 目標板啓動信息如下
U-Boot 1.1.6 (Mar 8 2007 - 14:47:53)
DRAM: 64 MB
Flash: 1 MB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
[ ~ljh@GDLC ]# loady
## Ready for binary (ymodem) download to 0x33000000 at 115200 bps...
C0(STX)/0(CAN) packets, 6 retries
## Total Size = 0x000f5ec4 = 1007300 Bytes
[ ~ljh@GDLC ]# bootm
## Booting image at 33000000 ...
Image Name: Linux-2.6.14
Created: 2007-03-09 5:17:52 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1007236 Bytes = 983.6 kB
Load Address: 30008000
Entry Point: 30008000
Verifying Checksum ... OK
OK
Starting kernel ...
Uncompressing Linux.................................................................... done, booting the kernel.
Linux version 2.6.14 ([email protected]) (gcc version 3.3.2) #3 Fri Mar 9 10:52:49 CST 2007
CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410 (id 0x32410000)
S3C2410: core 200.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
S3C2410 Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists
Kernel command line: console=ttySAC0 root=/dev/nfs nfsroot=10.1.8.246:/friendly-arm/rootfs_netserv ip=10.1.8.245:10.1.8.246:f
irq: clearing subpending status 00000002
PID hash table entries: 512 (order: 9, 8192 bytes)
timer tcon=00500000, tcnt a2c1, tcfg 00000200,00000000, usec 00001eb8
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 64MB = 64MB total
Memory: 62592KB available (1694K code, 386K data, 96K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
softlockup thread 0 started up.
NET: Registered protocol family 16
S3C2410: Initialising architecture
S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics
DMA channel 0 at c4800000, irq 33
DMA channel 1 at c4800040, irq 34
DMA channel 2 at c4800080, irq 35
DMA channel 3 at c48000c0, irq 36
NetWinder Floating Point Emulator V0.97 (double precision)
devfs: 2004-01-31 Richard Gooch ([email protected])
devfs: boot_options: 0x1
Console: switching to colour frame buffer device 80x25
fb0: Virtual frame buffer device, using 1024K of video memory
S3C2410 RTC, (c) 2004 Simtec Electronics
s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410-nand: mapped registers at c4980000
s3c2410-nand: timing: Tacls 10ns, Twrph0 40ns, Twrph1 10ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
NAND_ECC_NONE selected by board driver. This is not recommended !!
Scanning device for bad blocks
Bad eraseblock 4080 at 0x03fc0000
Creating 4 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00100000 : "bootloader"
0x00100000-0x00400000 : "kernel"
0x00400000-0x02c00000 : "root"
0x02d00000-0x03c00000 : "user"
mice: PS/2 mouse device common for all mice
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
IP-Config: Device `eth0' not found.
Looking up port of RPC 100003/2 on 10.1.8.246
RPC: sendmsg returned error 101
portmap: RPC call returned error 101
Root-NFS: Unable to get nfsd port number from server, using default
Looking up port of RPC 100005/1 on 10.1.8.246
RPC: sendmsg returned error 101
portmap: RPC call returned error 101
Root-NFS: Unable to get mountd port number from server, using default
RPC: sendmsg returned error 101
Root-NFS: Server returned error -101 while mounting /friendly-arm/rootfs_netserv
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "nfs" or unknown-block(2,0)
Please append a correct "root=" boot option
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
2 創建uImage
2.1 相關技術背景介紹
前面已經介紹了內核編譯後,生成zImage的內核鏡像文件。該鏡像文件可以通過UBOOT
提供的go命令,
跳轉執行,引導內核。同時在uboot1.1.4
的tools目錄下,提供了生成uImage的工具mkimage命令,在生成
uboot
的二進制鏡像文件的同時,mkimage命令會同時編譯生成,無需另外編譯。通過mkimage命令,在
zImage中加入頭文件(鏡像頭長0x40,真正的內核入口向後偏移了0x40大小),生成uImage鏡像文件,該文
件就是執行bootm所需的內核鏡像文件。
2.2 在內核中創建uImage的方法
2.2.1 獲取mkimage工具
2.6內核樹的Makefile提供了創建uImage的方法,但需要我們提供相應的mkimage命令。
所以首先拷貝uboot
中tools目錄下編譯後生成的mkimage到/usr/bin/下,然後便可以在內核根目錄下通過
make uImage
來創建uImage文件。該文件生成在arch/arm/boot/下。
常見問題及解決方法:
1. Linux內核啓動時出現:bad machine ID,原因大致是u-boot傳遞給內核的machine ID錯誤,可以手動在內核源代碼中添加machine ID.
解決方法:
在U-boot命令行中輸入
bdinfo
查看板卡信息,我的輸出如下:
[ ~ljh@GDLC ]# bdinfo
arch_number = 0x000000C1
env_t = 0x00000000
boot_params = 0x30000100
DRAM bank = 0x00000000
-> start = 0x30000000
-> size = 0x04000000
ethaddr = 08:00:3E:26:0A:5B
ip_addr = 10.1.8.245
baudrate = 115200 bps
可以看出arch_number爲0xC1, 接着編輯內核中的arch/arm/boot/compressed/head.S文件,修改
1: mov r7, r1 @save architecture ID
改爲(arch/arm/tools/mach-types,您所使用的machine type)
1: mov r7, 0xC1 @save architecture ID
從新編譯內核即可
移植到開發板,啓動。
PS:可能會遇到Uncompressing Linux................................................................ done, booting the kernel.就不動了的錯誤。原因很簡單,命令行的console參數錯了,應該爲console=ttySAC0,不是console=ttyS0。
因爲2.6對2410的串口支持已經很好了,使用默認配置的話就不要去懷疑串口驅動了,問題出在命令行上。有人說我將默認的命令行改成了console=ttySAC0也還是不行。這隻能說明改動了默認的命令行,只有在bootloader沒有傳遞命令行參數給內核的時候才起作用。如果你的bootloader傳遞命令行參數給內核了,則在bootloader中將命令行改了就行了。例如:“console=ttySAC0,115200 root=/dev/ram init=/linuxrc rw initrd=0x30008000,0x320000 ”。
因爲燒寫bootloader麻煩,時間長,調試階段不建議修改bootloader。我將內核中的arch/arm/kernel/setup.c文件中的parse_tag_cmdline()函數中的內容註釋掉,並且配置正確的CONFIG_CMDLINE參數,即可運行。以後每當改變內核參數只要改變CONFIG_CMDLINE就可以了。(CONFIG_CMDLINE這個值可以在make menuconfig中配置,2.6.11版本和2.6.14版本配置位置有所不同,請注意)。
也許你按上面的方法還是不行,那你就得改bootloader了,一般在BIOS的SRC/NAND.C文件中定義的,把裏面的命令和相關命令註釋掉,再按上面的方法。(爲什麼要註釋掉,我想你不可能只想用一個內核吧!!這樣做就可以在內核中隨便修改參數了。。。)