三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)

时间:2021-07-13 04:26:05


三星uboot1.1.6源码分析——start.s(1)的地址链接

三星uboot1.1.6源码分析——start.s(2)--从NAND复制uboot源码到RAM(1)的链接地址



接着上一篇的内容说。上一篇说到了这个函数nandll_read_blocks,这一篇,进入这个函数的源码,看看它的作用。

--------------------------------------------------------------------------------------------------------------

/*
 * Read data from NAND.
 */

传入的参数是 nandll_read_blocks(CFG_PHY_UBOOT_BASE,0x3c000,large_block);

其中:  CFG_PHY_UBOOT_BASE为0x57e00000 

0x3c000为读取的字节数
large_block 根据上一篇的分析,为2
--------------------------------------------------------------------
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
{
        uchar *buf = (uchar *)dst_addr; 我们要把源码复制的内存地址
        int i;

---------------------------------------------------------------------------------------------
uint page_shift = 9;

 
if (large_block==1)
page_shift = 11;


        /* Read pages */  刚才说了,我们的large_block为2
if(large_block==2)
page_shift = 12;

-----------------------------------------------------------------------------------------------

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)
 ----------------------------------------------------------------------------------------------
if(large_block == 2)
{
/* Read pages */
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1))) {
       nandll_read_page(buf, i, large_block);
}      ------------- 这个循环,读出Block0,page0、1、2、3的数据




/* Read pages */
for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {
       nandll_read_page(buf, i, large_block);
}   ------------这个循环从page4开始读出,知道读出0x3c000字节的数据
}

想要看懂这部分代码,需要先看下面这 nandll_read_page源码的分析,这个源码的作用,就是根据我们给定的地址,从具体的page中读出数据。但是这里为什么要用两个循环呢?不太懂。

-----------------------------------------------------------------------------------------------

现在有遇到了一个函数, nandll_read_page,同样它的源码也在同一个文件中,如下所示:

/*
 * address format
 *              17 16         9 8            0
 * --------------------------------------------
 * | block(12bit) | page(5bit) | offset(9bit) |
 * --------------------------------------------
 */

static int nandll_read_page (uchar *buf, ulong addr, int large_block)
{
        int i;
int page_size = 512;


if (large_block==1)
  page_size = 2048;
if (large_block==2)     这个上面说过了
page_size = 4096;


        NAND_ENABLE_CE(); 这个上面也说过了


        NFCMD_REG = NAND_CMD_READ0;

-----------------------------------------------------------------------

#define NAND_CMD_READ00

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)

----------------------------------------------------------------------------------------------------

        /* Write Address */
        NFADDR_REG = 0;


if (large_block)
       NFADDR_REG = 0;


NFADDR_REG = (addr) & 0xff;
NFADDR_REG = (addr >> 8) & 0xff;
NFADDR_REG = (addr >> 16) & 0xff;         ------------看下面的图:

------------------------------------------------------------------------------------------------

这里涉及到地址转化,和地址发送的顺序问题,下面这个图是地址发送的顺序,那么地址怎样转化的呢?

这里的addr是上面参数传递进来的。

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)


--------------------------------------------------------------------------------------------------------


if (large_block)
NFCMD_REG = NAND_CMD_READSTART;

---------------------------------------------------------------------------

其中有:

#define NAND_CMD_READSTART0x30

看上面那个图,就应该知道为什么了。

---------------------------------------------------------------------------


        NF_TRANSRnB();----------------检测忙标志,有如下定义:

-----------------------------------------------------

#define NF_TRANSRnB()do { while(!(NFSTAT_REG & (1 << 0))); } while(0)

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)

三星uboot1.1.6源码分析——start.s(3)---从NAND复制uboot到外部RAM(2)

---------------------------------------------------------------------------


/* for compatibility(2460). u32 cannot be used. by scsuh */  ------把数据读到buf中。
for(i=0; i < page_size; i++) {
                *buf++ = NFDATA8_REG;
        }


        NAND_DISABLE_CE();  禁止NAND
        return 0;
}

----------------------------------------------------------------------------------------------------
else    这个我们用不到,分析方法和上面一样  这里就只用了一个循环。
{
for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {
       nandll_read_page(buf, i, large_block);
}
}


        return 0;
}