三星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
{
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;
-----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
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
----------------------------------------------------------------------------------------------------
/* 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是上面参数传递进来的。
--------------------------------------------------------------------------------------------------------
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)
---------------------------------------------------------------------------
/* 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;
}