18.17 U-Boot+内核移植

时间:2021-07-10 15:19:22

18.17.1 移植U-Boot-2012.04.08

1.下载、建立source insight工程、编译、烧写、如果无运行分析原因。

$ tar xif u-boot-2012.04..tar.bz2
$ cd u-boot-2012.04.
$ make smdk2410_config
$ make
ERROR【错误原因:gcc版本低】
$ arm-linux-gcc -v
[gcc version 3.4.]
更新gcc步骤:解压到根目录
$ sudo tar -xjf arm-linux-gcc-4.3..tar.bz2 -C /
$ ls
$ usr
$ echo $PATH查看gcc执行路径
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games: /work/tools/gcc-3.4.5-glibc-2.3.6/bin"
$ sudo vi /etc/environment【在路径后增加:/usr/local/arm/4.3./bin】
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/4.3.2/bin"
:wq
sudo reboot
重启系统,更新gcc后,即可编译成功。烧写uboot.bin后,程序不运行!

2.分析u-boot:通过连接命令分析组成文件、阅读代码分析启动过程。

需要做的事:

1)初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH

2)如果BootLoader比较大,重定位到SDRAM

3)把内核从NAND FLASH读到SDRAM

4)设置“要传给内核的参数”

5)跳转执行内核

$ arm-linux-objdump -D u-boot > u-boot.dis反汇编

代码中:DECLARE_GLOBAL_DATA_PTR定义一个r8寄存器变量

#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")

2.1 set the cpu to svc32:设置CPU为管理模式

2.2 turn off the watchdog

2.3 mask all IRQs by setting all bits in the INTMR - default:屏蔽所有中断

2.4 /* FCLK:HCLK:PCLK = 1:2:4 *//* default FCLK is 120 MHz ! */设置分频时钟比例

2.5 Set stackpointer in internal RAM to call board_init_f设置内存控制器

2.6  Set up the stack call C function:调用C函数,设置栈

2.7 call init_sequence:调用(函数数组)里的各个函数,初始化设备

2.7.1 board_early_init_f:设置系统时钟,设置GPIO端口

2.8 relocate_code(addr_sp, id, addr); :C调用asm;重定位代码,调用此函数时,重新修改了栈

addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;//0x3400,0000

addr-4k=0x33FF,F000

addr &= ~(0x10000 - 1);//0xFFFF清掉最低16位,0x33FF,0000

addr -= gd->mon_len;//697k/0x33FF,0000-0xae4e0(反汇编找到的)=33F41B20

addr &= ~(4096 - 1);//33F41B20清低12位=>0x33F4,1000

2.8.1 从NOR FLASH把代码复制到SDRAM:

2.8.2 程序的链接地址是0,访问全局变量、静态变量、调用函数时是使“基于0地址编译得到的地址”

现在把程序复制到SDRAM

需要修改代码,把“基于0地址编译得到的地址”改为新地址

2.8.3 程序里有些地址在链接时不能确定,要到运行前才能确定;fixabs

2.9 清除bss

2.10 调用board_init_r函数:第二阶段。应该再次设置sp

可以修改配置文件定义CONFIG_S3C2440

3. 修改U-Boot代码

3.1 建smdk2440单板

cd board/samsung

cp smdk2410 smdk2440 -rf

cd ../../include/configs/

cp smdk2410.h smdk2440.h

新建smdk2440单板规则

grep "smdk2410" -nR

修改boards.cfg:

仿照

smdk2410    arm        arm920t        -             samsung              s3c24x0

添加

smdk2440    arm        arm920t        -             samsung              s3c24x0

3.2 烧写实验:绝对不会成功的……哈哈哈

3.3 调试:【1.内存2.时钟】

a. 阅读代码发现不足:U-Boot里先以64M的时钟计算参数来设置内存控制器,但是MPLL还未设置

处理方法:把MPLL的设置放到start.s里,取消board_early_init_f里对MPLL的设置

编译出来的U-Boot很大,可以先烧写旧的U-Boot到nor,然后用这个U-Boot来烧写新的U-boot

用原来的方式设置MPLL和内存lowevel_init.S

3.4 查看串口波特率的设置,发现在get_HCLK里没有定义CONFIG_S3C2440

处理方法:include/configs/smdk2440.h:

//#defineCONFIG_S3c2410

#define CONFIG_S3C2440

编译有错误,根据MakeFile查找到宏后,去掉//#define CONFIG_CMD_NAND

3.5修改U-Boot支持NAND启动

原来的代码在链接时,加了-pie选项,使得u-boot.bin多了  *(.rel*)、*(.dynsym)信息

程序特别大,不利于从NAND启动代码(重定位之前的代码应该少于4k)

1.把链接地址定死,直接复制

2.导致了程序必须有地址段,程序远远超过4k;代码庞大,程序复杂

3.5.1 链接时去掉-pie

arch/arm/config.mk:75:LDFLAGS_u-boot += -pie去掉这行

3.5.2 参考“毕业班视频第一课的start.s、init.c”修改代码,修改_TEXT_BASE的值,

把init.c放入board/samsung/smdk2440目录,修改Makefile,增加init.o

修改start.S

3.5.3 修改board_init_f,把重定位relocate_code的代码去掉

将relocate_code设置为unsigned int格式,返回id

bl r1, _TEXT_BASE

bl board_init_r/*第二阶段*/

3.5.4 修改链接脚本:把start.S,init.c,lowlevel.s等文件放到最前面

./arch/arm/cpu/u-boot.lds:

board/samsung/smdk2440/libsmdk2440.o (.text)

修改include/common.h

unsigned int board_init_f  (ulong) __attribute__ ((noreturn));

【__attribute__ ((noreturn))不显示输出】

3.6 修改支持NOR Flash

修改u-boot-2012.04.01\drivers\mtd\jedec_flash.c内的jedec_table增加NOR FLASH类型

修改u-boot-2012.04.01\include\configs\smdk2440.h

#define CONFIG_SYS_MAX_FLASH_SECT (128)

在u-boot-2012.04.01\drivers\mtd\cfi_flash.c增加

#define DEBUG 1       #define _DEBUG 1

修改u-boot-2012.04.01\arch\arm\lib\board.c

//puts(failed);

//hang();

烧写执行

SMDK2440 # protect off all、测试NOR FLASH是否可以读写

SMDK2410 # flinfo

修复重定位时留下的bug,重新设置sp

第二阶段要重新设置栈设置到addr_sp2

start.S:

.globl base_sp

base_sp:

.long 0

ldr sp, base_sp

board.c的unsigned int board_init_f(ulong bootflag)函数内:

extern ulong base_sp;

base_sp = addr_sp;

//relocate_code(addr_sp, id, addr);

3.7 修改U-Boot支持NAND Flash

修改:include/configs/smdk2440:#define CONFIG_CMD_NAND

把u-boot-2012.04.01\drivers\mtd\nand\s3c2410_nand.c复制为s3c2440_nand.c

分析过程:

board.c > nand_init()

> nand_init_chip()

> board_nand_init()[设置nand_chip结构体,提供底层操作函数]

> nand_scan()

> nand_set_defaults()

>chip->select_chip = nand_select_chip;

>chip->cmdfunc = nand_command

>nand_get_flash_type()

>chip->select_chip(mtd, 0);

>chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);

nand_command//既可以用来发命令,也可以用来发列地址(页内地址)、行地址(哪一页)

chip->cmd_ctrl

s3c2440_hwcontrol

>chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);

>*maf_id = chip->read_byte(mtd);

>*dev_id = chip->read_byte(mtd);

3.8 修改U-Boot支持DM9000网卡

board.c >     eth_initialize(gd->bd);

>board_eth_init()

>cs8900_initialize()

通过在linux里查找dm9000用法:grep "dm9000_init" * -nR

增加下列代码:

#ifdef CONFIG_DRIVER_DM9000

rc = dm9000_initialize(bis);

#endif

测试:

*** ERROR: `ethaddr' not set

set ipaddr 10.3.10.231

set ethaddr 00:16:E6:32:6E:EC

3.9 修改U-Boot保存环境变量,易用性修改+裁剪

*** Warning - bad CRC, using default environment

u-boot-2012.04.01\include\configs\smdk2440.h

#define CONFIG_BOOTARGS "console=ttySAC0 root=/dev/mtdblock3"

#define CONFIG_BOOTCOMMAND "nand read 30000000 kernel 0x200000;bootm 30000000"

定义了bootcmd=nand read 30000000 kernel 0x200000;bootm 30000000才显示倒计时5s

#define CONFIG_BOOTDELAY 5

#define CONFIG_ETHADDR 00:16:E6:32:6E:EC

内核打印出的分区信息:

0x00000000-0x00040000:"bootloader"       256KB

0x00040000-0x00060000:"params"      128KB

0x00060000-0x00260000:"kernel"              2048KB=2M

0x00260000-0x10000000:"rootfs"

下载:

SMDK2440 # tftp 30000000 u-boot20181219.bin

SMDK2440 # protect off all

SMDK2440 # erase 0 3ffff

SMDK2440 # cp.b 30000000 0 40000

SMDK2440 # reset

SMDK2440 # set bootcmd 'nand read 30000000 kernel;bootm 30000000'

SMDK2440 # save

#define MTDIDS_DEFAULT             "nand0=jz2440-0"

#define MTDPARTS_DEFAULT "mtdparts=jz2440-0:256k(u-boot),"       \

"128k(params),"  \

"2m(kernel),"              \

"-(rootfs)"

SMDK2440 # mtdparts

SMDK2440 # help mtdparts

SMDK2440 # mtdparts default

SMDK2440 # nand erase.part kernel

SMDK2440 # tftp 30000000 uImage

SMDK2440 # nand erase.part kernel

SMDK2440 # nand write 30000000 kernel

SMDK2440 # reset

resetting ...

烧写JAFFS:

SMDK2440 # tftp 30000000 fs_mini_mdev.jffs2

SMDK2440 # nand erase.part rootfs

SMDK2440 # nand write.jffs2 30000000 0x00260000 size

set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

boot

更新U-Boot:

SMDK2440 # tftp 30000000 u-boot.bin; protect off all; erase 0 4ffff; cp.b 30000000 0 50000

烧写YAFFS:

SMDK2440 # tftp 30000000 fs_mini_mdev.yaffs2

SMDK2440 # nand erase.part rootfs

SMDK2440 # nand write.yaffs 30000000 0x00260000 889bc0(size)

ERROOR:         Kernel panic - not syncing: No init found.  Try passing init= option to kernel.

nand dump 260000和.yaffs2文件比较,每一页是2048,第二页是2048+64

nand dump 260800是第二页

在 u-boot-2012.04.01\drivers\mtd\nand\nand_util.c里修改

ops.mode = MTD_OOB_RAW;//用原始的OOB

if (rval)/*如果是非零才会错误,只写了一页数据*/!!!!!!!!!!!!!!!!!

vi u-boot-2012.04.01\drivers\mtd\nand\nand_util.c +518

if (!need_skip && !(flags & WITH_DROP_FFS)) {

改为

if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB)) {

制作补丁:

参照“18.13.3制作Uboot补丁文件步骤”。

18.17.2 移植Linux3.4.2内核

.先下载Linux3.4.2内核,然后解压内核。

$tar xzf linux-3.4..tar.gz
$cd linux-3.4.

1.1 修改Makefile

$vi Makefile +
/ARCH找到
ARCH?=$(SUBARCH)改为arm
CROSS_COMPILE ?=arm-linux-

在linux-3.4.2/Documentation/Changes下查找适合的gcc编译器

1.2 选择默认配置:

$ find -name "*_defconfig"

      ./arch/arm/configs/s3c2410_defconfig

      ./arch/arm/configs/mini2440_defconfig

$make s3c2410_defconfig //生成.config

查看系统支持什么单板

ls **
ls **
vi .config //可以看到MINI2440和SMDK2410

1.3 make uImage编译

ERROR :
  arch/arm/mm/tlb-v4wbi.S: Assembler messages:
  arch/arm/mm/tlb-v4wbi.S:: Error: too many positional arguments
  make[]: *** [arch/arm/mm/tlb-v4wbi.o] Error
  make: *** [arch/arm/mm] Error
ANSWER :
  更新编译器为4..3版本
  $vi /etc/environment
  将路径增加:/usr/local/arm/4.3./bin
  然后重启Linux服务器

3.解压3.4.2内核创建SourceInsight工程

4.复制编译好的uImage文件到work/nfs_root

$cp arch/arm/boot/uImage /work/nfs_root/uImage_new
#nfs 10.3.10.232:/work/nfs_root/uImage_new
ERROR :
  SMDK2440 # nfs 10.3.10.232:/work/nfs_root/uImage_new
  dm9000 i/o: 0x20000000, id: 0x90000a46
  DM9000: running in bit mode
  MAC: :::ff::
  could not establish link
  Using dm9000 device
  File transfer via NFS from server 10.3.10.232; our IP address is 10.3.10.231
  Filename '/work/nfs_root/uImage_new'.
  Load address: 0x32000000
  Loading:
  ################################################################
  ##############T T *** ERROR: Cannot umount   能下载,但快要下载完时,却出现“ERROR: Cannot Umount”这样的错误。   或   #####################transmission timeout   ############################################ ANSWER :   如出现checksum bad或者time out之类的错误,试着重启虚拟机的nfs服务。   在虚拟机里修改/etc/hosts文件。 如:   $sudo vi /etc/hosts   目标板ip 根文件系统   10.3.10.231 /work/nfs_root   打开uboot程序查看默认的MACH_ID:   gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;//   如果s=getenv(“machid”);成功,则使用它;否则使用默认

移植Linux3.4.2步骤:

步骤1:

cd arch/arm/

find -name "mach*.o" /*可查看uImage 支持的单板*/

$find -name mach-types.h

$vi ./include/generated/mach-types.h

在UBOOT里:

#set machid 16a //mach-smdk2440.c或#set machid 7CF /mach-mini2440.c
#set bootargs console=ttySAC0, root=/dev/mtdblock3 /*设置bound*/
#save
#nfs 10.3.10.232:/work/nfs_root/uImage_new
#bootm

步骤2:

#vi arch\arm\mach-s3c24xx\mach-smdk2440.c +
s3c24xx_init_clocks();改为s3c24xx_init_clocks();

步骤3:配置/编译

$ make s3c2410_defconfig 或 make mini2440_defconfig
$ make uImage

步骤4:重复步骤1

linux乱码解决后显示的错误:

      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"

.修改分区

根据上一步的错误,可知,linux3.4.2系统的分区太多。

按照错误信息,在服务器搜索

    $grep "\"Boot\ Agent\"" * -nR

    vi arch/arm/mach-s3c24xx/common-smdk.c +

    修改static struct mtd_partition smdk_default_nand_part[] = {

    $make uImage && cp arch/arm/boot/uImage /work/nfs_root/uImage_new

下载内核:

  #nfs  10.3.10.232:/work/nfs_root/uImage_new
#bootm /*启动后提示文件系统错误*/

重新下载文件系统:

 #nfs  10.3.10.232:/work/nfs_root/fs_mini_mdev.yaffs2

      #nand erase.part rootfs

      #nand write.yaffs    889bc0

      或者

      #nfs  10.3.10.232:/work/nfs_root/fs_mini_mdev.jffs2

      #nand erase.part rootfs; nand write.jffs2    $filesize

      #set bootargs console=ttySAC0, root=/dev/mtdblock3 rootfstype=jffs2 //重启后仍有错误,说明旧的文件系统不能使用,需要重新制作

. 制作文件系统

1.解压下载的文件系统

$ tar xjf busybox-1.20..tar.bz2

busybox-1.20.$ make menuconfig

      错误:

      Your display is too small to run Menuconfig!

      It must be at least  lines by  columns.

      make[]: *** [menuconfig] Error 

      make: *** [menuconfig] Error 

      解决方案:缩小字体或移动到大的显示屏

2.设置Busybox

Busybox Settings --->

      Busybox Options --->

             Cross Complier prefix(NEW)

                    arm-linux-

busybox-1.20.$ make

/work/nfs_root/$ mkdir fs_mini_mdev_new //新建文件系统文件夹

/work/nfs_root/$ cd fs_mini_mdev_new

2.1根文件系统制作

2.1.1.安装到新建的文件系统文件夹:

busybox-1.20.0$ vi README //查看使用说明

busybox-1.20.0$make install CONFIG_PREFIX=/work/nfs_root/fs_mini_mdev_new

2.1.2.复制库

$ echo $PATH

$ cd /usr/local/arm/4.3./bin //查找库内容

/usr/local/arm/4.3./bin$ find -name lib

      ./arm-none-linux-gnueabi/libc/armv4t/lib

      ./arm-none-linux-gnueabi/libc/armv4t/usr/lib

$mkdir /work/nfs_root/fs_mini_mdev_new/lib

$ cp arm-none-linux-gnueabi/libc/armv4t/lib/*so* /work/nfs_root/fs_mini_mdev_new/lib -d

$mkdir /work/nfs_root/fs_mini_mdev_new/usr/lib -p

$ cp arm-none-linux-gnueabi/libc/armv4t/usr/lib/*so* /work/nfs_root/fs_mini_mdev_new/usr/lib/ -d

2.1.3.构建etc目录

/work/nfs_root$ cp fs_mini_mdev/etc fs_mini_mdev_new -rf

//vi inittab    修改s3c2410_serial0为console //vi init.d/rcS //cat fstab

2.1.4.构建dev目录

/work/nfs_root/fs_mini_mdev_new$ mkdir dev

$ ls -l /dev/console /dev/null查看主、次设备号

/work/nfs_root/fs_mini_mdev_new$ sudo mknod dev/console c  

/work/nfs_root/fs_mini_mdev_new$ sudo mknod dev/null c  

2.1.5.其他空目录

/work/nfs_root/fs_mini_mdev_new$ mkdir proc mnt tmp sys root

2.2制作JAFFS2

/work/nfs_root$ mkfs.jffs2 -n -s  -e 128KiB -d fs_mini_mdev_new -o fs_mini_mdev_new.jffs2 //2048一个扇区大小,128KiB可插除扇区

烧写:

#nfs  10.3.10.232:/work/nfs_root/fs_mini_mdev_new.jffs2

#nand erase.part rootfs; nand write.jffs2    $filesize

#set bootargs console=ttySAC0, root=/dev/mtdblock3 rootfstype=jffs2

#nfs  10.3.10.232:/work/nfs_root/uImage_new

#bootm 

出现错误:

Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004

SIGILL   illegal instruction

重新配置内核支持EABI

$make menuconfig

Kernel Features --->

      [*]Use arm EABI...

$make uImage && cp arch/arm/boot/uImage /work/nfs_root/uImage_eabi

#set bootargs console=ttySAC0, root=/dev/mtdblock3 rootfstype=jffs2

#nfs  10.3.10.232:/work/nfs_root/uImage_eabi

#bootm 

.移植YAFFS文件系统

1.获得源码

git clone git://www.aleph1.co.uk/yaffs2

2.打补丁

$cd yaffs-dir      进入yaffs目录

$./patch-ker.sh  c m linux-tree

eg.

$/patch-ker.sh c m /work/system/linux-3.4.

3.配置内核支持YAFFS

linux-3.4.$ make menuconfig

-> File systems

-> Miscellaneous filesystems (MISC_FILESYSTEMS [=y])

->[*] yaffs2 file system support (YAFFS_FS [=n])

4.编译、使用uImage

linux-3.4.$ make uImage

Error:

      d_make_root(inode) //Linux-3.4.2内核的mtd结构体的名字都加了下划线

修改完错误后,编译:

$ make uImage && cp arch/arm/boot/uImage /work/nfs_root/uImage_yaffs

5.制作、烧写yaffs映象

/work/nfs_root$ mkyaffs2image fs_mini_mdev_new fs_mini_mdev_new.yaffs2

mkyaffs2image命令哪来的?

      yaffs_source_util_larger_small_page_nand.tar.bz2/Development_util_ok/yaffs2/utils --->执行make

      或git clone git://www.aleph1.co.uk/yaffs2/utils --->执行make

             这里面的程序有问题,修改

#nfs  10.3.10.232:/work/nfs_root/fs_mini_mdev_new.yaffs2

#nand erase.part rootfs; nand write.yaffs   $filesize

6.启动

#set bootargs console=ttySAC0, root=/dev/mtdblock3

#nfs  10.3.10.232:/work/nfs_root/uImage_yaffs; bootm 

7.若没成功,用替代法查找问题

7.1 UBOOT可能有问题:换上1.1.6的UBOOT

#tftp  u-boot.bin

#nand erase.part u-boot

#nand write  u-boot

#reset

#nfs  10.3.10.232:/work/nfs_root/fs_mini_mdev_new.yaffs2

#nand erase rootfs

#nand write.yaffs    $(filesize)

#set bootargs console=ttySAC0, root=/dev/mtdblock3

#nfs  10.3.10.232:/work/nfs_root/uImage_yaffs

#bootm 

发现1.1.6的UBOOT没问题,所以就是我们移植的新UBOOT有BUG:

drivers\mtd\nand\Nand_util.c

      if (!need_skip && !(flags & WITH_DROP_FFS)) {

改为

      if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB)) {

.裁剪内核

System Type  --->   

          SAMSUNG S3C24XX SoCs Support  --->

                进入选择不需要的即可

-> File systems //进入选择熟悉的修改即可

根据输出裁剪内核

mousedev: PS/ mouse device common for all mice

本次修改制作了u-boot_new.bin, uImage_small, fs_mini_mdev_new.yaffs

重烧整个系统:

使用jtag工具烧u-boot_new.bin

或使用uboot来更新自己: tftp 30000000 u-boot_new.bin; nand erase.part u-boot; nand write 30000000 u-boot

启动uboot,用它来烧写内核、FS

nfs  10.3.10.232:/work/nfs_root/uImage_small; nand erase.part kernel; nand write  kernel

nfs  10.3.10.232:/work/nfs_root/fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs   $filesize

设置参数

set 'nand read 30000000 kernel;bootm 30000000'

set bootargs console=ttySAC0, root=/dev/mtdblock3

set machid 16a

save

制作Linux3.4.2内核补丁:参照“18.13.3制作Uboot补丁文件步骤”。