开发环境:主机:Window XP SP2;linux:VMware7.01+ubuntu9.10;目标板:扬创utu2440-F开发板

交叉编译器:arm-linux-gcc4.3.2(一开始用的是编译内核的版本arm-linux-gcc3.4.1,但出现了软浮点问题,于是换成了现在用的版本,当然本人编译内核的时候还是用3.4.1版本)

摘要:在熟悉了使用JLINK间接烧写u-boot至FLASH的方法与步骤使用AXD和JLINK调试u-boot方法与步骤后,接下来就是移植u-boot-2011.03中最关键部分了:移植NAND FLASH部分,使u-boot支持从NAND FLASH启动和读写。本节内容比较多,修改的代码也比较多,特别还涉及到了ARM汇编,所以请保持耐心。

1. u-boot的NAND FLASH部分移植准备

移植u-boot的NAND FLASH部分特别是支持u-boot从NAND FLASH启动部分,需要做一些相关准备。主要是:

1.1 掌握u-boot启动第一阶段的调试方法

详见reille blog中关于使用AXD和JLINK调试u-boot:使用AXD和JLINK调试u-boot方法与步骤,以及参考本文A.5所指的参考资料。

1.2 挂机(即烧写自己移植的u-boot到NAND FLASH后启动不起来)了怎么办?

详见reille blog中关于使用JLINK间接烧写u-boot的方法与步骤:使用AXD和JLINK调试u-boot方法与步骤

1.3 从Nand Flash启动U-BOOT的基本原理

1.3.1 前4K的问题

如果S3C2440被配置成从Nand Flash启动(配置由硬件工程师在电路板设置), S3C2440的Nand Flash控制器有一个特殊的功能,在S3C2440上电后,Nand Flash控制器会自动的把Nand Flash上的前4K数据搬移到4K内部RAM中,并把0x00000000设置内部RAM的起始地址,CPU从内部RAM的0x00000000位置开 始启动。这个过程不需要程序干涉。程序员需要完成的工作,是把最核心的启动程序放在Nand Flash的前4K中。

1.3.2 启动程序的安排

由于Nand Flash控制器从Nand Flash中搬移到内部RAM的代码是有限的,所以在启动代码的前4K里,我们必须完成S3C2410的核心配置以及把启动代码(U-BOOT)剩余部分搬到RAM中运行。u-boot源码不支持从nand flash启动,可是s3c2410支持从nand flash启动,加电后s3c2440将nand flash的前4k(保存有u-boot的部分功能–拷贝功能–把nand flash中的内容拷贝到SDRAM)拷贝到sram(s3c2440芯片内的sram)。这就需要修改u-boot源码,增加u-boot的功能: 使u-boot在得到执行权后能够将其自身拷贝到开发板上SDRAM中,以便处理器能够执行u-boot

2. u-boot的NAND FLASH部分移植

以下的操作是经过整理的,详细过程见A.1.1所列出的网址

注意,如果u-boot要在SDRAM中调试,得把u-boot-2011.03\include\configs\reille2440.h文件中的宏定义CONFIG_SKIP_LOWLEVEL_INIT开启和关闭CONFIG_S3C2440_NAND_BOOT宏定义

2.1 修改u-boot-2011.03\include\configs\reille2440.h文件

2.1.1 注销如下定义:

/* del by guoyirong 2011.06.19
#define    CONFIG_ENV_IS_IN_FLASH    1
#define CONFIG_ENV_SIZE        0x10000    // Total Size of Environment Sector
*/

2.1.2 reille2440.h文件末增加如下定义:

/**********************************************************/
/* 以下为NAND启动及驱动相关 added by guoyirong 2011.06.19 */

/*
* 去掉NOR FLASH支持,如果不去掉,则arch/arm/lib/libarm.o被连接到了4K之外,
* 4K之内没有这个程序libarm是不可能实现NAND启动的
*/
#define CONFIG_SYS_NO_FLASH
//#define CONFIG_CMD_FLASH      /* flinfo, erase, protect   */
//#define CONFIG_CMD_IMLS       /* List all found images  */

