【FL2400】Linux3.0 內核移植 一

接觸arm + Linux已經將近兩年了,之前都是站在大神的肩膀上來移植linux內核,對很對要求移植的東西都不是很懂!爲了進一步深入對內核的瞭解,我決定重新從頭開始對linux內核進行移植。這次移植完全是從一個新手的角度進行移植,包括可能出現的問題,以及出現的問題如何解決。

環境:

操作系統: CentOS 6.2 

編譯環境:gcc version 4.3.6 (Buildroot 2011.11) 

開發板    : 飛凌2440(s3c2440)(arm920t)

u-boot    :u-boot-2010.09(MACHID = 1999)

Linux內核:linux-3.0

【在移植之前,以上環境都是配置好的,包括u-boot-2010.09已經可以在板子上運行的】


linux內核已經給我們提供了許多已經配置好的config文件,在arch/arm/configs/下,我們選一個跟我們比較像s3c2410_defconfig的進行配置;

make menuconfig進入配置模式-->Load an Alternate Configuration File-->在裏面輸入需要的具體路徑:arch/arm/configs/s3c2410_defconfig-->退出並保存

由於裏面他自動加載的模塊太多了,我們需要去掉大部分,也就是傳說中的系統裁剪,接着make menuconfig進入配置模式。這個就自己根據英文意思進行選擇,我就說一個地方,在System Type 裏面,如果不進行稍微的裁剪,他會編譯適合大部分內核,如果你只想編譯適合你自己的,在System MMU下面把除S3C2440的選項都去掉!make完成之後,內核已經制作完成了,當然還需要uboot的mkimage工具將內核按照一定格式壓縮

mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d zImage uImage-s3c2440.gz
Image Name:   Linux Kernel
Created:      Tue Aug 12 09:26:51 2014
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    1984356 Bytes = 1937.85 kB = 1.89 MB
Load Address: 30008000
Entry Point:  30008040
【注:mkimage工具在uboot編譯成功之後,就會在tools文件夾下面生成】

生成的uImage-s3c2440.gz放入tftp服務器裏面,然後進入uboot的debug模式,用tftp命令將編譯好的內核下載到SRAM上:

tftp 30008000 uImage-s3c2440.gz;bootm 30008000
這裏的地址一定要跟上面mkimage的參數一致。我特意測試了一下,如果不一致的效果:

[ fl2440@chenzhenwei ]# tftp 30009000 uImage-s3c2440.gz;bootm 30009000
dm9000 i/o: 0x20000300, id: 0x90000a46 
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:6b
could not establish link
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 192.168.1.2; our IP address is 192.168.1.244
Filename 'uImage-s3c2440.gz'.
Load address: 0x30009000
Loading: T #################################################################
         #################################################################
         ######
done
Bytes transferred = 1984420 (1e47a4 hex)
## Booting kernel from Legacy Image at 30009000 ...
   Image Name:   Linux Kernel
   Created:      2014-08-12   1:26:51 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1984356 Bytes = 1.9 MiB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   Loading Kernel Image from 30009040 to 30008000... OK
OK
OS entry point: 30008040
Image entry point=30008040
這樣,下載完成之後,如果你之前的uboot的MACHID跟你LINUX內核的ID是一樣的話,那內核就可以正常啓動了,當然我沒有那麼幸運,上面我已經說過了,我UBOOT的MACHID是1999。而內核默認的MACHID爲000016a。所以就出現如下後果(提示MACHID不支持):

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

Error: unrecognized/unsupported machine ID (r1 = 0x33edffc4).

Available machine support:

ID (hex)        NAME
0000016a        SMDK2440
0000043c        SMDK2443

Please check your kernel config and/or bootloader.
那麼我們需要把mach-type的id改下:

[09:42:50 @ linux-3.0 ]$ vim arch/arm/tools/mach-types

s3c2440         ARCH_S3C2440        S3C2440         362
將362改爲1999即可,重新編譯,加載內核,這裏說個小技巧,由於我們要不停測試內核,如果一個勁的往Nand Flash上不斷擦除讀寫,很麻煩,浪費時間,而且還減少nandflash的使用壽命,所以正確的調試方法是,直接將內核下載到指定的地址空間上,直接運行,我上面就是使用這種方法!

