上一篇文章我们已经修改了uboot源码使其能够正常打印输出了,但是输出停到了nand启动那里,所以这篇文章就来记录如何修改源码使uboot支持NAND启动。

原来的代码在链接时加了”-pie”选项, 使得u-boot.bin里多了”(.rel)”, “*(.dynsym)”使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K)。

1.去掉 “-pie”选项
在文件:arch/arm/config.mk的第75行,去掉:LDFLAGS_u-boot += -pie

2.在这之前会编写好一个init.c程序,拿到这里来用,init.c程序的编写会放到另一篇博客中,这里直接提供代码,代码链接为:init.c程序
将之前写好的文件init.c放到board/samsung/smdk2440目录, 并且修改Makefile,将init.c编译进去如下图:

3.修改start.S文件
start.S中有代码:

/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
    ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
    ldr r0,=0x00000000
    bl  board_init_f

将这一部分代码改为:

ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
    bic sp, sp, #7 /* 8-byte alignment for ABI compliance */

    /* lyy */
    bl   nand_init_ll
    mov r0, #0
    ldr r1, _TEXT_BASE

    ldr r2, _bss_end_ofs

    bl copy_code_to_sdram
    bl clear_bss

    ldr pc,=call_board_init_f


/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:

    ldr r0,=0x00000000
    bl  board_init_f

    /* unsigned int的值存在r0里,正好给board_init_r */
    ldr r1, _TEXT_BASE

    /* 调用第二阶段的代码*/
    bl board_init_r

4.删除重定位代码:
这下面的一大段代码是重定位代码,我们在这里不需要它,需要将其全部删除

/*------------------------------------------------------------------------------*/

/* * void relocate_code (addr_sp, gd, addr_moni) * * This "function" does not return, instead it continues in RAM * after relocating the monitor code. * */
    .globl  relocate_code
relocate_code:
    mov r4, r0  /* save addr_sp */
    mov r5, r1  /* save addr of gd */
    mov r6, r2  /* save addr of destination */

    /* Set up the stack */
stack_setup:
    mov sp, r4

    adr r0, _start
    cmp r0, r6
    beq clear_bss       /* skip relocation */
    mov r1, r6          /* r1 <- scratch for copy_loop */
    ldr r3, _bss_start_ofs
    add r2, r0, r3      /* r2 <- source end address */

copy_loop:
    ldmia   r0!, {r9-r10}       /* copy from source address [r0] */
    stmia   r1!, {r9-r10}       /* copy to target address [r1] */
    cmp r0, r2          /* until source end address [r2] */
    blo copy_loop

#ifndef CONFIG_SPL_BUILD
    /* * fix .rel.dyn relocations */
    ldr r0, _TEXT_BASE      /* r0 <- Text base */
    sub r9, r6, r0      /* r9 <- relocation offset */
    ldr r10, _dynsym_start_ofs  /* r10 <- sym table ofs */
    add r10, r10, r0        /* r10 <- sym table in FLASH */
    ldr r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */
    add r2, r2, r0      /* r2 <- rel dyn start in FLASH */
    ldr r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */
    add r3, r3, r0      /* r3 <- rel dyn end in FLASH */
fixloop:
    ldr r0, [r2]        /* r0 <- location to fix up, IN FLASH! */
    add r0, r0, r9      /* r0 <- location to fix up in RAM */
    ldr r1, [r2, #4]
    and r7, r1, #0xff
    cmp r7, #23 /* relative fixup? */
    beq fixrel
    cmp r7, #2 /* absolute fixup? */
    beq fixabs
    /* ignore unknown type of fixup */
    b   fixnext
fixabs:
    /* absolute fix: set location to (offset) symbol value */
    mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
    add r1, r10, r1     /* r1 <- address of symbol in table */
    ldr r1, [r1, #4] /* r1 <- symbol value */
    add r1, r1, r9      /* r1 <- relocated sym addr */
    b   fixnext
fixrel:
    /* relative fix: increase location by offset */
    ldr r1, [r0]
    add r1, r1, r9
fixnext:
    str r1, [r0]
    add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
    cmp r2, r3
    blo fixloop
#endif

clear_bss:
#ifndef CONFIG_SPL_BUILD
    ldr r0, _bss_start_ofs
    ldr r1, _bss_end_ofs
    mov r4, r6          /* reloc addr */
    add r0, r0, r4
    add r1, r1, r4
    mov r2, #0x00000000 /* clear */

clbss_l:str r2, [r0]        /* clear loop... */
    add r0, r0, #4
    cmp r0, r1
    bne clbss_l

    bl coloured_LED_init
    bl red_led_on
#endif

4.修改CONFIG_SYS_TEXT_BASE为0x33f00000
在代码中跳转到 :_TEXT_BASE

/* lyy */
    bl   nand_init_ll
    mov r0, #0
    ldr r1, _TEXT_BASE

跳转到lowlevel_init.S中的这里:

_TEXT_BASE:
    .word   CONFIG_SYS_TEXT_BASE

然后点击:CONFIG_SYS_TEXT_BASE
跳转到smdk2440.h中的这里:

#define CONFIG_SYS_TEXT_BASE 0x0

将CONFIG_SYS_TEXT_BASE的值改为:0x33f00000
5.修改board_init_f(arch/arm/lib/board.c中), 把relocate_code去掉

//relocate_code(addr_sp, id, addr);

同时去掉下面两句代码:

/*
     * reserve memory for U-Boot code, data & bss
     * round down to next 4 kB limit
     */
    //addr -= gd->mon_len;
    //addr &= ~(4096 - 1);

然后在这个函数的最后面加上:

return (unsigned int)id;

函数添加了int类型返回值,那么函数定义时的类型就得设置一下如下:

void board_init_f(ulong bootflag)
改为:

unsigned int board_init_f(ulong bootflag)

同时头文件中也需要定义类型:
在/include/common.h中275行有如下声明:

/* arch/$(ARCH)/lib/board.c */
void    board_init_f  (ulong) __attribute__ ((noreturn));
void    board_init_r  (gd_t *, ulong) __attribute__ ((noreturn));

将其改为:

/* arch/$(ARCH)/lib/board.c */
unsigned int board_init_f  (ulong);
void    board_init_r  (gd_t *, ulong);

__attribute__ ((noreturn));这句代码是指定没有返回值,所以需要去掉。

6.修改链接脚本: 把start.S, init.c, lowlevel.S等文件放在最前面
链接脚本为:/arch/arm/cpu/u-boot.lds
打开前面有一段:

.text :
        {
                __image_copy_start = .;
                CPUDIR/start.o (.text)
                *(.text)
        }

将其改为:

.text :
        {
                __image_copy_start = .;
                CPUDIR/start.o (.text)
                board/samsung/smdk2440/libsmdk2440.o (.text)
                *(.text)
        }

libsmdk2440.o包含了start.S, init.c, lowlevel.S,所以只需要把它放前面就行。

这些修改完之后,编译,烧写,看看效果:

这是我们将开关设置为NAND启动后的效果,至少现在已经支持了NAND启动。目前两种启动都可以了,接下来就是支持nand flash 和nor flash了,这样就可以通过NAND启动和NOR启动完全启动uboot了,我将放到另外两篇文章中讲,因为移植过程较为复杂,最后我会给出相关的移植顺序以及阅读文章的顺序,以及制作整个补丁,大家只需要打补丁,就可以一次性移植好这个uboot。

喜欢我的可以加加关注,同时也可以加我qq和微信一起学习交流
qq:1126137994
微信:liu1126137994
更多资源分享,共同进步!