#define CONFIG_S3C2440_NAND_BOOT  1
#define CONFIG_NAND_S3C2440
#define NAND_CTL_BASE  0x4E000000  //Nand Flash配置寄存器基地址,查2440手册可得知
#define oNFCONF  0x00 //相对Nand配置寄存器基地址的偏移量,还是配置寄存器的基地址
#define oNFCONT  0x04 //相对Nand配置寄存器基地址的偏移量,可得到控制寄存器的基地址(0x4E000004)
#define oNFADDR  0x0c //相对Nand配置寄存器基地址的偏移量,可得到地址寄存器的基地址(0x4E00000c)
#define oNFDATA  0x10 //相对Nand配置寄存器基地址的偏移量,可得到数据寄存器的基地址(0x4E000010)
#define oNFCMD   0x08 //相对Nand配置寄存器基地址的偏移量,可得到指令寄存器的基地址(0x4E000008)
#define oNFSTAT  0x20 //相对Nand配置寄存器基地址的偏移量,可得到状态寄存器的基地址(0x4E000020)
#define oNFECC   0x2c //相对Nand配置寄存器基地址的偏移量,可得到ECC寄存器的基地址(0x4E00002c)

#define UBOOT_LENGTH  0x40000 /*256K*/

#define STACK_BASE  0x33f00000     //定义堆栈的地址
#define STACK_SIZE  0x8000         //堆栈的长度大小

#define CONFIG_CMD_NAND
#define CONFIG_CMDLINE_EDITING

#define  CONFIG_NAND_S3C2440

#ifdef CONFIG_CMDLINE_EDITING
#undef CONFIG_AUTO_COMPLETE
#else
#define CONFIG_AUTO_COMPLETE
#endif

/* NAND flash settings */
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE            0x4E000000 //Nand配置寄存器基地址
#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_MTD_NAND_VERIFY_WRITE    1
//#define NAND_SAMSUNG_LP_OPTIONS       1  //注意:我们这里是64M的Nand Flash,所以不用,如果是128M的大块Nand Flash,则需加上
#endif

// 添加环境变量保存到Nand的宏(注意:如果你要使用从Nor启动的saveenv命令,则不要这些Nand宏定义)
#define CONFIG_ENV_IS_IN_NAND  1
#define CONFIG_ENV_OFFSET      0x30000 //将环境变量保存到nand中的0x30000位置
#define CONFIG_ENV_SIZE        0x10000 /* Total Size of Environment Sector */

2.1.3 注释CONFIG_SKIP_LOWLEVEL_INIT

//#define CONFIG_SKIP_LOWLEVEL_INIT

2.2 增加从NAND FLASH读取数据到内存的函数,文件名为nand_read.c,放到board\samsung\reille2440\nand_read.c下

nand_read.c文件内容如下:

/*
* board\samsung\reille2440\nand_read.c
*
* (C) Copyright 2011
* reille <http://velep.com/> <reille@qq.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*/

#include <config.h>

#define NF_BASE   0x4E000000  //Nand Flash配置寄存器基地址

#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int  *)(x))

#define NFCONF __REGi(NF_BASE + 0x0 )  //通过偏移量还是得到配置寄存器基地址
#define NFCONT __REGi(NF_BASE + 0x4 )  //通过偏移量得到控制寄存器基地址
#define NFCMD  __REGb(NF_BASE + 0x8 )  //通过偏移量得到指令寄存器基地址
#define NFADDR __REGb(NF_BASE + 0xC )  //通过偏移量得到地址寄存器基地址
#define NFDATA __REGb(NF_BASE + 0x10)  //通过偏移量得到数据寄存器基地址
#define NFSTAT __REGb(NF_BASE + 0x20)  //通过偏移量得到状态寄存器基地址

#define NAND_CHIP_ENABLE  (NFCONT &= ~(1<<1))  //Nand片选使能
#define NAND_CHIP_DISABLE (NFCONT |= (1<<1))   //取消Nand片选
#define NAND_CLEAR_RB     (NFSTAT |= (1<<2))
#define NAND_DETECT_RB    { while(! (NFSTAT&(1<<2)) );}

#define NAND_SECTOR_SIZE 512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE – 1)

#if 0
#define DEBUGN    printf
#else
#define DEBUGN(x, args …) {}
#endif

/* low level nand read function */
int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size){
int i, j;

//    DEBUGN(“nand_read_ll………….\n”);// 这句不能有,否则uboot不能从NAND FLASH启动起来

if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)){
return -1; //地址或长度不对齐
}

NAND_CHIP_ENABLE; //选中Nand片选

