加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

u-boot-2014.10移植第27天----nand flash启动(五)

发布时间:2020-12-15 17:24:07 所属栏目:百科 来源:网络整理
导读:硬件平台:tq2440 开发环境:Ubuntu-3.11 u-boot版本:2014.10 本文允许转载,请注明出处:http://blog.csdn.net/fulinus 为实现nand flash启动,最好的方法是使用u-boot自身提供的SPL方式,就是借助另一个相对独立的u-boot-spl.bin执行文件,将u-boot.bin拷

硬件平台:tq2440

开发环境:Ubuntu-3.11

u-boot版本:2014.10

本文允许转载,请注明出处:http://blog.csdn.net/fulinus


为实现nand flash启动,最好的方法是使用u-boot自身提供的SPL方式,就是借助另一个相对独立的u-boot-spl.bin执行文件,将u-boot.bin拷贝到SDRAM中去,再运行u-boot.bin。这样一来u-boot就可以再次重定向。我们这里首先尝试用一个老方法。

1、首先关闭“位置无关”的编译选项,在arch/arm/config.mk文件中,注释“pie”:

# needed for relocation
# LDFLAGS_u-boot += -pie

2、修改基地址,在include/configs/tq2440.h配置文件中,修改CONFIG_SYS_TEXT_BASE:

#define CONFIG_SYS_TEXT_BASE 0x33F80000

3、在board/samsung/tq2440目录下添加nand_read_ll.c文件,nand_read_ll.c文件内容如下:

/* NAND FLASH控制器 */

#define NFCONF  (*((volatile unsigned long *)0x4E000000))
#define NFCONT  (*((volatile unsigned long *)0x4E000004))
#define NFCMMD  (*((volatile unsigned long *)0x4E000008))
#define NFADDR  (*((volatile unsigned long *)0x4E00000C))
#define NFDATA  (*((volatile unsigned long *)0x4E000010))
#define NFSTAT  (*((volatile unsigned long *)0x4E000020))

static int is_boot_from_norflash(void)
{
    int val;
    volatile int *p = (volatile int *)0;

    val = *p;
    *p = 0x12345678;
    if(*p == 0x12345678){
        /* 写成功,是nand flash启动 */
        *p = val;
        return 0;
    }else{
        /* Nor flash 不能像内存一样写 */
        return 1;
    }
}

void nand_init_ll(void)
{
#define TACLS 0
#define TWRPH0  1
#define TWRPH1  0

    /* 设置时序 */
    NFCONT = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

    /* 使能Nand flash 控制器,初始化ECC,禁止片选 */
    NFCONT = (1<<4)|(1<<1)|(1<<0);
}

void clear_bss(void)
{
    extern int __bss_start,__bss_end;
    int *p = &__bss_start;

    for(; p < &__bss_end; p++){
        *p = 0;
    }
}

static void nand_select(void)
{
    NFCONT &= ~(1<<1);
}

static void nand_deselect(void)
{
    NFCONT |= (1<<1);
}

static void nand_cmd(unsigned char cmd)
{
    volatile int i;

    NFCMMD = cmd;

    for(i = 0; i < 10; i++);
}

static void nand_addr(unsigned int addr)
{
    volatile int i;
    unsigned int col = addr % 2048;
    unsigned int page = addr / 2048;

    NFADDR = col & 0xFF;
    
    for(i = 0; i < 10; i++);

    NFADDR = (col >> 8) & 0xFF;

    for(i = 0; i < 10; i++);

    NFADDR = page & 0xFF;

    for(i = 0; i < 10; i++);

    NFADDR = (page >> 8) & 0xFF;

    for(i = 0; i < 10; i++);

    NFADDR = (page >> 16) & 0xFF;

    for(i = 0; i < 10; i++);
}

static void nand_wait_ready(void)
{
    while(!(NFSTAT & 1));
}

static unsigned char nand_data(void)
{
    return NFDATA;
}

static void nand_read_ll(unsigned int addr,unsigned char *buf,unsigned int len)
{
    int i = 0;
    int col = addr % 2048;

    /* 1.选中 */
    nand_select();

    while(i < len)
    {
        /* 2.发出读命令:00h */
        nand_cmd(0x00);

        /* 3.发出地址指令 */
        nand_addr(addr);

        /* 4.发出读命令:30h */
        nand_cmd(0x30);

        /* 5.判断状态 */
        nand_wait_ready();

        /* 6.读数据 */
        for(; (col < 2048) && (i < len); col++){
            buf[i] = nand_data();
            i++;
            addr++;
        }

        col = 0;
    }

    /* 7.取消选中 */
    nand_deselect();
}

void copy_code_to_sdram(unsigned char *src,unsigned char *dest,unsigned int len)
{
    int i = 0;

    /* 如果是Nor flash 启动 */
    if(is_boot_from_norflash()){
        while(i < len){
            dest[i] = src[i];
            i++;
        }
    }else{
        nand_init_ll();
        nand_read_ll((unsigned int)src,dest,len);
    }
}

4、修改board/samsung/tq2440目录下的Makefile文件:

obj-y   := tq2440.o
+ obj-y   += nand_read_ll.o
obj-y   += lowlevel_init.o


5、修改arch/arm/lib/crt0.S文件:

ENTRY(_main)


/*
?* Set up initial C runtime environment and call board_init_f(0).
?*/


#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
? ? ? ? ldr ? ? sp,=(CONFIG_SPL_STACK)
#else
? ? ? ? ldr ? ? sp,=(CONFIG_SYS_INIT_SP_ADDR)
#endif
? ? ? ? bic ? ? sp,sp,#7 ? ? ?/* 8-byte alignment for ABI compliance */
? ? ? ? mov ? ? r2,sp
? ? ? ? sub ? ? sp,#GD_SIZE ? ? ? ?/* allocate one GD above SP */
? ? ? ? bic ? ? sp,#7 ? ? ?/* 8-byte alignment for ABI compliance */
? ? ? ? mov ? ? r9,sp ? ? ? ? ?/* GD is above SP */


