Linux內核移植與啟動
Target borad:FL2440
Bootloader:U-boot-2010.09
交叉編譯器:buildroot-2012.08
1.linux內核基礎知識
首先,磨刀不誤砍柴工。在動手進行linux內核移植之前,我們有必要對linux內核進行一定的了解。
1.1 Linux內核啟動過程概述
一個嵌入式Linux系統從軟件角度看可以分為四個部分:
引導加載程序(Bootloader),Linux內核,文件系統,應用程序。
其中Bootloader是系統啟動或復位以后執行的第一段代碼,它主要用來初始化處理器及外設,然后調用Linux內核,linux內核在完成系統的初始化之后需要掛載某個文件系統作為根文件系統(rootfs),根文件系統是linux系統的核心組成部分,也是內核啟動時首先要掛載的就是根文件系統。它可以作為linux系統中文件和數據的存儲區域,通常它還包括系統配置文件和運行應用程序需要的庫,保證了人和內核的信息交互。應用程序則是嵌入式系統所要達到的目標,一切的准備都是為了實現程序。若是沒有應用程序,硬件上再精良嵌入式系統都沒有實用意義。
Bootloader:在嵌入式操作系統中,BootLoader是在操作系統內核運行之前運行。可以初始化硬件設備、建立內存空間映射圖,從而將系統的軟硬件環境帶到一個合適狀態,以便為最終調用操作系統內核准備好正確的環境。Bootloader在它完成CPU和相關硬件的初始化之后,再將操作系統映像或固化的嵌入式應用程序裝在到內存中然后跳轉到操作系統所在的空間,啟動操作系統運行。它最根本的功能就是為了啟動linux內核. 為了啟動內核Bootloader要依次完成
初始化RAM—初始化串口—檢測處理器類型—設置Linux啟動參數(bootargs)—調用Linux內核鏡像。
文件系統:Linux文件系統中的文件是數據的集合,文件系統不僅包含着文件中的數據而且還有文件系統的結構,所有Linux 用戶和程序看到的文件、目錄、軟連接及文件保護信息等都存儲在其中。
1.2 編譯環境交叉編譯器的制作
交叉編譯器本節不過多介紹。但我們必須知道若要實現人,虛擬機,開發板之間的信息傳遞就必須首先制作交叉編譯器來幫助我們編譯。在做好交叉編譯器准備好編譯環境之后我們就可以開始進行純內核移植了。(在此使用的交叉編譯器為buildroot-2012.08)
2.Linux內核移植與啟動
2.1下載並解壓縮linux-3.0.tar.bz2 源代碼
首先到 Linux Kernel 官方網站www.kernel.org下載得到 linux-3.0-rc4.tar.bz2 文件,把它放到一個你有權限讀寫的文件夾,運行下面命令解壓縮並進入解壓后的文件夾:
$ tar -xjf linux-3.0.tar.bz2
$ cd linux-3.0
2.2配置內核編譯參數
1. 首先修改頂層目錄的Makefile文件
$ vim Makefile
這里首要便是交叉編譯器環境變量和選擇開發平台類型
然后要將生成的zimage拷貝到當前目錄,再手動增加mkimage工具來自動把Zimage生成可執行的.bin文。
注:內核編譯之后會生成兩個文件。一個Image,一個Zimage。image為內核映像文件,而Zimage為內核映像壓縮文件。Image大約為4M,而Zimage不到2M。
===============================================================================
@@ -192,8 +192,8 @@
# Default value for CROSS_COMPILE is not to prefix executables
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
export KBUILD_BUILDHOST := $(SUBARCH)
- ARCH ?= $(SUBARCH)
- CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
+ARCH ?= arm
+CROSS_COMPILE?= /opt/buildroot-2012.08.packet/buildroot-2012.08/arm920t/usr/bin/arm-linux-
# Architecture as present in compile.h
UTS_MACHINE := $(ARCH)
@@ -557,6 +557,9 @@
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux
+ cp arch/arm/boot/zImage . -f
+ mkimage -A arm -O linux -T kernel -C none -a 30008040 -n "Linux Kernel" -d zImage \ linuxrom-s3c2440.bin
+ rm -f zImage
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os
@@ -1201,6 +1204,7 @@
-o -name '.*.rej' -o -size 0 \
-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
-type f -print | xargs rm -f
+ @rm -f linuxrom-s3c2440.bin

2.修改晶振頻率
因為我使用的是FL2440的開發板,根據datesheet可知晶振頻率為12M。所以下一步修改晶振頻率。
$ vim arch/arm/mach-s3c2440/mach-smdk2440.c
============================================================================
@@ -160,7 +160,7 @@
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
-- s3c24xx_init_clocks(16934400);
+ s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}

3. 修改驅動的串口
vim drivers/tty/serial/samsung.c
===========================================================================
@@ -54,7 +54,7 @@
/* UART name and device definitions */
-- #define S3C24XX_SERIAL_NAME "ttySAC"
+ #define S3C24XX_SERIAL_NAME "ttyS"
#define S3C24XX_SERIAL_MAJOR 204
#define S3C24XX_SERIAL_MINOR 64
打開文本窗口來選定即將要編譯的模塊,保存后會將里面的信息保存到同時生成的.config配置文件中。
另外:make menuconfig時出來的文本窗口中的信息是通過讀取在內核源代碼目錄下的Kconfig文件來配置的。根據Makefile文件來編譯,而Makefile文件中的變量則通過.config來進行賦值操作。僅僅在Kconfig中添加選項。



