免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1612 | 回复: 0
打印 上一主题 下一主题

[BootLoader] 请教一个关于 u-boot移植到TQ2440时nand flash出现的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-12-02 12:16 |只看该作者 |倒序浏览
本帖最后由 carsion 于 2013-12-02 12:15 编辑

环境:RHEL6.3
编译环境:arm-linux-gcc-4.3.3
开发板:TQ2440
Nandflash型号:K9F2G08U0B

#####################################################################################################
移植过程是这样的:
我在移植u-boot.2009.08到TQ2440的时候,出现了一个很奇怪的问题,就是在移植nand flash 的时候,不能从nand flash启动。请看我nand flash部分的具体移植过程:
#####################################################################################################
支持nandflash:
修改drivers/mtd/nand/s3c2410_nand.c。修改如下:
##################################################
#include <common.h>

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

#include <nand.h>
#include <s3c2410.h>
#include <asm/io.h>
#define __REGb(x)        (*(volatile unsigned char *)(x))
#define __REGi(x)        (*(volatile unsigned int *)(x))
#define        NF_BASE                0x4e000000

# if defined(CONFIG_S3C2440)&& ! defined(CONFIG_S3C2410)
#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 NFMECCD0        __REGb(NF_BASE + 0x14)
#define NFMECCD1        __REGb(NF_BASE + 0x18)
#define NFSECCD                __REGb(NF_BASE + 0x1c)
#define NFSTAT                __REGb(NF_BASE + 0x20)
#define NFESTAT0        __REGb(NF_BASE + 0x24)
#define NFESTAT1        __REGb(NF_BASE + 0x28)
#define NFMECC0                __REGb(NF_BASE + 0x2c)
#define NFMECC1                __REGb(NF_BASE + 0x30)
#define NFSECC                __REGb(NF_BASE + 0x34)
#define NFSBLK                __REGb(NF_BASE + 0x38)
#define NFEBLK                __REGb(NF_BASE + 0x3c)
#define NFECC0                __REGb(NF_BASE + 0x2c)
#define NFECC1                __REGb(NF_BASE + 0x2d)
#define NFECC2                __REGb(NF_BASE + 0x2e)

#define S3C2410_NFCONT_EN          (1<<0)
#define S3C2410_NFCONT_INITECC     (1<<4)
#define S3C2410_NFCONT_nFCE        (1<<1)
#define S3C2410_NFCONT_MAINECCLOCK (1<<5)
#define S3C2410_NFCONF_TACLS(x)    ((x)<<12)
#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<8)
#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<4)

#define S3C2410_ADDR_NALE 0x08
#define S3C2410_ADDR_NCLE 0x0c
#endif
# if defined (CONFIG_S3C2410)
#define        NFCONF                __REGi(NF_BASE + 0x0)
#define        NFCMD                __REGb(NF_BASE + 0x4)
#define        NFADDR                __REGb(NF_BASE + 0x8)
#define        NFDATA                __REGb(NF_BASE + 0xc)
#define        NFSTAT                __REGb(NF_BASE + 0x10)
#define NFECC0                __REGb(NF_BASE + 0x14)
#define NFECC1                __REGb(NF_BASE + 0x15)
#define NFECC2                __REGb(NF_BASE + 0x16)

#define S3C2410_NFCONF_EN          (1<<15)
#define S3C2410_NFCONF_512BYTE     (1<<14)
#define S3C2410_NFCONF_4STEP       (1<<13)
#define S3C2410_NFCONF_INITECC     (1<<12)
#define S3C2410_NFCONF_nFCE        (1<<11)
#define S3C2410_NFCONF_TACLS(x)    ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x)   ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x)   ((x)<<0)

#define S3C2410_ADDR_NALE 4
#define S3C2410_ADDR_NCLE 8
#endif
ulong IO_ADDR_W = NF_BASE;
static void s3c2410_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) {
               
                if (!(ctrl & NAND_CLE))
                        IO_ADDR_W |= S3C2410_ADDR_NCLE;
                if (!(ctrl & NAND_ALE))
                        IO_ADDR_W |= S3C2410_ADDR_NALE;

//                chip->IO_ADDR_W = (void *)IO_ADDR_W;
                # if defined(CONFIG_S3C2410)
                if (ctrl & NAND_NCE)
                        NFCONF &= ~S3C2410_NFCONF_nFCE;
                else
                        NFCONF |= S3C2410_NFCONF_nFCE;
                # endif
                # if defined(CONFIG_S3C2440) && ! defined(CONFIG_S3C2410)
                if (ctrl & NAND_NCE)
                        NFCONT &= ~S3C2410_NFCONT_nFCE;
                else
                        NFCONT |= S3C2410_NFCONT_nFCE
                #endif
        }

        if (cmd != NAND_CMD_NONE)