#if 1
__TEXT_BASE:
? ? .word CONFIG_SYS_TEXT_BASE
? ??
? ? mov r0,#0
? ? ldr r1,__TEXT_BASE


? ? ldr r2,__TEXT_BASE


? ? ldr r3,=__bss_end


? ? sub r2,r3,r2


? ? bl copy_code_to_sdram
? ? bl clear_bss


? ? ldr pc,=call_board_init_f


call_board_init_f:
? ? mov r0,#0
? ? bl board_init_f


? ? ? ? ldr ? ? sp,[r9,#GD_START_ADDR_SP] ? ? /* sp = gd->start_addr_sp */
? ? ? ? bic ? ? sp,#7 ? ? ?/* 8-byte alignment for ABI compliance */
? ? ? ? ldr ? ? r9,#GD_BD] ? ? ? ? ? ? ? ?/* r9 = gd->bd */
? ? ? ? sub ? ? r9,r9,#GD_SIZE ? ? ? ? ? ? ? ?/* new GD is below bd */


? ? ldr r1,__TEXT_BASE
? ? bl board_init_r
#else


? ? ? ? mov ? ? r1,sp
? ? ? ? mov ? ? r0,#0
clr_gd:
? ? ? ? cmp ? ? r1,r2 ? ? ? ? ? ? ? ? ?/* while not at end of GD */
? ? ? ? strlo ? r0,[r1] ? ? ? ? ? ? ? ?/* clear 32-bit GD word */
? ? ? ? addlo ? r1,r1,#4 ? ? ? ? ? ? ?/* move to next */
? ? ? ? blo ? ? clr_gd
#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)
? ? ? ? sub ? ? sp,#CONFIG_SYS_MALLOC_F_LEN
? ? ? ? str ? ? sp,#GD_MALLOC_BASE]
#endif
? ? ? ? /* mov r0,#0 not needed due to above code */
? ? ? ? bl ? ? ?board_init_f


#if ! defined(CONFIG_SPL_BUILD)


/*
?* Set up intermediate environment (new sp and gd) and call
?* relocate_code(addr_moni). Trick here is that we'll return
?* 'here' but relocated.
?*/


? ? ? ? ldr ? ? sp,#GD_SIZE ? ? ? ? ? ? ? ?/* new GD is below bd */


? ? ? ? adr ? ? lr,here
? ? ? ? ldr ? ? r0,#GD_RELOC_OFF] ? ? ? ? /* r0 = gd->reloc_off */
? ? ? ? add ? ? lr,lr,r0
? ? ? ? ldr ? ? r0,#GD_RELOCADDR] ? ? ? ? /* r0 = gd->relocaddr */
? ? ? ? b ? ? ? relocate_code
here:


/* Set up final (full) environment */


? ? ? ? bl ? ? ?c_runtime_cpu_setup ? ? /* we still call old routine here */


? ? ? ? ldr ? ? r0,=__bss_start ? ? ? ?/* this is auto-relocated! */
? ? ? ? ldr ? ? r1,=__bss_end ? ? ? ? ?/* this is auto-relocated! */


? ? ? ? mov ? ? r2,#0x00000000 ? ? ? ? /* prepare zero to clear BSS */


clbss_l:cmp ? ? r0,r1 ? ? ? ? ? ? ? ? ?/* while not at end of BSS */
? ? ? ? strlo ? r2,[r0] ? ? ? ? ? ? ? ?/* clear 32-bit BSS word */
? ? ? ? addlo ? r0,r0,#4 ? ? ? ? ? ? ?/* move to next */
? ? ? ? blo ? ? clbss_l


? ? ? ? bl coloured_LED_init
? ? ? ? bl red_led_on


? ? ? ? /* call board_init_r(gd_t *id,ulong dest_addr) */
? ? ? ? mov ? ? r0,r9 ? ? ? ? ? ? ? ? ?/* gd_t */
? ? ? ? ldr ? ? r1,#GD_RELOCADDR] /* dest_addr */
? ? ? ? /* call board_init_r */
? ? ? ? ldr ? ? pc,=board_init_r ? ? ? /* this is auto-relocated! */


? ? ? ? /* we should not return here. */


#endif
#endif


ENDPROC(_main)


6、修改arch/arm/lib/board.c 文件中的board_init_f函数:

//void board_init_f(ulong bootflag)
unsigned int board_init_f(ulong bootflag)
。。。

? ? //addr -= gd->mon_len;
? ? //addr &= ~(4096 - 1);
? ? addr = CONFIG_SYS_TEXT_BASE;

。。。

? ? memcpy(id,(void *)gd,sizeof(gd_t));


? ? return (unsigned int)id;
}?

7、同时修改include/common.h头文件中board_init_f函数的声明:

//void ?board_init_f(ulong);
unsigned int board_init_f(ulong);


8、修改连接脚本arch/arm/cpu/u-boot.lds文件,将nand_read_ll.c文件放在前4K字节中:

? ? .text :
? ? {
? ? ? ? *(.__image_copy_start)
? ? ? ? *(.vectors)
? ? ? ? CPUDIR/start.o (.text*)
? ? ? ? board/samsung/tq2440/lowlevel_init.o(.text*)
? ? ? ? board/samsung/tq2440/nand_read_ll.o(.text*)

? ? ? ? *(.text*) ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? } ?

9、修改arch/arm/config.mk文件,将checkarmreloc功能注释掉:

# ALL-y += checkarmreloc

10、编译

不成功,感觉这个方法很牵强,换一种;

明天继续;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读