4.修改MACHINE ID設備編號
同樣因為是做FL2440的內核,所以我們選擇三星SMDK2440這個開發板。因為我U-boot中使用的machine id為1999,而且我使用的是s3c2440這個板子。
將mini2440和和s3c2440的machineID對調。
$ vim arch/arm/tools/mach-types

配置就緒之后
Make

顯示成功
此時已經會生成一個linux-s3c2440.bin的可執行二進制文件。
5.對nandflash進行分區

=========================================================================================================
@@ -106,49 +106,39 @@
},
};
-/* NAND parititon from 2.4.18-swl5 */
+/* NAND parititon from 2.4.18-swl5,modify by Handy 2014.11.30 */
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
- .name = "Boot Agent",
- .size = SZ_16K,
+ .name = "bootloader",
+ .size = SZ_1M,
.offset = 0,
},
[1] = {
- .name = "S3C2410 flash partition 1",
- .offset = 0,
- .size = SZ_2M,
+ .name = "linux",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_1M*15,
},
[2] = {
- .name = "S3C2410 flash partition 2",
- .offset = SZ_4M,
- .size = SZ_4M,
+ .name = "rootfs",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_1M*40,
},
[3] = {
- .name = "S3C2410 flash partition 3",
- .offset = SZ_8M,
- .size = SZ_2M,
+ .name = "apps",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_1M*50,
},
[4] = {
- .name = "S3C2410 flash partition 4",
- .offset = SZ_1M * 10,
- .size = SZ_4M,
+ .name = "data",
+ .offset = MTDPART_OFS_NXTBLK,
+ .size = SZ_1M*50,
},
[5] = {
- .name = "S3C2410 flash partition 5",
- .offset = SZ_1M * 14,
- .size = SZ_1M * 10,
- },
- [6] = {
- .name = "S3C2410 flash partition 6",
- .offset = SZ_1M * 24,
- .size = SZ_1M * 24,
- },
- [7] = {
- .name = "S3C2410 flash partition 7",
- .offset = SZ_1M * 48,
+ .name = "backup",
+ .offset = SZ_1M * 100,
.size = MTDPART_SIZ_FULL,
- }
+ },
};

板子上nandflash是256M,給bootloader1M用來啟動,內核15M以及40M的根文件系統。其他自由分配。
注意:此時若要再進行分區就要選擇相應的文件系統。Nandflash比較常用的有yaffs2,ubifs,cramfs以及initramfs等等。
$ make
此時能編譯成功,但是生成的linux-s3c2440.bin文件依舊不能在板子上跑起來。
因為內核啟動時首先掛載的是根文件系統,我們還沒有做根文件系統給予內核支持,系統會出錯而退出啟動。
3. 添加根文件系統支持
1、根文件系統簡介
文件系統是對一個存儲設備上的數據和元數據進行組織的機制。這種機制有利於用戶和操作系統的交互。而根文件系統則是所有文件系統的根,我理解的是所有文件系統都是由根文件系統擴展開來的。而若是沒有根文件系統則談不上其他的文件系統。根文件系統它包含系統引導以及其他文件系統所能掛載的必要文件。
什么是根文件系統?首先是一種文件系統,但是相對於普通的文件系統,它的特殊之處在於,它是內核
啟動時所mount的第一個文件系統。
而Linux又支持多種文件系統,包括ext2、ext3、vfat、ntfs、iso9660、jffs、romfs和nfs等,為了對各類文件系統 進行統一管理,Linux引入了虛擬文件系統VFS(Virtual File System),為各類文件系統提供一個統一的操作界面和應用編程接口。Linux啟動時,第一個必須掛載的是根文件系統;若系統不能從指定設備上掛載根文件系統,則系統會出錯而退出啟動。之后可以自動或手動掛載其他的文件系統。因此,一個系統中可以同時存在不同的文件系統。
不同的文件系統類型有不同的特點,因而根據存儲設備的硬件特性、系統需求等有不同的應用場合。在嵌入式Linux應用中,主要的存儲設備為 RAM(DRAM, SDRAM)和ROM(常采用FLASH存儲器),常用的基於存儲設備的文件系統類型包括:jffs2, yaffs, cramfs, romfs, ramdisk, ramfs/tmpfs等。
2、根文件系統支持
本文主要寫內核的移植與啟動,所以選擇了制作很簡單的initramfs文件系統作為根文件系統,它能伴隨內核編譯時同時與內核生成一個鏡像而能與之一起啟動。
$ Make menuconfig
進去選擇General setup編譯模塊
在下面選擇Initial RAM filesystem .....即initramfs文件系統,然后選擇支持initramfs的源文件系統包所處位置。這里為../../rootfs/rootfs_tree/


在選擇保存后即可連接開發板。重新編譯內核后下載到板子上便可以啟動了!


