Linux-2.6.32.2核心在mini2440上的移植(一)—構建自主開發環境

來源:互聯網
上載者:User

Linux-2.6.32.2核心在mini2440上的移植(一)---構建自主開發環境

移植環境(紅色粗字型字為修改後內容,藍色粗體字為特別注意內容)

1,主機環境:VMare下Fedora10 ,1G記憶體。

2,編譯編譯環境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。

3,開發板:mini2440,4M nor flash,64M nand flash。

4,linux 版本:linux-2.6.32.2

5,參考文章:

【1】嵌入式linux應用開發完全手冊,韋東山,編著。

【2】http://blogold.chinaunix.net/u3/101649/showart_2276906.html

 【3】Mini2440 之Linux 移植開發實戰指南

1.1,構建自主開發環境

我們在進行u-boot移植時,在u-boot-2009.08在mini2440上的移植(六)---增加引導核心功能提到過機器碼(MACH_TYPE),在引導測試時,為了便於測試,使用的是友善官方移植好的linux核心。現在我們將從這裡著手,逐步開始linux核心的移植。

【1】下載並解壓核心源碼

在命令列終端中可以通過下列方式下載,當然用其它下載工具下載

[root@localhost ~]# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.gz

然後解壓:

[root@localhost ~]# cd ./linux-test/
[root@localhost linux-test]# tar -zxf ../linux-2.6.32.2.tar.gz
[root@localhost linux-test]# ls
linux-2.6.32.2  linux-2.6.39  yaffs2  yaffs2.tar.gz
[root@localhost linux-test]# cd linux-2.6.32.2
[root@localhost linux-2.6.32.2]# 

【2】指定交叉編譯變數

我們移植目的是讓 Linux-2.6.32.2 可以在mini2440 上運行。首先,我們要使得Linux-2.6.32.2 的預設目標平台成為ARM 的平台,修改總目錄下的Makefile。

用gedit開啟/Makefile,定位到183行,修改如下:

# Alternatively CROSS_COMPILE can be set in the environment.
# 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  ?= arm
CROSS_COMPILE ?= arm-linux-

# Architecture as present in compile.h

其中,ARCH 是指定目標平台為arm,CROSS_COMPILE 是指定交叉編譯器,這裡指定的是系統預設的交叉編譯器,如要使用其它的,則要把編譯器的全路徑在這裡寫出。注意,在arm和arm-linux-後不要留空格,否則在編譯時間會出現錯誤。

接下來,要測試一下linux 的編譯是否能正常通過。執行:
[root@localhost linux-2.6.32.2]# make s3c2410_defconfig

使用預設核心設定檔,s3c2410_defconfig 是SMDK2440 的預設設定檔
[root@localhost linux-2.6.32.2]# make

編譯時間較長... ... 。編譯通過,在此我們先不必燒寫到開發板驗證它的正確性。

【3】建立自己的目標平台

(1)關於機器碼

以上編譯是用的 Linux 核心本身支援的目標平台配置,它對應於SMDK2440。現在我們要參考SMDK2440 加入自已的開發板平台,我們使用的是mini2440,因此取名為MINI2440。需要說明的是,Linux-2.6.32.2 本身已經包含了mini2440 的支援,這樣就出現了重名。那怎麼辦呢?在此我們依然使用MINI2440 這個名稱,只不過在後面的移植步驟中,把原始核心內建的mini2440 代碼部分直接刪除就可以了,以免和我們自己移植的混淆。

首先,很關鍵的一點,核心在啟動時,是通過bootloader 傳入的機器碼(MACH_TYPE)確定應啟動哪種目標平台的,友善之臂已經為mini2440 申請了自己的機器碼為1999,它位於linux-2.6.32.2/arch/arm/tools/mach_types 檔案中,如下面所示:

