【转】u-boot-2010.12移植到2440(四,支持nand flash启动)

2024-01-07 02:08

本文主要是介绍【转】u-boot-2010.12移植到2440(四,支持nand flash启动),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

u-boot-2010.12移植到2440(四,支持nand flash启动)

转自

http://my.chinaunix.net/space.php?uid=24319701&do=blog&id=136249

 

在这篇中,我们将移植nand flash部分,支持NAND启动及NAND FLASH的读写访问。

首先,我们在u-boot-2010.12/include/configs/smdk2440.h中注销如下定义。

//#define  CONFIG_ENV_IS_IN_FLASH    1

//#define CONFIG_ENV_SIZE           0x10000  /* Total Size of Environment Sector */

增加如下定义:

/*以下为NAND启动及驱动相关*/

#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

#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  //注意:我们这里是64MNand 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 */

arch/arm/cpu/arm920t/start.S文件中增加如下代码:

 

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl    cpu_init_crit

#endif

 

//下面添加2440u-bootNand Flash启动

 

#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_LOAD_ADDR//传递给C代码的第一个参数:u-bootRAM中的起始地址 //暂时为这个值

    mov r1, #0x0      //传递给C代码的第二个参数:Nand Flash的起始地址

    mov r2, #UBOOT_LENGTH  //传递给C代码的第三个参数:u-boot的长度大小

    bl nand_read_ll   //此处调用C代码中读Nand的函数,现在还没有要自己编写实现

    tst r0, #0x0

    beq ok_nand_read

 

bad_nand_read:

    loop2: b loop2    //infinite loop

 

ok_nand_read:

    //检查搬移后的数据,如果前4k完全相同,表示搬移成功

    mov r0, #0

    ldr r1, =CONFIG_SYS_LOAD_ADDR//暂时为这个值

    mov r2, #0x400           //4 bytes * 1024 = 4K-bytes

go_next:

    ldr r3, [r0], #4

    ldr r4, [r1], #4

    teq r3, r4

    bne notmatch

    subs r2, r2, #4

    beq board_init_f

    bne go_next

 

notmatch:

    loop3: b loop3           //infinite loop

#endif //CONFIG_S3C2440_NAND_BOOT

 

.align 2   /*add by bsc 2010-2-6 13:11*/

DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

 

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

#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)

 

/* low level nand read function */

int nand_read_ll(unsigned char *buf, unsigned long start_addr, int size)

{

    int i, j;

 

    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;

}

 

修改board/samsung/smdk2440/ makefile

COBJS    := smdk2440.o flash.o nand_read.o

 

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

 

#include <common.h>

 

#if 0

#define DEBUGN    printf

#else

#define DEBUGN(x, args ...) {}

#endif

 

#include <nand.h>

#include <asm/arch/s3c24x0_cpu.h>

#include <asm/io.h>

 

 

#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;

}

然后,在drivers/mtd/nand/Makefile文件中添加s3c2440_nand.c的编译项,如下:

COBJS-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o

u-boot-2010.12/include/configs/smdk2440.h中增加宏定义:

# define  CONFIG_NAND_S3C2440

 

重新编译,将u-boot.bin下载到内存运行,可以运行,FLASH也正常的读写。注意,此时我们的uboot还不支持从NAND FLASH启动,前面的步骤只是为了调试方便,我们将可以看到在内存中运行的u-boot成功的将NAND FLASH中的数据拷贝到了内存中CONFIG_SYS_LOAD_ADDR的位置。接下来我们让其支持在NAND FLASH中的启动。

 

将上面的ldr r0, =CONFIG_SYS_LOAD_ADDRldr r1, =CONFIG_SYS_LOAD_ADDR替换为ldr r0, =CONFIG_SYS_TEXT_BASEldr r1, =CONFIG_SYS_TEXT_BASE

 

通过查看u-boot.map可以看到,我们的nand_read_ll()函数被连接在4K之后的位置,所以根本无法再启动时实现数据到内存的拷贝。因此我们根据网友的说法修改arch/arm/cpu/arm920t/u-boot.lds如下:

.text :

       {

              arch/arm/cpu/arm920t/start.o (.text)

              board/samsung/smdk2440/lowlevel_init.o    (.text)

              board/samsung/smdk2440/nand_read.o (.text)

              *(.text)

       }