//                writeb(cmd, chip->IO_ADDR_W);
                writeb(cmd, (void *)IO_ADDR_W);
}

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

#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
        DEBUGN("s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
        # if defined(CONFIG_S3C2410)
        NFCONF |= S3C2410_NFCONF_INITECC;
        #endif
        # if defined(CONFIG_S3C2440)&& ! defined(CONFIG_S3C2410)
        NFCONT |= S3C2410_NFCONT_INITECC;
        #endif
}

static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
                                      u_char *ecc_code)
{
        ecc_code[0] = NFECC0;
        ecc_code[1] = NFECC1;
        ecc_code[2] = NFECC2;
        DEBUGN("s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
                mtd , ecc_code[0], ecc_code[1], ecc_code[2]);

        return 0;
}

static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
                                     u_char *read_ecc, u_char *calc_ecc)
{
        if (read_ecc[0] == calc_ecc[0] &&
            read_ecc[1] == calc_ecc[1] &&
            read_ecc[2] == calc_ecc[2])
                return 0;

        printf("s3c2410_nand_correct_data: not implemented\n");
        return -1;
}
#endif

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

        DEBUGN("board_nand_init()\n");

        clk_power->CLKCON |= (1 << 4);

        /* initialize hardware */
        # if defined(CONFIG_S3C2410)
        twrph0 = 3; twrph1 = 0; tacls = 0;

        cfg = S3C2410_NFCONF_EN;
        cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
        cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
        cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);

        NFCONF = cfg;

        /* initialize nand_chip data structure */
        nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;
        #endif
        # if defined(CONFIG_S3C2440)&& ! defined(CONFIG_S3C2410)
        twrph0 = 4; twrph1 = 2; tacls = 0;

        cfg = 0;
        cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
        cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
        cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);

        NFCONF = cfg;
        NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);
        /* initialize nand_chip data structure */
        nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;
        #endif
        /* read_buf and write_buf are default */
        /* read_byte and write_byte are default */

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

        nand->dev_ready = s3c2410_dev_ready;

#ifdef CONFIG_S3C2410_NAND_HWECC
        nand->ecc.hwctl = s3c2410_nand_enable_hwecc;
        nand->ecc.calculate = s3c2410_nand_calculate_ecc;
        nand->ecc.correct = s3c2410_nand_correct_data;
        nand->ecc.mode = NAND_ECC_HW3_512;
#else
        nand->ecc.mode = NAND_ECC_SOFT;
#endif

#ifdef CONFIG_S3C2410_NAND_BBT
        nand->options = NAND_USE_FLASH_BBT;
#else
        nand->options = 0;
#endif

        DEBUGN("end of nand_init\n");

        return 0;
}
#############################################################
修改配置文件include/configs/smdk2440.h,增加支持nand的相关宏:
#############################################################
#define CONFIG_NAND_S3C2410    1
/* Comman line configuration. */
#define CONFIG_CMD_NAND
/* NAND flash settings */
#if defined(CONFIG_CMD_NAND)
#define CONFIG_SYS_NAND_BASE        0X4E000000
#define CONFIG_SYS_MAX_NAND_DEVICE        1
#define CONFIG_MTD_NAND_VERIFY_WRITE        1
#endif

########################################################
在dirvers/mtd/nand目录下makefile中,添加以下内容:
########################################################
COBJS-y +=s3c2410_nand.o

########################################################
将生成的u-boot.bin下载到Nor flash 中,可以看到如下信息:
#######################################################
U-Boot 2009.08 (12鏈02 2013 - 10:54:15)

DRAM:  64 MB
Flash:  2 MB
NAND:  256 MiB
*** Warning - bad CRC or NAND, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   dm9000
SMDK2440 #

#################################################
这里是正常的,能检测到了nand flash的信息。下面是支持从nandflash中启动的配置:
#################################################
在include/configs/smdk2440.h中添加代码如下:
#################################################
/* Nand flash reister and envionment variables */
#define CONFIG_S3C2440_NAND_BOOT        1
#define NAND_CTL_BASE        0X4E000000
#define bINT_CTL(Nb)        __REG(INT_CTL_BASE+(Nb))
#define UBOOT_RAM_BASE        0x33f80000
#define STACK_BASE        0x33F00000
#define STACK_SIZE        0x80000

################################################
修改cpu/arm920t/start.S如下:
################################################
屏蔽掉从Nor flash启动部分
################################################
#if 0
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:                                /* relocate U-Boot to RAM            */
        adr        r0, _start                /* r0 <- current position of code   */
        ldr        r1, _TEXT_BASE                /* test if we run from flash or RAM */
        cmp     r0, r1                  /* don't reloc during debug         */
        beq     stack_setup

        ldr        r2, _armboot_start
        ldr        r3, _bss_start
        sub        r2, r3, r2                /* r2 <- size of armboot            */
        add        r2, r0, r2                /* r2 <- source end address         */