for(i=start_addr; i < (start_addr + size);){
//发出READ0指令
NAND_CLEAR_RB;
NFCMD = 0;

//对Nand进行寻址
NFADDR = i & 0xFF;
NFADDR = (i >> 9) & 0xFF;
NFADDR = (i >> 17) & 0xFF;
NFADDR = (i >> 25) & 0xFF;

NAND_DETECT_RB;

for(j=0; j < NAND_SECTOR_SIZE; j++, i++){
*buf = (NFDATA & 0xFF);
buf++;
}
}

NAND_CHIP_DISABLE; //取消片选信号

return    0;

}

2.3 修改cmd_bootm.c文件

a)把81和82行注释掉,如下:

// abort NOR FLASH  |del by guoyirong 2011.06.25
//#include <mtd/cfi_flash.h>
//extern flash_info_t flash_info[]; /* info for FLASH chips */

b)把函数int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])整体注释掉,改为如下:

int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]){return (0);}

做一步是因为要去掉NOR FLASH支持(如果不去掉,则arch/arm/lib/libarm.o被连接到了4K之外,4K之内没有这个程序libarm是不可能实现NAND启动的),但去掉后,在这里会出现编译错误,如下所示:

In file included from cmd_bootm.c:80:

/home/reille/work/u-boot-2011.03/include/mtd/cfi_flash.h:174: error: expected ‘)’ before ‘*’ token

cmd_bootm.c:81: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘flash_info’

cmd_bootm.c: In function ‘do_imls’:

cmd_bootm.c:1145: error: ‘flash_info_t’ undeclared (first use in this function)

cmd_bootm.c:1145: error: (Each undeclared identifier is reported only once

cmd_bootm.c:1145: error: for each function it appears in.)

cmd_bootm.c:1145: error: ‘info’ undeclared (first use in this function)

cmd_bootm.c:1149: error: ‘flash_info’ undeclared (first use in this function)

cmd_bootm.c:1152: error: ‘FLASH_UNKNOWN’ undeclared (first use in this function)

make[1]: *** [cmd_bootm.o] Error 1