開啟/arch/arm/tools/mach-types,定位到1989行,可以看到檔案中有相應的機器碼的定義定義如下(黑體部分):
exeda   MACH_EXEDA  EXEDA   1994
mx31sf005  MACH_MX31SF005  MX31SF005  1995
f5d8231_4_v2  MACH_F5D8231_4_V2 F5D8231_4_V2  1996
q2440   MACH_Q2440  Q2440   1997
qq2440   MACH_QQ2440  QQ2440   1998
mini2440  MACH_MINI2440  MINI2440  1999
colibri300  MACH_COLIBRI300  COLIBRI300  2000
jades   MACH_JADES  JADES   2001
spark   MACH_SPARK  SPARK   2002
benzina   MACH_BENZINA  BENZINA   2003

在U-boot/include/asm-arm/mach-types.h 檔案的1985行附近(u-boot-2009.08),可以看到mini2440 的機器碼定義如下面所示:

#define MACH_TYPE_Q2440 1997
#define MACH_TYPE_QQ2440 1998
#define MACH_TYPE_MINI2440 1999  //mini2440的機器碼
#define MACH_TYPE_COLIBRI300 2000
#define MACH_TYPE_JADES 2001

這需要兩者相匹配,如果核心的機器碼和bootloader 傳入的不匹配,就會經常出現下面的錯誤:
Uncompressing Linux................................................................................................................................. done, booting
the kernel.
運行到這不就停住了。

接下來, 我們注意到linux-2.6.32.2/arch/arm/mach-s3c2440 目錄下有個mach-mini2440.c 檔案,它其實就是國外愛好者為mini2440 移植添加的主要內容了,但我們不用它,把它直接刪除。將linux-2.6.32.2/arch/arm/mach-s3c2440/目錄下的mach-smdk2440.c 複製一份。命名為mach-mini2440.c ,並開啟檔案定位到末尾處,找到

MACHINE_START(S3C2440, "SMDK2440") , 將其修改為
MACHINE_START(MINI2440, "Mini2440 development board")
提示:開發板運行後,在命令列終端輸入:cat /proc/cpuinfo 可以看到我們添加的開發板資訊,當然這個資訊可以定製成我們需要的資訊。

(2)修改時鐘源頻率

在上面我們剛剛複製並修改過的mach-mini2440.c檔案中,定位到163行附近,把其中的16934400(代表原SMDK2440 目標板的晶振是16.9344MHz)改為mini2440 開發板上實際使用的12000000(代表mini2440 開發板上的晶振12MHz,元器件標號為X2),如下所示:

static void __init smdk2440_map_io(void)
{
 s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
 s3c24xx_init_clocks(12000000);
 s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}

(3)從SMDK2440 到MINI2440

因為我們要製作自己的mini2440 平台體系,因此把mach-mini2440.c 中所有的smdk2440 字樣改為mini2440,可以使用批處理命令修改,在vim 的命令模式下輸入:

%s/smdk2440/mini2440/g
上面這句的意思是:把所有和“smdk2440”匹配的字串全部替換為“mini2440”,前面的“%s“代表字串匹配,最後的“g”代表global,是全域的意思,不過這裡採用另一種辦法,在gedit裡用尋找替換,比較方便,操作如下:

gedit->搜尋->替換,在開啟的對話方塊中,在搜尋一欄輸入“smdk2440”,在替換為一欄輸入“mini2440”然後點擊全部替換按鈕,即可完成。

除此之外,還有一個地方需要改動,在mini2440_machine_init(void)函數中,把smdk_machine_init()函數調用注釋掉,因為我們後面會編寫自己的初始化函數,不需要調用smdk2440 原來的,定位到173行,修改如下:

static void __init mini2440_machine_init(void)
{
 s3c24xx_fb_set_platdata(&mini2440_fb_info);
 s3c_i2c0_set_platdata(NULL);

 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
 //smdk_machine_init();
}

(4)編譯測試

在 Linux 原始碼根目錄下執行

[root@localhost linux-2.6.32.2]# make mini2440_defconfig 
#
# configuration written to .config
#
[root@localhost linux-2.6.32.2]# make mini2440_defconfig

 使用Linux 官方內建的mini2440 配置。