copy_loop:
        ldmia        r0!, {r3-r10}                /* copy from source address [r0]    */
        stmia        r1!, {r3-r10}                /* copy to   target address [r1]    */
        cmp        r0, r2                        /* until source end addreee [r2]    */
        ble        copy_loop
#endif        /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif


################################################
添加从nand flash 启动代码
################################################
#ifdef CONFIG_S3C2440_NAND_BOOT
#define oNFCONF        0x00
#define oNFCONT        0x04
#define oNFCMD        0x08
#define oNFSTAT        0x20
#define LENGTH_UBOOT        0x60000
        mov        r1, # NAND_CTL_BASE
        ldr        r2, = ((7<<12)|(7<<8)|(7<<4)|(0<<0))
        str        r2, [r1, #oNFCONF]
        ldr        r2, [r1, #oNFCONF]
       
        ldr        r2, = ((1<<4)|(0<<1)|(1<<0))
        str        r2, [r1, #oNFCONT]
        ldr        r2, [r1, #oNFCONT]
       
        ldr        r2, =(0x6)
        str        r2, [r1, #oNFSTAT]
        ldr        r2, [r1, #oNFSTAT]
       
        mov        r2, #0xff
        strb        r2, [r1, #oNFCMD]
        mov        r3, #0
nand1:
        add        r3, r3, #0x01
        cmp        r3, #0xa
        blt        nand1

nand2:
        ldr        r2, [r1, #oNFSTAT]
        tst        r2, #0x2
        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
        mov        fp, #0
       
        /* copy U-BOOT to RAM */
        ldr        r0, =TEXT_BASE
        mov        r1, #0x0
        mov        r2, # LENGTH_UBOOT
        bl        nand_read_ll
        tst        r0, #0x0
        beq        ok_nand_read

bad_nand_read:
        loop2:        b        loop2
ok_nand_read:
        mov        r0, #0
        ldr        r1, =TEXT_BASE
        mov        r2, #0x400
go_next:
        ldr        r3, [r0], #4
        ldr        r4, [r1], #4
        teq        r3, r4
        bne        notmatch
        subs        r2, r2, #4
        beq        stack_setup
        bne        go_next
notmatch:
        loop3:        b        loop3
#endif        /* CONFIG_S3C2440_NAND_BOOT */

#####################################################
添加DW_STACK_START的定义:
#####################################################
.align        2
DW_STACK_START:        .word STACK_BASE + STACK_SIZE - 4

#####################################################
在board/samsung/smdk2440下新建一个nand_read.c文件,代码如下:
#####################################################
#include <common.h>
#include <linux/mtd/nand.h>
#define __REGb(x)        (*(volatile unsigned char *)(x))
#define __REGw(x)        (*(volatile unsigned short *)(x))
#define __REGi(x)        (*(volatile unsigned int *)(x))
#define NF_BASE                0x4E000000
# if defined(CONFIG_S3C2410) && !defined(CONFIG_S3C2440)
#define NFCONF        __REGi(NF_BASE + 0x0)
#define NFCMD        __REGb(NF_BASE + 0x4)
#define NFADDR        __REGb(NF_BASE + 0x8)
#define NFDATA        __REGb(NF_BASE + 0xc)
#define NFSTAT        __REGb(NF_BASE + 0x10)
#define NFSTAT_BUSY        1
#define nand_select()        (NFCONF & =~(0x800))
#define nand_deselect()        (NFCONF | = (0x800))
#define nand_clear_RnB()        do {} while(0)

#elif defined(CONFIG_S3C2440)||defined(CONFIG_S3C2442)
#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 NFDATA16 __REGw(NF_BASE + 0x10)
#define NFSTAT __REGb(NF_BASE + 0x20)
#define NFSTAT_BUSY         1
#define nand_select()    (NFCONT &=~(1<<1))
#define nand_deselect()  (NFCONT |= (1<<1))
#define nand_clear_RnB() (NFSTAT |= (1<<2))
#endif

static inline void nand_wait(void)
{
        int i;
        while (! (NFSTAT & NFSTAT_BUSY))
                for (i=0; i<10; i++);
}

struct boot_nand_t
{
        int page_size;
        int block_size;
        int bad_block_offset;
        //unsigned long size;
};

static int is_bad_block(struct boot_nand_t * nand,unsigned long i)
{
        unsigned char data;
        unsigned long page_num;
        nand_clear_RnB();
        if (nand->page_size==512){
                NFCMD = NAND_CMD_READOOB;
                NFADDR = nand->bad_block_offset & 0xf;
                NFADDR = (i>>9) & 0xff;
                NFADDR = (i>>17) & 0xff;
                NFADDR = (i>>25) & 0xff;
        }else if (nand->page_size ==2048){
                page_num= i>>11;
                NFCMD = NAND_CMD_READ0;
                NFADDR = (nand->bad_block_offset>>8) & 0xff;
                NFADDR = page_num  & 0xff;
                NFADDR = (page_num>>8) & 0xff;
                NFADDR = (page_num>>16) & 0xff;
        }else{
                return -1;
        }
        nand_wait();
        data = (NFDATA & 0xff);
        if(data != 0xff)
                return 1;
        return 0;
}
static int nand_read_page_ll(struct boot_nand_t * nand,unsigned char * buf, unsigned long addr)
{
        unsigned short *ptr16 = (unsigned short *)buf;
        unsigned int i,page_num;
        nand_clear_RnB();
        NFCMD = NAND_CMD_READ0;
        if (nand->page_size == 512){
                NFADDR = addr & 0xff;
                NFADDR = (addr >> 9) & 0xff;
                NFADDR = (addr >> 17) & 0xff;
                NFADDR = (addr >> 25) & 0xff;
        }else if(nand->page_size == 2048){
                page_num = addr >> 11;
                NFADDR = 0;
                NFADDR = 0;
                NFADDR = page_num & 0xff;
                NFADDR = (addr >> 8) & 0xff;
                NFADDR = (addr >> 16) & 0xff;
                NFCMD = NAND_CMD_READSTART;
        }else{
                return -1;
        }
        nand_wait();
        # if defined(CONFIG_S3C2410)&& !defined(CONFIG_S3C2440)
                for (i=0 ;i<nand->page_size;i++)
                *buf = (NFDATA & 0xff);
                buf++;
        # elif defined(CONFIG_S3C2440)|| defined(CONFIG_S3C2442)
                for (i=0; i< nand->page_size; i++){
                *ptr16 = NFDATA16;
                ptr16++;
        }
        #endif
                return nand->page_size;
;
}

static unsigned short nand_read_id()
{
        unsigned short res = 0;
        NFCMD = NAND_CMD_READID;
        NFADDR = 0;
        res = NFDATA;
        res = (res <<8) | NFDATA;
        return res;
}

int nand_read_ll(unsigned char *buf,unsigned long start_addr,int size)
{
        int i,j;
        unsigned short nand_id;
        struct boot_nand_t nand;
        nand_select();
        nand_clear_RnB();
        for (i = 0; i < 10; i++)
        ;
        nand_id = nand_read_id();
        if(0){
        unsigned short *nid = (unsigned short *)0x31fffff0;
        *nid = nand_id;
        }
        if ((nand_id == 0xec76) || (nand_id==0xad76)){
        nand.page_size = 512;
        nand.block_size =6 * 1024;
        nand.bad_block_offset =5;
        }else if(nand_id == 0xecf1 ||
                nand_id == 0xecda ||
                nand_id == 0xecd3){
                nand.page_size == 2048;
                nand.block_size == 128 * 1024;
                nand.bad_block_offset == nand.page_size;
        }else{
                return -1;
        }
        if ((start_addr &(nand.block_size -1)) || (size & (nand.block_size -1)))
                return -1;
        for(i = start_addr; i < (start_addr + size);){
        #ifdef CONFIG_S3C2410_NAND_SKIP_BAD
        if(i & (nand.block_size - 1)==0){
        if(is_bad_block(&nand,i)||is_bad_block(&nand, i + nand.page_size)){
                i += nand.block_size;
                size += nand.block_size;
                continue;
        }
        }
        #endif
        j = nand_read_page_ll(&nand,buf,i);
        i += j;
        buf += j;
        }
        nand_deselect();
        return 0 ;
}

###################################################
修改在board/samsung/smdk2440目录下的Makefile:
###################################################
COBJS        := smdk2440.o flash.o nand_read.o

###################################################
修改cpu/arm920t/u-boot.lds文件,修改如下:
###################################################
.text :
        {
                cpu/arm920t/start.o        (.text)
                board/samsung/smdk2440/lowlevel_init.o        (.text)
                board/samsung/smdk2440/nand_read.o        (.text)
                *(.text)
        }

###################################################
将include/configs/smdk2440.h中的Nor flash环境变量屏蔽并且添加新代码如下:
###################################################
/* Command line configuration */
#define CONFIG_CMD_NAND

#if defined(CONFIG_CMD_NAND)
#define CONFIG_ENV_IS_IN_NAND        1
#define CONFIG_ENV_OFFSET         0x60000
#define CONFIG_ENV_SIZE                0x20000
#else
#define CONFIG_ENV_IS_IN_FLASH 1
#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
#endif

###################################################
然后编译,将生成的u-boot.bin下载到nand flash中。问题是,从nand flash中启动却终端没有任何消息出现。这个是怎么回事的啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP