基於 移植uboot后.
1. 移植linux內核
1.1 下載源碼
打開 https://www.kernel.org/ 直接肝最新的 5.2.8
下載完后,在ubuntu里解壓備用.
1. 交叉編譯環境用的是arm-linux-gcc 4.6.4的版本,這個版本挺好找的,在網上下載壓縮包后,根據個人習慣解壓到 /opt/ 下, 2. 並且修改環境變量 sudo vim /etc/profile export PATH=/opt/gcc-4.6.4/bin:$PATH 3. 保存,然后source /etc/profile 進行更新.穩妥起見,ubuntu要注銷一下,重新登錄. 4. 確定:在窗口輸入arm-linux-gcc -v 顯示的是你的編譯環境就可以啦.
注:是可以多版本gcc編譯器 " 偽共存 " 的,我這里就是gcc 3.4 的也有一份, 需要的時候,把環境變量注釋一下留下需要的版本就好了.我覺得這樣很方便.
s3c2440 支持2中時鍾晶振:12MHz 和 16MHz,我這個板子上用的是12MHz, 所以修改 arch/arm/mach-s3c2440/mach-smdk2440.c s3c24xx_init_clocks(16934400); 改為: s3c24xx_init_clocks(12000000);
修改nand 分區 arch/arm/mach-s3c24xx/common-smdk.c static struct mtd_partition smdk_default_nand_part[] = { [0] = { .name = "uboot", .size = SZ_256K, .offset = 0, }, [1] = { .name = "env", .offset = MTDPART_OFS_APPEND, .size = SZ_128K, }, [2] = { .name = "kernel", .offset = MTDPART_OFS_APPEND, .size = SZ_4M, }, [3] = { .name = "rootfs", .offset = MTDPART_OFS_APPEND, .size = SZ_8M, }, [4] = { .name = "appfs", .offset = MTDPART_OFS_APPEND, .size = SZ_8M, }, }; //可自行修改,注因為內核編譯完有3.4M,所以降kernel的分區改成了4M,根文件系統用的是jffs2,填充成了8M大小,所以這里是8M
1, 修改Makefile 搜索ARCH ,找到 359 ARCH ?= $(SUBARCH) 注釋掉改成 ARCH ?= arm //因為要編譯arm架構體系的. 這一步是代替編譯的時候, make V=s ARCH=arm . 在下一行直接添加 交叉編譯鏈 CROSS_COMPILE ?= arm-linux- ok. 這樣子,make menuconfig 就是arm架構的了.
2. make menuconfig 這里我用的因為是s3c2440 的soc, 所以 選擇最接近的s3c2410的模板來進行修改. 怎么查看有沒有適合自己的呢? 這些config文件在: [ ./arch/arm/config/ ]下
使用: 在linux內核根目錄下,執行 1. make s3c2410_defconfig 就可以自動進行拷貝和更新. 2. 然后make menuconfig 進行微調 3. 保存: make savedefconfig 進行配置保存, 4. 存檔: cp davedefconfig /arch/arm/config/你想保存的型號, 我這里是s3c2440_defconfig make s3c2410_defconfig make menuconfig make savedefconfig cp davedefconfig /arch/arm/config/s3c2440_defconfig
言歸正傳,怎么配置內核,make menuconfig 開頭顯示當前的交叉編譯鏈, 如果沒有配置交叉編譯環境的話,當前的環境就是ubuntu的環境.
然后怎么配置:太繁瑣了,附上網上的教程.
[https://blog.csdn.net/tk01044242_1/article/details/78815816]
make V=s 先編譯看是否出錯. 這里我先前編譯未能通過,原因是用了3.+的gcc, 后來改成了新的編譯器(4.6.2)就沒有再報錯. 新的內核還是用新的編譯器,就得內核用舊的編譯器這是道理. 制作uImage make V=s uImage 后面報錯: OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready UIMAGE arch/arm/boot/uImage "mkimage" command not found - U-Boot images will not be built arch/arm/boot/Makefile:90: recipe for target 'arch/arm/boot/uImage' failed make[1]: *** [arch/arm/boot/uImage] Error 1 arch/arm/Makefile:339: recipe for target 'uImage' failed make: *** [uImage] Error 2 //可以看到,zImage是編譯完成了,但是說mkimage命令不支持, 所以uImage沒有生成成功 把uboot源碼文件夾中的mkimage(可執行文件) 拷貝到/sys/local/bin中,這樣編譯器就能支持給iamge添加64k的uboot頭信息.形成uImage.這個文件去下一個uboot源碼中獲得. 最后生成的uImage 在 /arch/arm/boot中.
我用的是tftp的方式 . 我的內核是3.4M, 按4M的空間來算,就是 0x400000 所以 tftp 0x30000000 uImage //這里的0x30000000 是三星內存的起始地址,臨時的一個空間,掉電后就會消失,所以下一步就是要把這個固件 寫入到不會丟失的nand flash中. 當然,這個時候,bootm 0x30000000 是可以直接啟動內核的,只是掉電丟失. nand flash 寫入的規則是,寫入前要擦除.所以 nand erase 0x60000 0x400000 //為什么是0x60000 呢, 由下: 我的uboot環境是: // mtdparts=nandflash0:256k@0(bootloader),128k(params),4m(kernel),-(root) 可知,256+128k = 384k *1024 = 393216 = 0x60000 ,所以前面2個空間占據了[0~ 0x60000]的空間,因此,內核空間從0x60000開始. 0x400000 則是有uImage鏡像大小決定,取大取整就好. 然后 我原本以為是 nand write 0x30000000 0x60000 0x400000 ,這樣做的時候, uboot確實校驗到頭部信息了,但是總是 整個內核crc失敗.不知道為什么. 在百度的時候,無意間看到: nand write.jffs2 0x30000000 0x60000 0x400000 ,居然就可以了... 可見差別在 nand write 和 nand write.jffs2上.
//1. 用tftp 將uImage 拷貝到臨時內存中 tftp 0x30000000 uImage //2. 擦除nand flash中 屬於kernel的區域 nand erase 0x60000 0x400000 //3. 將uImage 寫入到nand flash nand write.jffs2 0x30000000 0x60000 0x400000 //4.運行的時候,要將固件搬運到內存中運行 nand read.jffs2 0x30007fc0 0x60000 0x400000 //5.從內核處啟動: bootm 0x30007fc0
因為我的uboot參數是 bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0 所以我將nand flash中的內核,讀到內存 0x30007FC0后 ,從這個地方開始執行內核的第一條,是核對uboot加入的64K的頭部信息 4194304 bytes read: OK ## Booting image at 30007fc0 ... Image Name: Linux-5.2.6 Created: 2019-08-15 8:53:43 UTC Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3490728 Bytes = 3.3 MB Load Address: 30008000 Entry Point: 30008000 Verifying Checksum ... OK XIP Kernel Image ... OK 這里,如果寫入方式[write.jffs2]正確的話,就會通過crc校驗,否則就是crc error. 如果因為啟動地址和搬運地址不匹配,未能識別到64K的uboot頭, 會顯示magic number err.
執行到后面,會提示panic 內核崩潰,因為我們文件系統還沒做,所以會提示錯誤.
.