make[1]: Leaving directory `/home/reille/work/u-boot-2011.03/common’

make: *** [common/libcommon.o] Error 2

reille@ubuntu:~/work/u-boot-2011.03$

注释掉后就不会出现了,按理来说在u-boot-2011.03\include\configs\reille2440.h文件中去掉了宏定义CONFIG_CMD_IMLS及加上宏定义CONFIG_SYS_NO_FLASH就不会出现编译错误了,但不知道为什么没能起作用。

2.4 修改board/samsung/reille2440/makefile

#del by guoyirong 2011.06.25
#COBJS    := reille2440.o flash.o nand_read.o
# no nor flash |add by guoyirong 2011.06.25
COBJS    := reille2440.o nand_read.o

注意,不再有NOR FLASH了,因此去掉flash.o

2.5 drivers/mtd/nand/目录下新建s3c2440_nand.c文件实现对NAND FLASH的操作

2.5.1 s3c2440_nand.c文件内容如下:

/*
* drivers/mtd/nand/s3c2440_nand.c
*
* 实现对nand FLASH的操作
*
* (C) Copyright 2011
* reille <http://velep.com/> <reille@qq.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*/

#include <common.h>
#include <nand.h>
#include <asm/arch/s3c24x0_cpu.h>
#include <asm/io.h>

#if 0
#define DEBUGN    printf
#else
#define DEBUGN(x, args …) {}
#endif

#define __REGb(x)    (*(volatile unsigned char *)(x))
#define __REGi(x)    (*(volatile unsigned int *)(x))

#define NF_BASE  0x4e000000             //Nand配置寄存器基地址
#define NFCONF   __REGi(NF_BASE + 0x0)  //偏移后还是得到配置寄存器基地址
#define NFCONT   __REGi(NF_BASE + 0x4)  //偏移后得到Nand控制寄存器基地址
#define NFCMD    __REGb(NF_BASE + 0x8)  //偏移后得到Nand指令寄存器基地址
#define NFADDR   __REGb(NF_BASE + 0xc)  //偏移后得到Nand地址寄存器基地址
#define NFDATA   __REGb(NF_BASE + 0x10) //偏移后得到Nand数据寄存器基地址
#define NFMECCD0 __REGi(NF_BASE + 0x14) //偏移后得到Nand主数据区域ECC0寄存器基地址
#define NFMECCD1 __REGi(NF_BASE + 0x18) //偏移后得到Nand主数据区域ECC1寄存器基地址
#define NFSECCD  __REGi(NF_BASE + 0x1C) //偏移后得到Nand空闲区域ECC寄存器基地址
#define NFSTAT   __REGb(NF_BASE + 0x20) //偏移后得到Nand状态寄存器基地址
#define NFSTAT0  __REGi(NF_BASE + 0x24) //偏移后得到Nand ECC0状态寄存器基地址
#define NFSTAT1  __REGi(NF_BASE + 0x28) //偏移后得到Nand ECC1状态寄存器基地址
#define NFMECC0  __REGi(NF_BASE + 0x2C) //偏移后得到Nand主数据区域ECC0状态寄存器基地址
#define NFMECC1  __REGi(NF_BASE + 0x30) //偏移后得到Nand主数据区域ECC1状态寄存器基地址
#define NFSECC   __REGi(NF_BASE + 0x34) //偏移后得到Nand空闲区域ECC状态寄存器基地址
#define NFSBLK   __REGi(NF_BASE + 0x38) //偏移后得到Nand块开始地址
#define NFEBLK   __REGi(NF_BASE + 0x3c) //偏移后得到Nand块结束地址

#define S3C2440_NFCONT_nCE  (1<<1)
#define S3C2440_ADDR_NALE   0x0c
#define S3C2440_ADDR_NCLE   0x08

ulong IO_ADDR_W = NF_BASE;

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl){
struct nand_chip *chip = mtd->priv;

DEBUGN(“hwcontrol(): 0x%02x 0x%02x\n”, cmd, ctrl);

if (ctrl & NAND_CTRL_CHANGE) {
IO_ADDR_W = NF_BASE;
if (!(ctrl & NAND_CLE)){                //要写的是地址
IO_ADDR_W |= S3C2440_ADDR_NALE;
}

if (!(ctrl & NAND_ALE)){                //要写的是命令
IO_ADDR_W |= S3C2440_ADDR_NCLE;
}

if (ctrl & NAND_NCE){
NFCONT &= ~S3C2440_NFCONT_nCE;    //使能nand flash
}
else{
NFCONT |= S3C2440_NFCONT_nCE;     //禁止nand flash
}
}

if (cmd != NAND_CMD_NONE){
writeb(cmd,(void *)IO_ADDR_W);
}
}

static int s3c2440_dev_ready(struct mtd_info *mtd){
DEBUGN(“dev_ready\n”);
return (NFSTAT & 0x01);
}

int board_nand_init(struct nand_chip *nand){
u_int32_t cfg;
u_int8_t tacls, twrph0, twrph1;
struct s3c24x0_clock_power * const clk_power = s3c24x0_get_base_clock_power();

DEBUGN(“board_nand_init()\n”);

/*clk_power->CLKCON |= (1 << 4);*/
writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);
twrph0 = 4; twrph1 = 2; tacls = 0;
cfg = (tacls<<12)|(twrph0<<8)|(twrph1<<4);
NFCONF = cfg;
cfg = (1<<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT = cfg;

/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;

/* read_buf and write_buf are default */

/* read_byte and write_byte are default */

/* hwcontrol always must be implemented */
nand->cmd_ctrl = s3c2440_hwcontrol;

nand->dev_ready = s3c2440_dev_ready;

return    0;

}

2.5.2 在drivers/mtd/nand/Makefile文件中添加s3c2440_nand.c的编译项

COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

2.6 修改start.S文件

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl    cpu_init_crit
#endif

/************************START*******************************/
/* 添加2440中u-boot从Nand启动 added by guoyiorng 2011.06.25 */
#ifdef CONFIG_S3C2440_NAND_BOOT
mov r1, #NAND_CTL_BASE           // 复位Nand Flash
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF]           // 设置配置寄存器的初始值,参考s3c2440手册
ldr r2, [r1, #oNFCONF]

    ldr r2, =( (1<<4)|(0<<1)|(1<<0) )
str r2, [r1, #oNFCONT]           // 设置控制寄存器
ldr r2, [r1, #oNFCONT]

    ldr r2, =(0x6)                   // RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff                    // 复位command
strb r2, [r1, #oNFCMD]

    mov r3, #0                       // 等待
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1

nand2:
ldr r2, [r1, #oNFSTAT]           // 等待就绪
tst r2, #0x4
beq nand2

    ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2                 // 取消片选
str r2, [r1, #oNFCONT]

    //get read to call C functions (for nand_read())
ldr sp, DW_STACK_START           // 安装栈的起始地址,为C代码准备堆栈,DW_STACK_START定义在下面
mov fp, #0                        // 初始化帧指针寄存器

    //copy U-Boot to RAM
ldr r0, =CONFIG_SYS_TEXT_BASE    // 传递给C代码的第一个参数:u-boot在RAM中的起始地址
mov r1, #0x0                      // 传递给C代码的第二个参数:Nand Flash的起始地址
mov r2, #UBOOT_LENGTH              // 传递给C代码的第三个参数:u-boot的长度大小
bl nand_read_ll                   // 此处调用C代码中读Nand的函数,现在还没有要自己编写实现
tst r0, #0x0                    // 如果函数nand_read_ll的返回值为0,表示执行成功
beq ok_nand_read

bad_nand_read:
loop2: b loop2                    // infinite loop

ok_nand_read:
//检查搬移后的数据,如果前4k完全相同,表示搬移成功
mov r0, #0                        // 将R0设为0
ldr r1, =CONFIG_SYS_TEXT_BASE    // 将R1设为虚拟地址起始处
mov r2, #0x400                    // 4 bytes * 1024 = 4k-bytes
go_next:
ldr r3, [r0], #4    // 取R0处地址的数据到R3中,然后R0自加4字节
ldr r4, [r1], #4    // 读取R1处地址的数据到R4中,然后R1自加4字节
teq r3, r4            // 比较R3和R4的数据是否相等,也就是检测Boot Internal SRAM和SDRAM中的数据是否相等
bne notmatch        // 不等则跳转到notmatch
subs r2, r2, #4    // 相等则R2自减4,当R2为0则跳转到relocations
//    beq board_init_f
beq relocations            /* 注意此句,直接跳转到relocate_code函数的调整部分,
因为我们不打算在board_init_f()函数中再回来了*/
bne go_next            // R2不为0则跳转回go_next继续检测

notmatch:
loop3: b loop3           //infinite loop

#endif //CONFIG_S3C2440_NAND_BOOT

/**************************END********************************/

/*——————————————————————————*/

/*
* 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

/**************************START***************************/
/* 增加标号,以便跳转到这里 added by guoyirong 2011.06.25 */
relocations:
ldr r6, =CONFIG_SYS_TEXT_BASE/*注意,R6下面被用到表示新的目标地址*/
/************************** END ***************************/

#ifndef CONFIG_PRELOADER
/*
* 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_PRELOADER
ldr    r0, _bss_start_ofs
ldr    r1, _bss_end_ofs
    ldr r3, _TEXT_BASE        /* add gy guoyirong 2011.06.25 */
mov    r4, r6                /* reloc addr */
//    add    r0, r0, r4            /* del by guoyirong 2011.06.25 */
//    add    r1, r1, r4            /* del by guoyirong 2011.06.25 */
add    r0, r0, r3            /* add by guoyirong 2011.06.25 */
add    r1, r1, r3            /* add by guoyirong 2011.06.25 */
    mov    r2, #0x00000000        /* clear                */

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

/* del by guoyirong 2011.06.25
bl coloured_LED_init
bl red_LED_on
*/
#endif

/* 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        /* 用绝对地址跳转到内存去了,不再回来了del by guoyirong 2011.06.25 */
ldr pc, _board_init_f    /* 增加此句,用绝对地址跳转到内存去了,不再回来add by guoyirong 2011.06.25*/

/**********************************************************/
/* 增加此句,我们用绝对地址跳转到内存去了,不再回来了add by guoyirong 2011.06.25*/
_board_init_f:
.word board_init_f
/**********************************************************/

/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
#ifdef CONFIG_NAND_SPL
ldr     r0, _nand_boot_ofs
mov    pc, r0

_nand_boot_ofs:
.word nand_boot
#else
ldr    r0, _board_init_r_ofs
adr    r1, _start
add    lr, r0, r1
add    lr, lr, r9
/* setup parameters for board_init_r */
mov    r0, r5        /* gd_t */
mov    r1, r6        /* dest_addr */
/* jump to it … */
mov    pc, lr

_board_init_r_ofs:
.word board_init_r – _start
#endif

_rel_dyn_start_ofs:
.word __rel_dyn_start – _start
_rel_dyn_end_ofs:
.word __rel_dyn_end – _start
_dynsym_start_ofs:
.word __dynsym_start – _start

// add by guoyirong 2011.06.25
.align 2
DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

2.7 修改arch\arm\cpu\arm920t\u-boot.lds

.text :
{
arch/arm/cpu/arm920t/start.o    (.text)
board/samsung/reille2440/libreille2440.o    (.text)
    *(.text)
}

2.8 修改修改\arch\arm\lib\board.c

a)修改一:board_init_f()函数

bd_t *bd;
init_fnc_t **init_fnc_ptr;
gd_t *id;
ulong addr, addr_sp;

/* Pointer is writable since we allocated a register for it */
gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
/* compiler optimization barrier needed for GCC >= 3.4 */
__asm__ __volatile__(“”: : :”memory”);

memset ((void*)gd, 0, sizeof (gd_t));

//    gd->mon_len = _bss_end_ofs;    // del by guoyirong 2011.06.25

    /* 增加此句以保证与配置的一致性add by guoyirong 2011.06.25
* 具体原因请查看代码中对此变量的使用即可明白,注意我们的 _TEXT_BASE=0x33f80000
*/
gd->mon_len = 0x700000;

b)修改二:board_init_f()函数

gd->relocaddr = addr;
gd->start_addr_sp = addr_sp;
gd->reloc_off = addr – _TEXT_BASE;
debug (“relocation Offset is: %08lx\n”, gd->reloc_off);
memcpy (id, (void *)gd, sizeof (gd_t));

    __asm__ __volatile__(“mov sp,%0″::”r”(addr_sp):”sp”); // added by guoyirong 2011.06.25

// add by guoyirong 2011.06.25
#ifdef CONFIG_S3C2440_NAND_BOOT
board_init_r(id, addr);
#else
relocate_code (addr_sp, id, addr);
/* NOTREACHED – relocate_code() does not return */
#endif

c)修改三:board_init_r()函数

debug (“Now running in RAM – U-Boot at: %08lx\n”, dest_addr);

// u-boot启动时的输出版本信息 added by guoyirong 2011.06.25
display_banner();
display_dram_config();

2.9 修改board\samsung\reille2440\config.mk

# tftp debug added by guoyirong 2011.06.11
#CONFIG_SYS_TEXT_BASE = 0x33000000

CONFIG_SYS_TEXT_BASE = 0x33F80000

至此,该修改该移植的部分都完成了,重新编译,然后下载到NAND FLASH

3. 调试问题

严格按照上述的修改或者按照A.1.1网址进行修改,一般不会有问题

我在调试过程中,由于在nand_read_ll()函数中加了一句打印信息,导致不能正常启动,实际上在nand_read_ll()函数中不能加打印信息,弄得我用AXD去单步调试。

启动信息如下:

U-Boot 2011.03 (Jun 26 2011 – 02:40:58)

DRAM:  64 MiB
NAND:  NAND_ECC_NONE selected by board driver. This is not recommended !!
64 MiB
*** Warning – bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   CS8900-0
[reille2440]#

A. 参考资料

A.1 u-boot的NAND FLASH部分移植:

A.1.1 http://www.linuxidc.com/Linux/2011-02/32772p4.htm

A.1.2 http://womeikongya.blog.163.com/blog/static/58599220201121352920156/

A.1.3 http://blog.csdn.net/csuwzc/archive/2011/05/30/6454256.aspx

A.2 u-boot源码中start.S汇编指令含义的详细解释

http://os.it168.com/a2009/0629/994/000000994561.shtml

A.3 使用JLink间接烧写S3C2410、S3C2440开发板Nor、Nand Flash的方法

http://www.ourdev.cn/bbs/bbs_content_all.jsp?bbs_sn=3228953

A.4 U-Boot调试环境搭建请教~~如何实现u-boot和内核的源码级调试

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3521744&bbs_page_no=1&bbs_id=1032

A.5 如何调试uboot中NAND FLASH 启动部分

http://blog.csdn.net/qiaoliang328/archive/2011/03/07/6229389.aspx

» 文章出处: reille博客—http://velep.com , 如果没有特别声明,文章均为reille博客原创作品
» 郑重声明: 原创作品未经允许不得转载,如需转载请联系reille#qq.com(#换成@)
分享到:

  One Response to “移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###7.NAND FLASH部分移植和支持NAND FLASH启动和读写”

  1. This is just the perfect answer for all forum memrebs

 Leave a Reply

(必须)

(我会替您保密的)(必须)

*

   
© 2012 velep.com | reille blog | 管理| 粤ICP备12094833号-2| 谷歌地图| 百度地图| Suffusion theme|Sayontan Sinha

无觅相关文章插件,快速提升流量