[root@localhost linux-2.6.32.2]# make zImage

 編譯核心,時間較長,最後會產生zImage。把產生的核心檔案zImage(位於arch/arm/boot 目錄)下載到板子的記憶體中運行,可以看到核心已經可以正常啟動了,如下所示,但此時大部分硬體驅動還沒加,並且也沒有檔案系統,因此還無法登陸。

... ...

【4】核心配置菜單中的mini2440 選項和實際代碼是如何關聯的

在開始移植其他驅動之前,我們再瞭解一些看起來比較“神秘”的常識,那就是運行make menuconfig 時,核心配置菜單中的mini2440 選項是如何出現的。需要確保前面已經執行了make mini2440_defconfig 載入了預設配置,因為在x86平台下下執行此操作,系統預設的是x86平台,而且還要在頂層Makefile裡作了如下修改:

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH  ?= arm
CROSS_COMPILE ?= arm-linux-

現在在終端中進入到linux-2.6.32.2根目錄下執行:

[root@localhost linux-2.6.32.2]# make menuconfig

出現所示核心配置根菜單

 按上下方向鍵移動到 System Type,按斷行符號進入該子功能表,

  再找到S3C2440 Machines,按斷行符號進入該子功能表,

在此就可以看到 Linux 天生核心對mini2440 開發板的支援選項了,那麼它們是從哪裡來的呢?
開啟 Linux-2.6.32.2/arch/arm/mach-s3c2440/Kconfig 檔案定位到99行附近,可以找到如下資訊(黑體部分):

config MACH_AT2440EVB
 bool "Avantech AT2440EVB development board"
 select CPU_S3C2440
 select S3C_DEV_USB_HOST
 select S3C_DEV_NAND
 help
   Say Y here if you are using the AT2440EVB development board

config MACH_MINI2440
 bool "MINI2440 development board"
 select CPU_S3C2440
 select EEPROM_AT24
 select LEDS_TRIGGER_BACKLIGHT
 select SND_S3C24XX_SOC_S3C24XX_UDA134X
 select S3C_DEV_NAND
 select S3C_DEV_USB_HOST
 help
   Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
   available via various sources. It can come with a 3.5" or 7" touch LCD.

endmenu

現在明白了吧,“MINI2440 development board”正是在這個Kconfig 檔案中定義說明的,當然你可以根據自己的喜好改為其他顯示資訊。這裡的顯示資訊只是在核心配置菜單中出現的,要讓選擇的配置實際起效,還需要根據此配置在Makefile 中添加相應的代碼檔案,請看該目錄下的Makefile,定位到25行,如下所示:

 # Machine support

obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o

這樣,設定檔就跟實際的代碼檔案通過配置定義聯絡在一起了,這裡的配置定義是“CONFIG_MACH_MINI2440”,核心中還有很多類似的配置定義,並且有的配置定義還存在依賴關係,我們在此就不對它們詳細說明了,隨著對核心代碼結構的不斷熟悉,你就會逐漸學會分析和尋找你所需要的各種配置和定義等。

【5】移植Nand 驅動並更改分區資訊

(1)修改Nand Flash 分區表

系統預設的分區不一定是我們所需的,所以要自已修改,除此之外,還有 Nand Flash的結構資訊需要增加填寫,以便能夠適合系統內建的Nand Flash 驅動介面,這可以參考SMDK2440 中關於Nand Flash 裝置註冊的一些資訊。
開啟/arch/arm/plat-s3c24xx/common-smdk.c,定位到110行附近,可以看到這樣一個結構體:

static struct mtd_partition smdk_default_nand_part[] = {
 [0] = {
  .name = "Boot Agent",
  .size = SZ_16K,
  .offset = 0,
 },
 [1] = {
  .name = "S3C2410 flash partition 1",
  .offset = 0,
  .size = SZ_2M,
 },
 [2] = {
  .name = "S3C2410 flash partition 2",
  .offset = SZ_4M,
  .size = SZ_4M,
 },
 [3] = {
  .name = "S3C2410 flash partition 3",
  .offset = SZ_8M,
  .size = SZ_2M,
 },
 [4] = {
  .name = "S3C2410 flash partition 4",
  .offset = SZ_1M * 10,
  .size = SZ_4M,
 },
 [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,
  .size = SZ_16M,
 }
};

