移植u-boot

移植U-boot

(一)初试

  1. 在官网上下载最新的uboot(u-boot-2012.04.01)压缩包,并将其拖到服务器上;

    1.1 在SecureCRT上第一次尝试编译

    1.2 出错

    出错原因:编译工具链版本低。
    

    1.3 查看当前交叉编译工具链版本

  2. 安装新的编译工具链(arm-linux-gcc-4.3.2);

    2.1 解压到根目录

    2.2 修改环境变量(进入根目录/usr/local/arm/4.3.2/bin)

    另一种方法(如下图):sudo vi /etc/environment
    

  3. 再次编译u-boot,进入之前u-boot-2012.04.01文件夹

    3.1 清除之前编译的:make distclean

    3.2 配置:make smdk2410_config

    3.3 编译:make

    3.4 编译成功–生成u-boot.bin文件

  4. 将生成u-boot.bin文件用eop下载到NOR Flash,启动,但串口上并没有什么显示。(这是正常的,因为还没有做修改)

(二)源码分析启动过程

  1. 创建si工程;

    添加代码时:board文件夹只需添加的Samaung中的smdk2410,arch文件夹下的Arm->cpu->arm920t->s3c24x0、include->Asm->arch-s3c24x0是我们关注的,其他文件夹可以均添加上。

  2. 第一阶段代码分析(文件:start.S (arch\arm\cpu\arm920t),lowlevel_init.S (board\samsung\smdk2410))

    2.1 将CPU的工作模式设为管理模式(svc):/* set the cpu to SVC32 mode */

    2.2 关闭看门狗:/* turn off the watchdog */

    2.3 /* mask all IRQs by setting all bits in the INTMR - default */

    2.4 设置FCLK、HCLK、PCLK的比例(设置CLKDIVN寄存器):/* FCLK:HCLK:PCLK = 1:2:4 */

    2.5 设置内存控制器: cpu_init_crit

    a. /* flush v4 I/D caches */
    
    b. 关闭MMU、CACHE:/* disable MMU stuff and caches */
    
    c. 跳转至lowlevel_init:bl  lowlevel_init
    
        为加载BootLoader的第二阶段代码准备RAM空间(lowlevel_init.S)--开发板相关
    
        即:初始化内存芯片,对于S3C2440,使得外接的SDRAM可用。
    
        lowlevel_init函数,并不复杂,只是这时的代码、数据只保存在NOR FLASH中,内存中还没有,所以读取数据时要变换地址。
    


    第137-139行:进行地址变换,因为这时候内存中还没有数据,不能使用链接程序时确定的地址来读取数据。
    
    第137行:SMRDATA表示这13个寄存器的值存放的开始地址(连接地址),为0x33F8xxxx,处于内存中。
    
    第138行:获得代码段的起始地址,即“_TEXT_BASE”,在board\smdk2410\config.mk中定义"TEXT_BASE = 0x33F80000"
    
    第139行:将0x33F8xxxx与0x33F80000相减,就是13个寄存器值在NOR Flash上存放的地址。
    

    2.6 设置栈,调用C函数board _ init _ f:/* Set stackpointer in internal RAM to call board_init_f */

    a. 调用函数数组init_sequence里的各个函数:(例)board_early_init_f : 设置系统时钟、设置GPIO
    
    b. board _ init _ f最后调用的重定位函数:relocate_code(addr_sp, id, addr);
    
    addr:把NOR Flash中的程序拷贝到哪里去;
    
    addr_sp:设置的栈;
    
    id:一些变量的地址
    
        1. addr
    
            addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;  
    
            /* CONFIG_SYS_SDRAM_BASE=0x30000000, gd->ram_size=64MB, 所以addr=0x34000000 */
    
    
            addr -= (4096 * 4);  /* addr = 33FFC000 */
    
            addr &= ~(0x10000 - 1); /* addr = 33FF0000 */
    
            addr -= gd->mon_len; /* gd->mon_len = _bss_end_ofs;--uboot程序的大小:AE4E0(反汇编文件中),所以addr= 33F41B20 */
    
            addr &= ~(4096 - 1);  /* addr=33F41000 */
    
        2. addr_sp
    
            addr_sp = addr - TOTAL_MALLOC_LEN;
    
            addr_sp -= sizeof (bd_t);
    
            addr_sp -= sizeof (gd_t);
    
            addr_sp -= 12;
    
        3. id
    
            id = (gd_t *) addr_sp; /* 指向一个结构体gd_t */    
    

    2.7 重定位代码

    分析重定位代码(start.S文件):relocate_code(addr _ sp, id, addr)–C语言调用汇编(其中addr _ sp存储到r0,id存储到r1,addr存储到r2)

    分析重定位代码

    2.8 clear_bss

    2.9 调用C函数board_init_r:第2阶段的代码

(三)修改代码

移植u-boot之修改代码

(I)修改代码— 建新板 _ 时钟 _ SDRAM _ UART

(II)修改代码—支持NAND启动

(III)修改代码—支持Nor Flash(读写)

(IV)修改代码—支持Nand Flash(读写)

(V)修改代码—支持DM9000网卡

(四)裁剪和修改默认参数

  1. 易用性裁剪uboot(修改配置文件smdk2440.h)



    —重新编译后的uboot大小

  2. 修改默认参数

    2.1 修改默认参数

    —启动后,从串口提示信息找到文件


    —设置配置文件中的参数

    2.2 参考内核中的分区

    set ipaddr 192.168.0.4
    
    set ethaddr 00:0c:29:07:33:a6
    
    set serverip 192.168.0.2
    
    tftp 30000000 uImage_4.3            
    
    bootm 30000000
    

    —设置参数

    —内核启动后,查看分区

    2.3 设置关于存储环境变量分区的参数

    —由sav命令的帮助信息(saveenv),找到所需文件

    —根据目录,查看其文件夹下的Makefile,找到该文件编译进uboot所需的宏,并在配置文件中定义该宏


    —在Env_nand.c文件的saveenv函数中,找到我们还需要定义的宏

    —在配置文件中,参照2.2中内核的分区,设置宏

  3. 上传配置文件,重新编译uboot后,在串口设置环境变量后用tftp烧写新的uboot到sdram,然后再用命令将其拷贝到NOR Flash中


    —重启后,打印变量

    —消除之前的警告


    —uboot移植到这里也基本上完整了。

  4. 设置分区–以便我们使用(仅仅是方便的功能)

    4.1 添加mtdparts命令所需的宏:所需要编进uboot的文件为cmd_mtdparts.c,在所在目录下的Makefile中找到所依赖的宏,并在配置文件中定义该宏

    4.2 在uboot源码下执行命令搜索:grep “mtdparts” * -nR,找出参考文件来仿照设置分区

    —参考文件

    —配置文件中定义

    4.3 根据老师试验,还需在Board.c文件中加入一行代码

    4.4 将修改的两文件上传,重新编译失败并解决该问题

    4.4 将修改的两文件上传,重新编译成功后,现在可以直接下载到sdram(不用设置环境变量),再复制到NOR Flash中重启开发板,执行mtdparts命令,出现如图打印

    4.5 试验–把下载到sdram中的拷贝到Nand Flash

    —下载uImage_4.3到sdram

    —擦除(原:nand erase 60000 200000)

    —nand写(原:nand write 30000000 60000 200000)

  5. 最后,我们在将之前的bootcmd修改一下,重新编译

    —此时,我们可以不用再烧写uboot,直接在串口上设置bootcmd,保存,重启

    —打印查看

    —此时我们再次reset,uboot启动后,倒数5秒后就会直接启动内核

(五)支持yaffs映像及制作补丁

  1. 试验1–烧写JFFS文件系统

    1.1 tftp烧写文件(嵌入式–第二期\资料光盘\bin\文件系统)fs_mini_mdev.jffs2

    tftp 30000000 fs_mini_mdev.jffs2
    

    1.2 拷贝到Nand中文件系统分区

    nand erase.part rootfs
    nand write.jffs2 30000000 260000 5b89a8
    注:这里260000就是文件系统分区的偏移地址,5b89a8就是fs_mini_mdev.jffs2的文件大小(tftp烧写完即可得到)
    

    1.3 设置bootargs

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

    1.4 boot后,启动内核,成功挂载jffs2文件系统

  2. 试验2–烧写yaffs文件系统

    1.1 重启开发板,tftp烧写文件(嵌入式–第二期\资料光盘\bin\文件系统)fs_mini_mdev.yaffs2

    tftp 30000000 fs_mini_mdev.yaffs2
    

    1.2 拷贝到Nand中文件系统分区

    nand erase.part rootfs
    nand write.yaffs 30000000 260000 889bc0
    注:这里260000就是文件系统分区的偏移地址,889bc0就是fs_mini_mdev.yaffs2的文件大小(tftp烧写完即可得到)
    

    执行完上条命令会出现如下图错误提示,需在配置文件中配置相应的宏,重启编译并烧写新的uboot后,重新烧写文件系统

    —找到根源文件

    —配置宏

    1.3 bootargs不用修改,选择默认即可

    1.4 boot后,启动内核,串口出现如下图错误指示

  3. 解决试验2的问题

    3.1 比较源文件fs_mini_mdev.yaffs2(用UE打开)和烧写到Nand中的文件(nand dump命令),发现Nand中的第一页的oob与源文件不符并且其余页均为数据均不符

    补充:现开发板使用的Nand:一页大小为2M(包含oob)
    

    —源文件(第一页oob)

    —nand(第一页oob)

    —源文件(第二页数据)

    —nand(第二页数据)

    3.2 修改相关文件

    —适用nand有坏块的情况

    3.3 重新编译、烧写uboot

    tftp 30000000 u-boot.bin;protect off all;erase 0 3ffff;cp.b 30000000 0 40000
    

    3.4 重复试验2烧写yaffs文件系统的步骤

到这里,我们已经完整的移植了2012版的uboot了!!!

<补充:制作uboot的补丁文件>

  1. 制作补丁文件(使用diff命令)

    —制作步骤

    —查看补丁文件

  2. 打补丁(进入之前源码解压后的文件夹)

    patch -p1 <../u-boot-2012.04.01_tp.patch

    注:../表示补丁文件在该文件夹的上层目录下,即/work/system
    

    最后,配置编译,生成新的uboot.bin文件,用tftp烧写到NOR Flash中,并将yaffs文件系统烧到NAND分区中,boot后成功挂载(与之前一步一步修改的效果是一样的)。


2017.11.25

你可能感兴趣的:(嵌入式linux)