U-boot-2014.04移植到MINI2440(9) nor flash启动和nand flash 启动

时间:2021-09-22 16:36:47

在mini2440上,nor flash启动和nand flash启动可以满足不同的需要,这里进行移植,nor的启动移植比较简单,因为不需要进行代码的重定向,nand的启动相对复杂,这里先从nor开始,进入正题:

      

       .修改支持nor flash启动

       第一步:修改mini2440.h

       在第27行:

       #define CONFIG_SYS_TEXT_BASE       0x30008000

       这里将这个值改为0x0,因为从nor flash启动,直接在0地址执行就可以,不需要再拷贝到sdram中。修改为:

       #define CONFIG_SYS_TEXT_BASE       0x0

       之前我的帖子分析的start.s启动过程等等,都是对应的没有做代码重定向,没有从nand启动,因为那时候只在sdram里执行u-boot,在第37行:

       //#define CONFIG_SKIP_LOWLEVEL_INIT

       将其注释掉,这样程序执行:

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl    cpu_init_crit

#endif

       因为我们没有定义CONFIG_SKIP_LOWLEVEL_INIT,所以程序就会跳转到cpu_init_crit里面,在cpu_init_crit里面,程序进一步跳转到    

mov       ip, lr

       bl    lowlevel_init

       mov       lr,ip

       进入lowlevel_init以后,就会执行这一段代码:

       ldr    r0, =SMRDATA

       ldr   r1,=CONFIG_SYS_TEXT_BASE

       sub  r0,r0, r1

       因为TEXT_BASE现在被我们设置为了0,SMRDATA就会从相对0地址的地方开始,这样我们就可以从nor flash启动。

      

第二步:修改lowlevel_init.s

       第113行:

       #define REFCNT                    1113      

       这个REFCNT其实是位宽和刷新频率的设置,这里需要做一个修改,改为如下:

       #define REFCNT                    0x4f4

      

第三步:编译测试

       这里我编译没有问题,下载进去在执行erase的时候,无法擦除我的nor flash,这可能是我原来的u-boot对nor flash的第一个块进行了保护,即使protectoff all也没用,但是可以擦除别的块,所以这里我借助了j-link来下载我移植的u-boot到nor flash。具体的下载步骤不懂得可以上网查下,下载进去之后启动,输出如下信息:

U-Boot 2014.04 (Sep 02 2015 - 15:09:02)

 

CPUID: 32440001

FCLK:     400 MHz

HCLK:     100 MHz

PCLK:      50 MHz

DRAM: 64 MiB

WARNING: Caches not enabled

Flash: 2 MiB

NAND: 256 MiB

*** Warning - bad CRC, using defaultenvironment

 

In:   serial

Out:  serial

Err:  serial

Net:  dm9000

MINI2440 Deep_l_zh #

说明我们是可以从nor启动了,下面进入nand的移植,我们一般nor只是用来调试和学习,所以掌握从nand启动是很重要的。

      

       .nand flash启动移植

       第一步:去除-pie选项

       在arch/arm/config.mk中,第82行,修改如下:

       # needed for relocation

#LDFLAGS_u-boot += -pie

       这里是为了避免重定向后新的地址比较复杂,所以还是采用老的办法进行修改。

       第二步:修改mini2440.h

       重新将TEXT_BASE制定为0x33f80000

       #define CONFIG_SYS_TEXT_BASE       0x33f80000

       第三步:添加nand_read_b.c文件并修改makefile

       在/board/mini2440/mini2440下,修改Makefile,将其编译进去,修改部分如下:

obj-y      :=mini2440.o

obj-y      += nand_read_b.o

obj-y      +=lowlevel_init.o

       接着再该目录下创建nand_read_b.c文件,该文件所有内容如下:

#define NFCONF(*((volatile unsigned long*)0x4E000000))

#define NFCONT(*((volatileunsigned long *)0x4E000004))

#define NFCMMD(*((volatileunsigned char *)0x4E000008))

#define NFADDR(*((volatileunsigned char *)0x4E00000C))

#define NFDATA(*((volatileunsigned char *)0x4E000010))

#define NFSTAT(*((volatileunsigned char *)0x4E000020))

 

 

 

static void nand_read_b(unsignedint addr,unsigned char *buf,unsigned int len);

 

static intisBootFromNorFlash(void)

{

       volatileint *p = (volatile int *)0;

       intval;

       val= *p;

       *p= 0x12345678;

       if(*p == 0x12345678)

       {

       /*写成功, nand 启动 */

       *p= val;

       return0;

       }    

       else

              {

                     /*NOR不能像内存一样写 */

                     return1;

                     }

}

 

void nand_init_b(void)

{

              #defineTACLS 3

              #defineTWRPH0 3

              #defineTWRPH1 2

              /*设置时序 */

              NFCONF= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

              /*使能 NAND Flash控制器, 初始化 ECC,禁止片选 */

              NFCONT= (1<<4)|(1<<1)|(1<<0);

}

 

void copy_code_to_sdram(unsignedchar *src, unsigned char *dest, unsigned int len)

{

int i = 0;

/* 如果是 NOR启动 */

       if(isBootFromNorFlash())

       {

       while(i < len)

              {

                     dest[i]= src[i];

              i++;

              }

       }

else

       {

       nand_init_b();

       nand_read_b((unsignedint)src, dest, len);

       }

}

 

void clear_bss(void)