修改完之後,make,make image,下載,運行之後就沒有上面那個狀況了,但是他就停在這裏不輸出了:

[ fl2440@chenzhenwei ]# run tb
dm9000 i/o: 0x20000300, id: 0x90000a46 
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:6b
could not establish link
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 192.168.1.2; our IP address is 192.168.1.244
Filename 'uImage-s3c2440.gz'.
Load address: 0x30008000
Loading: T #################################################################
         #################################################################
         ######
done
Bytes transferred = 1984424 (1e47a8 hex)
## Booting kernel from Legacy Image at 30008000 ...
   Image Name:   Linux Kernel
   Created:      2014-08-12   1:51:01 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1984360 Bytes = 1.9 MiB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK
OK
OS entry point: 30008040
Image entry point=30008040

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
注: 這裏的tb是我在uboot裏面定義的一個變量,變量內容(tb=tftp 30008000 uImage-s3c2440.gz;bootm 30008000)這樣我就不用每次輸入那麼多了;
但是我驚奇的發現我的班長的lcd已經有一個小企鵝了,雖然小企鵝殘缺不全?據目前推測是因爲驅動參數沒有設置好,後期我們再設置,現在先來說說接下來串口沒有打印內核信息了。

uboot的有個bootargs參數,我們先來看看這個參數,這個參數是傳給內核使用的,你也可以再make menuconfig裏面設置這個參數(Boot options --> ()  Default kernel command string)

bootargs=console=ttyS0,115200 mem=64M initrd=0x30800000,16M root=/dev/ram0 rw loglevel=7

這裏的console口ttyS0,內核既然沒有輸出,那麼他創建的console設備名肯定不是他了,所以我們現在就要找到內核裏serial的名字。找了半天在drivers/tty/serial/samsung.c裏發現了這個驅動,有如下定義:

/* UART name and device definitions */
 
#define S3C24XX_SERIAL_NAME "ttySAC"
#define S3C24XX_SERIAL_MAJOR    204
#define S3C24XX_SERIAL_MINOR    64
說明SERIAL_NAME爲ttySAC,那麼我們就需要把我們的bootargs參數修改下,改爲

bootargs=console=ttySAC0,115200 mem=64M initrd=0x30800000,16M root=/dev/ram0 rw loglevel=7
重新啓動內核,你會驚喜的發現,內核有東西輸出了,但是是一堆亂碼?根據我的常識推斷,這肯定是波特率不對,但是波特率在bootargs裏面設置的是115200啊,跟我PC上的波特率是一樣的啊!那是哪裏的問題呢?肯定是那個地方的頻率不對,才導致系統出現這個問題!


圖一 串口波特率不對,導致內核打印信息爲亂碼

(有人肯定會問我,你怎麼找這麼準啊?對,這完全是經驗,你要怎麼才能擁有這個經驗呢?多實踐,多瞭解,多記,首先你要對內核的每個目錄是幹什麼的要了解下吧?然後你要知道linux內核他的設備驅動是個怎麼回事吧?具體這些問題,網上說的不計其數。)

這個使我想起了s3c2410跟s3c2440的主頻不一樣,又因爲我使用的是s3c2410的config文件,所以我就需要看看他的主內核是時鐘是怎麼配置的。一般時鐘都在芯片內核初始化的地方,我們就需要去mach-s3c2440的目錄下面看看。

 vim arch/arm/mach-s3c2440/mach-smdk2440.c

找到machine_init的地方,這個肯定是系統初始化了,發現有這麼一段代碼:

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


static void __init smdk2440_machine_init(void)
{
    s3c24xx_fb_set_platdata(&smdk2440_fb_info);
    s3c_i2c0_set_platdata(NULL);


    platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
    smdk_machine_init();
}
有一句s3c24xx_init_clocks(16934400);這個事16.934MHz的晶振,而我板子上的系統晶振爲12MHz的,所以我需要把這晶振頻率改下:s3c24xx_init_clocks(12000000);

注意:可能你們的板子上的晶振不是12MHz的,所以要自己看下原理圖或者開發板上的晶振是多少。
重新make , make image , 下載,bootm。


圖二  s3c2440晶振電路圖

這次內核成功的打印信息了:

Bytes transferred = 1984424 (1e47a8 hex)
## Booting kernel from Legacy Image at 30008000 ...
   Image Name:   Linux Kernel
   Created:      2014-08-12   2:23:33 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1984360 Bytes = 1.9 MiB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK
OK
OS entry point: 30008040
Image entry point=30008040

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Linux version 3.0.0 ([email protected]) (gcc version 4.3.6 (Buildroot 2011.11) ) #3 Tue Aug 12 10:20:31 CST 2014
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: console=ttySAC0,115200 mem=64M initrd=0x30800000,16M root=/dev/ram0 rw loglevel=7
PID hash table entries: 256 (order: -2, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 44520k/44520k available, 21016k reserved, 0K highmem
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    DMA     : 0xffc00000 - 0xffe00000   (   2 MB)
    vmalloc : 0xc4800000 - 0xf6000000   ( 792 MB)
    lowmem  : 0xc0000000 - 0xc4000000   (  64 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .init : 0xc0008000 - 0xc002b000   ( 140 kB)
      .text : 0xc002b000 - 0xc0399000   (3512 kB)
      .data : 0xc039a000 - 0xc03c5080   ( 173 kB)
       .bss : 0xc03c50a4 - 0xc03e9d84   ( 148 kB)
NR_IRQS:99
系統默認nand flash分區:

Creating 8 MTD partitions on "NAND":
0x000000000000-0x000000004000 : "Boot Agent"
mtd: partition "Boot Agent" doesn't end on an erase block -- force read-only
0x000000000000-0x000000200000 : "S3C2410 flash partition 1"
0x000000400000-0x000000800000 : "S3C2410 flash partition 2"
0x000000800000-0x000000a00000 : "S3C2410 flash partition 3"
0x000000a00000-0x000000e00000 : "S3C2410 flash partition 4"
0x000000e00000-0x000001800000 : "S3C2410 flash partition 5"
0x000001800000-0x000003000000 : "S3C2410 flash partition 6"
0x000003000000-0x000010000000 : "S3C2410 flash partition 7"
但是提示沒有文件系統:

List of all partitions:
1f00              16 mtdblock0  (driver?)
1f01            2048 mtdblock1  (driver?)
1f02            4096 mtdblock2  (driver?)
1f03            2048 mtdblock3  (driver?)
1f04            4096 mtdblock4  (driver?)
1f05           10240 mtdblock5  (driver?)
1f06           24576 mtdblock6  (driver?)
1f07          212992 mtdblock7  (driver?)
No filesystem could mount root, tried:  ext2 cramfs vfat msdos iso9660 ntfs romfs
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)
Backtrace: 
[<c003b734>] (dump_backtrace+0x0/0x104) from [<c02bb4f0>] (dump_stack+0x18/0x1c)
 r6:c3889000 r5:00008000 r4:c3819f5c
[<c02bb4d8>] (dump_stack+0x0/0x1c) from [<c02bb548>] (panic+0x54/0x1a8)
[<c02bb4f4>] (panic+0x0/0x1a8) from [<c0008ff0>] (mount_block_root+0x264/0x2d0)
 r3:00000000 r2:c3819f5c r1:c3819f5c r0:c034e9e8
[<c0008d8c>] (mount_block_root+0x0/0x2d0) from [<c00090b0>] (mount_root+0x54/0x6c)
[<c000905c>] (mount_root+0x0/0x6c) from [<c00091dc>] (prepare_namespace+0x114/0x1e4)
 r5:c0026600 r4:c03c5120
[<c00090c8>] (prepare_namespace+0x0/0x1e4) from [<c0008490>] (kernel_init+0xe8/0x128)
 r5:c002584c r4:c0025bdc
[<c00083a8>] (kernel_init+0x0/0x128) from [<c0050554>] (do_exit+0x0/0x6e8)
 r6:c0050554 r5:c00083a8 r4:00000000
再具體看下他的List of all partitions,部分分區跟我的內核和文件系統分區重疊了,所以我們要對文件系統分區進行修改;(這裏我就不對文件系統進行詳細的描述了,因爲這次是針對linux內核移植)

【如果存在什麼問題,請大家留言並指出】

E-mail: [email protected]

如果轉載請註明出處,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章