编译发现,编译通不过,出现重定义的错误。这可能是新版本的编译和连接规则有变化导致的,具体原因还不清楚,因此我们采用其他的办法。

board/samsung/smdk2440/libsmdk2440.o: In function `nand_read_ll':

/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/nand_read.c:30: multiple definition of `nand_read_ll'

board/samsung/smdk2440/nand_read.o:/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/nand_read.c:30: first defined here

board/samsung/smdk2440/libsmdk2440.o: In function `lowlevel_init':

/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/lowlevel_init.S:137: multiple definition of `lowlevel_init'

board/samsung/smdk2440/lowlevel_init.o:/home/bsc/samba/u-boot-2010.12/board/samsung/smdk2440/lowlevel_init.S:137: first defined here

make: *** [u-boot] 错误 1

这可能是新版本的编译和连接规则有变化导致的,具体原因还不清楚,因此我们采用其他的办法。修改arch/arm/cpu/arm920t/u-boot.lds如下:

.text :

       {

              arch/arm/cpu/arm920t/start.o (.text)

              board/samsung/smdk2440/ libsmdk2440.o    (.text)

arch/arm/lib/libarm.o     (.text)

              *(.text)

       }

编译之后发现,board_init_f函数还是超过了4K,我们只能对前面的代码进行瘦身了,我们的目标板没有NOR FLASH,所以我们取消NOR FLASH的支持。

u-boot-2010.12/include/configs/smdk2440.h中增加宏定义:

/*去掉NOR FLASH支持*/

#define CONFIG_SYS_NO_FLASH

#define CONFIG_CMD_FLASH  /* flinfo, erase, protect   */

#define CONFIG_CMD_IMLS            /* List all found images  */

修改board/samsung/smdk2440/ makefile,取消对flash的编译。

COBJS    := smdk2440.o nand_read.o

编译后下载到内存,杯具又发生了,跑进board_init_r()函数的时候死机了。至此相当的郁闷了,没办法再修改arch/arm/cpu/arm920t/u-boot.lds如下:

.text :

       {

              arch/arm/cpu/arm920t/start.o (.text)

              board/samsung/smdk2440/ libsmdk2440.o    (.text)

              *(.text)

       }

在编译,下载到内存运行,可以运行。但是还是相当杯具的,通过查看u-boot.map可以看到arch/arm/lib/libarm.o被连接到了4K之外,4K之内没有这个程序我们是不可能实现NAND启动的。但是天无绝人之路,我们可以让U-boot提前进入内存运行。思路是,我们提前将代码拷贝到内存中,提前跳转到内存中运行不再回来。修改arch/arm/cpu/arm920t/start.S文件如下:

 

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

       bl    cpu_init_crit

#endif

 

//下面添加2440u-bootNand Flash启动

#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-bootRAM中的起始地址

    mov r1, #0x0      //传递给C代码的第二个参数:Nand Flash的起始地址

    mov r2, #UBOOT_LENGTH  //传递给C代码的第三个参数:u-boot的长度大小

    bl nand_read_ll   //此处调用C代码中读Nand的函数,现在还没有要自己编写实现

    tst r0, #0x0

    beq ok_nand_read

 

bad_nand_read:

    loop2: b loop2    //infinite loop

 

ok_nand_read:

    //检查搬移后的数据,如果前4k完全相同,表示搬移成功

    mov r0, #0

    ldr r1, =CONFIG_SYS_TEXT_BASE

    mov r2, #0x400           //4 bytes * 1024 = 4K-bytes

go_next:

    ldr r3, [r0], #4

    ldr r4, [r1], #4

    teq r3, r4

    bne notmatch

    subs r2, r2, #4

    beq relocations       /*注意此句,直接跳转到relocate_code 函数的调整部分,因为我们不打算在board_init_f()函数中再回来了*/

    bne go_next

 

notmatch:

    loop3: b loop3           //infinite loop

 

#endif //CONFIG_S3C2440_NAND_BOOT

 

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

 

/*

 * 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   r2, _TEXT_BASE

       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

      

relocations:     /*增加标号,以便跳转到这里*/

       ldr r6, =CONFIG_SYS_TEXT_BASE /*注意,R6下面被用到表示新的目标地址*/

 

#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         /* Text base */

       mov r4, r6             /* reloc addr */

       add  r0, r0, r3     /*注意此句修改*/

       add  r1, r1, r3    /*注意此句修改*/

       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