{

       externint __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(unsignedchar cmd)

{

       volatileint i;

       NFCMMD= cmd;

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

}

 

static void nand_addr(unsignedint addr)

{

       unsignedint col = addr % 2048;

       unsignedint page = addr / 2048;

       volatileint i;

       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 charnand_data(void)

{

  return NFDATA;

}

 

static void nand_read_b(unsignedint addr, unsigned char *buf, unsigned int len)

{

int col = addr % 2048;

int i = 0;

/* 1. 选中 */

nand_select();

while (i < len)

       {

       /*2. 发出读命令 00h */

       nand_cmd(0x00);

       /*3. 发出地址( 5步发出) */

       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();

}

 

第四步:修改crt0.S

       在arch/arm/lib/crt0.S文件中,修改如下:

       ENTRY(_main)

 

/*

 * Set up initial C runtime environment andcall board_init_f(0).

 */

 

#ifdefined(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 ABIcompliance */

       sub  sp,sp, #GD_SIZE     /* allocate one GD aboveSP */

       bic  sp,sp, #7      /* 8-byte alignment for ABIcompliance */

       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, sp, #7 /* 8-byte alignment forABI compliance */

       ldr r9, [r9, #GD_BD] /* r9 = gd->bd */

       subr9, r9, #GD_SIZE /* new GD is below bd*/

       ldr r1, __TEXT_BASE

       bl board_init_r

       #else

       mov       r0,#0

       bl    board_init_f

 

#if !defined(CONFIG_SPL_BUILD)

 

/*

 * Set up intermediate environment (new sp andgd) and call

 * relocate_code(addr_moni). Trick here is thatwe'll return

 * 'here' but relocated.

 */

 

       ldr   sp,[r9, #GD_START_ADDR_SP] /* sp =gd->start_addr_sp */

       bic  sp,sp, #7      /* 8-byte alignment for ABIcompliance */

       ldr   r9,[r9, #GD_BD]             /* r9 = gd->bd*/

       sub  r9,r9, #GD_SIZE             /* new GD isbelow bd */

 

       adr  lr,here

       ldr   r0,[r9, #GD_RELOC_OFF]          /* r0 =gd->reloc_off */

       add lr,lr, r0

       ldr   r0,[r9, #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 isauto-relocated! */

 

       mov       r2,#0x00000000        /* prepare zero toclear 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, ulongdest_addr) */

       mov    r0, r9                  /* gd_t */

       ldr   r1,[r9, #GD_RELOCADDR] /* dest_addr */

       /* call board_init_r */

       ldr   pc,=board_init_r       /* this isauto-relocated! */

 

       /* we should not return here. */

#endif

#endif

 

ENDPROC(_main)

 

       第五步:修改board_init_f函数

       在arch/arm/lib/board.c中,第265行,修改为:

       unsigned intboard_init_f(ulong bootflag)

{

bd_t *bd;

       init_fnc_t **init_fnc_ptr;

       gd_t *id;

       注释掉372的addr,添加新的addr:

       //addr -= gd->mon_len;

       //addr &= ~(4096 - 1);

addr=CONFIG_SYS_TEXT_BASE;

在结尾461行添加:

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

       return (unsignedint)id;

}

 

       第六步:修改common.h

       在/include下,common.h第298行,修改为:

       unsigned int board_init_f(ulong);

      

第七步:修改链接脚本u-boot.lds

       在arch/arm/cpu/下,u-boot.lds,第20行:

*(.__image_copy_start)

       CPUDIR/start.o (.text*)

       board/mini2440/mini2440/lowlevel_init.o(.text*)

       board/mini2440/mini2440/nand_read_b.o(.text*)

       *(.text*)

       同时需要修改/board/mini2440/mini2440下的Makefile,修改如下:

        obj-y      :=mini2440.o

extra-y   :=nand_read_b.o

extra-y   +=lowlevel_init.o

      

       第八步:修改顶层/arch/arm/config.mk

       注释掉checkarmreloc这部分,否则编译会出错

在第105行:

       #ALL-y += checkarmreloc

      

       第九步:编译测试

       从nor启动,然后下载到nand之后,关闭电源,s2开关打到nand处启动,出现如下信息:

 U-Boot 2014.04 (Sep 02 2015 - 18:54:01)

CPUID: 32440001

FCLK:     400 MHz

HCLK:     100 MHz

PCLK:      50 MHz

DRAM: 64 MiB

WARNING: Caches not enabled

Flash: *** failed ***

### ERROR ### Please RESET the board ###

       因为这时候从nand启动,检测不到nor flash的信息,但是使用友善的u-boot从nand启动是可以读到nor的信息的,并且可以使用nor的命令对其进行操作,看来这个地址空间还有很多文章,这里能够从nand启动进行内核引导的是我们的目的。所以,屏蔽这个错误,这个错误在我们移植nor flash读写的时候就探讨过了,这里进去arch/arm/lib/board.c,第577行:

       # endif /* CONFIG_SYS_FLASH_CHECKSUM */

       } else {

              puts(failed);

       //     hang();

       }

       把这个hang()函数注释掉。

       再次编译下载。

 U-Boot 2014.04 (Sep 02 2015 - 19:06:04)

CPUID: 32440001

FCLK:     400 MHz

HCLK:     100 MHz

PCLK:      50 MHz

DRAM: 64 MiB

WARNING: Caches not enabled

Flash: *** failed ***

NAND: 256 MiB

*** Warning - bad CRC, using defaultenvironment

 

In:   serial

Out:  serial

Err:  serial

Net:  dm9000

MINI2440 Deep_l_zh #

       可以看到成功了,不得不说,移植过程参照网上大神移植到tq2440的帖子,但是期间遇到了很多小问题,这里没有一一写下来,对自己还是收获不少,如有不正确,还请指出,大家共同进步!