這其實就是Nand Flash 的分區表,在Linux-2.6.32.2 中,nand 驅動是被註冊為平台裝置的,這同樣可在這個檔案的166行看到如下資訊:

static struct s3c2410_platform_nand smdk_nand_info = {
 .tacls  = 20,
 .twrph0  = 60,
 .twrph1  = 20,
 .nr_sets = ARRAY_SIZE(smdk_nand_sets),
 .sets  = smdk_nand_sets,
};

參考以上結構資訊,我們也在自己的mach-mini2440.c 中照此添加實現,同時需要參考友善之臂原廠核心中的Nand 分區表,操作如:

開啟/arch/arm/mach-s3c2440/mach-mini2440.c,定位到151行處,將下面更改後的分區表定義結構加入其中:

 .lpcsel  = ((0xCE6) & ~7) | 1<<4,
};

/* NAND parititon from 2.4.18-swl5 */

static struct mtd_partition mini2440_default_nand_part[] = {
 [0] = {
  .name = "boot", 
//;這裡是bootloader 所在的分區,可以放置u-boot, supervivi 等內容,對應/dev/mtdblock0
  .offset = 0,
  .size = 0x00040000, //256K
 },
 [1] = {
  .name = "param", 
//;這裡是supervivi 的參數區,其實也屬於bootloader 的一部分,如果u-boot 比較大,可以把此地區覆蓋掉,不會影響系統啟動,對應/dev/mtdblock1
  .offset = 0x00040000,
  .size = 0x00020000,
 },
 [2] = {
  .name = "kernel", 
//;核心所在的分區,大小為5M,足夠放下大部分自己定製的巨型核心了,比如核心使用了更大的Linux Logo 圖片等,對應/dev/mtdblock2
  .offset = 0x00060000,
  .size = 0x00500000,
 },
 [3] = {
  .name = "rootfs", 
//;檔案系統分區,友善之臂主要用來存放yaffs2 檔案系統內容,對應/dev/mtdblock3
  .offset = 0x00560000,
  .size = 1024 * 1024 * 1024,
 },
 [4] = {
  .name = "nand", 
//;此地區代表了整片的nand flash,主要是預留使用,比如以後可以通過應用程式訪問讀取/dev/mtdblock4 就能實現備份整片nand flash 了。
  .offset = 0x00000000,
  .size = 1024 * 1024 * 1024,
 } 
};

//;這裡是開發板的nand flash 設定表,因為板子上只有一片,因此也就只有一個表
static struct s3c2410_nand_set mini2440_nand_sets[] = {
 [0] = {
  .name  = "NAND",
  .nr_chips = 1,
  .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),
  .partitions = mini2440_default_nand_part,
 },
};

/* choose a set of timings which should suit most 512Mbit
 * chips and beyond.
*/
//;這裡是nand flash 本身的一些特性,一般需要對照datasheet 填寫,大部分情況下按照以下參數填寫即可
static struct s3c2410_platform_nand mini2440_nand_info = {
 .tacls  = 20,
 .twrph0  = 60,
 .twrph1  = 20,
 .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
 .sets  = mini2440_nand_sets,
 .ignore_unset_ecc = 1,
};
除此之外,還需要把nand flash 裝置註冊到系統中

static struct platform_device *mini2440_devices[] __initdata = {
 &s3c_device_usb,
 &s3c_device_lcd,
 &s3c_device_wdt,
 &s3c_device_i2c0,
 &s3c_device_iis,
 &s3c_device_nand, //;把nand flash 裝置添加到開發板的裝置列表結構
};
(3)加入編譯標頭檔

在上面的檔案中定位到50行附近,加入一下標頭檔:

#include <linux/mtd/mtd.h> 
#include <linux/mtd/nand.h> 
#include <linux/mtd/nand_ecc.h> 
#include <linux/mtd/partitions.h> 
#include <plat/nand.h>