*//* by bsc 2011/2/23 13:44:29*/

#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*/ /*删除此句,我们用绝对地址跳转到内存去了,不再回来了*/

       ldr pc, _board_init_f     /*增加此句,我们用绝对地址跳转到内存去了,不再回来了*/

      

_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

 

.align 2   /*add by bsc 2010-2-6 13:11*/

DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

修改完arch/arm/cpu/arm920t/start.S文件之后,我们会发现,有一句非常重要的代码被我们删除再也执行不到了,那就是设置堆栈指针:mov sp, r4

因此我们需要在board_init_f()函数中设置。

修改/arch/arm/lib/board.c代码如下:

 

首先将board_init_f()与board_init_r()函数的顺序调换下,因为我们要在board_init_f()中调用board_init_r()。

 

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

 

函数最后:

__asm__ __volatile__("mov sp,%0"::"r"(addr_sp):"sp");/*add by bsc 2011/2/24 15:17:48*/

             

#ifdef CONFIG_S3C2440_NAND_BOOT   /*add by bsc 2011/2/24 15:18:04*/

       board_init_r(id, addr);

#else

       relocate_code (addr_sp, id, addr);

       /* NOTREACHED - relocate_code() does not return */

#endif

       /*relocate_code (addr_sp, id, addr);*//*add by bsc 2011/2/24 15:18:28*/

       /* NOTREACHED - relocate_code() does not return */

 

然后修改board/samsung/smdk2440/config.mk如下:

CONFIG_SYS_TEXT_BASE = 0x33f80000

 

然后修改include/configs/smdk2440.h如下:

增加宏定义:

#define UBOOT_LENGTH  0x40000 /*uboot大小256K*/

删除宏定义:

#define CONFIG_SKIP_LOWLEVEL_INIT /*在内存中调试时增加此宏定义 by bsc */

 

然后编译,烧写到NAND FLASH中,重启之后你会发现,终于可以运行啦。

测试中发现,go命令好像有问题,直接死机了,其他一切正常。

如果你还想看到u-boot启动时的输出版本信息等,修改/arch/arm/lib/board.c代码如下:board_init_r函数中修改

   board_init();    /* Setup chipselects */

#ifdef CONFIG_SERIAL_MULTI
    serial_initialize();
#endif

    debug ("Now running in RAM - U-Boot at: %08lx/n", dest_addr);
    display_banner();
    display_dram_config();

#ifdef CONFIG_LOGBUFFER
    logbuff_init_ptrs ();
#endif

好了,现在uboot已经可以支持NAND FLASH启动和读写了。

我们还可以在common/env_common.c文件中的default_environment[]数组中增加

#if 1    /*add by bsc */

   "uu="   "t 0x30000000 u-boot.bin;nand erase 0x0 0x30000;nand write 0x30000000 0x0 0x30000" "/0"

   "kkn=" "t 0x30008000 zImage_nfs;bootm" "/0"

   "kk="   "t 0x30000000 zImage;nand erase 0x50000 0x300000;nand write 0x30000000 0x50000 0x200000" "/0"

   "yy="   "t 0x30000000 rootyaffs2.img;nand erase 0x250000 0x3db0000;nand write.yaffs2 0x30000000 0x250000 $(filesize)" "/0"

   "firstboot=" "set bootcmd $(normalboot);save;nand erase 0x50000 0x3f00000;run kk;run yy" "/0"

   "normalboot="   "nand read 0x30008000 0x50000 0x200000;bootm 0x30008000" "/0"

#endif

以使用 run uu;run yy这样的命令来实现一些操作。

这篇关于【转】u-boot-2010.12移植到2440(四,支持nand flash启动)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/578377

相关文章

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

SpringBoot项目是如何启动

启动步骤 概念 运行main方法,初始化SpringApplication 从spring.factories读取listener ApplicationContentInitializer运行run方法读取环境变量,配置信息创建SpringApplication上下文预初始化上下文,将启动类作为配置类进行读取调用 refresh 加载 IOC容器,加载所有的自动配置类,创建容器在这个过程

什么是 Flash Attention

Flash Attention 是 由 Tri Dao 和 Dan Fu 等人在2022年的论文 FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 中 提出的, 论文可以从 https://arxiv.org/abs/2205.14135 页面下载,点击 View PDF 就可以下载。 下面我

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断