(4)傳入mini2440_nand_info結構體初始化參數

定位到223行附近,修改如下:

static void __init mini2440_machine_init(void)
{
  s3c_i2c0_set_platdata(NULL);
 s3c_device_nand.dev.platform_data = &mini2440_nand_info; 
 platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
 //smdk_machine_init();
}

然後儲存。

1.2,編譯測試

至此,就完成了nand flash 驅動的移植,修改完成之後,最好在每次進行make menuconfig後都有執行

[root@localhost linux-2.6.32.2]# make clean

因為核心中已經可能已經增減了要編譯的模組,所以要在編譯之前清除下已編譯的目標模組,不然可能編譯出錯,然後進行編譯:

[root@localhost linux-2.6.32.2]# make zImage

編譯完成後,產生zImage檔案,然後給開發板上電,然後把zImage燒寫到開發板裡,看到如下資訊:

S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns
s3c24xx-nand s3c2440-nand: NAND soft ECC
NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit)
Scanning device for bad blocks
Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit":
0x000000000000-0x000000040000 : "boot"
uncorrectable error :
0x000000040000-0x000000060000 : "param"
ftl_cs: FTL header not found.
0x000000060000-0x000000560000 : "kernel"
ftl_cs: FTL header not found.
0x000000560000-0x000040560000 : "root"
mtd: partition "root" extends beyond the end of device "NAND 128MiB 3,3V 8-bit"
-- size truncated to 0x7aa0000
ftl_cs: FTL header not found.
0x000000000000-0x000040000000 : "nand"
mtd: partition "nand" extends beyond the end of device "NAND 128MiB 3,3V 8-bit"
-- size truncated to 0x8000000
uncorrectable error :
dm9000 Ethernet Driver, V1.31
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected

可以在啟動時看到藍色資訊,它們正是我們剛剛添加的nand flash 分區資訊,以及開發板本身nand flash 的一些資訊,這裡可以看到是128M 的nand flash。

.. ....

rpcbind: server 10.1.0.128 not responding, timed out
Root-NFS: Unable to get nfsd port number from server, using default
Looking up port of RPC 100005/1 on 10.1.0.128
rpcbind: server 10.1.0.128 not responding, timed out
Root-NFS: Unable to get mountd port number from server, using default
Root-NFS: Server returned error -5 while mounting /nfsboot
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; here are the available partitions:
1f00             256 mtdblock0 (driver?)
1f01             128 mtdblock1 (driver?)
1f02            5120 mtdblock2 (driver?)
1f03          125568 mtdblock3 (driver?)
1f04          131072 mtdblock4 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
[<c002e9c0>] (unwind_backtrace+0x0/0xd8) from [<c02d4798>] (panic+0x40/0x118)
[<c02d4798>] (panic+0x40/0x118) from [<c0008e68>] (mount_block_root+0x1c8/0x208)

[<c0008e68>] (mount_block_root+0x1c8/0x208) from [<c00090fc>] (prepare_namespace
+0x160/0x1b8)
[<c00090fc>] (prepare_namespace+0x160/0x1b8) from [<c0008434>] (kernel_init+0xd8
/0x10c)
[<c0008434>] (kernel_init+0xd8/0x10c) from [<c002a868>] (kernel_thread_exit+0x0/
0x8)

這裡提示的掛在分區時出現了問題。
解決辦法:
在分區中可以把下面的代碼去掉:
 [1] = {
  .name = "param", 
//;這裡是supervivi 的參數區,其實也屬於bootloader 的一部分,如果u-boot 比較大,可以把此地區覆蓋掉,不會影響系統啟動,對應/dev/mtdblock1
  .offset = 0x00040000,
  .size = 0x00020000,
 },
根據不同情況而定,出現上面的原因也有可能是沒有為linux-2.6.32.2添加yaffs檔案系統。
摘自:http://www.cnblogs.com/hnrainll/archive/2011/06/09/2076138.html

接下來,將為linux-2.6.32.2添加yaffs檔案系統。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.