起因
在学习OK6410附赠的源代码uboot1.1.6-V5.50-2014-09-19中,发现从nandflash拷贝代码到ram时,以下代码不明白(看中文注释):
/*
* uboot1.1.6\cpu\s3c64xx\nand_cp.c
* Read data from NAND.
*/
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;
if(large_block==2)
page_shift = 12;
if(large_block==3)
page_shift =13;
if(large_block == 2)
{
/* Read pages */
/* buf+=(1<<(page_shift-1))这里为什么要1左移11位呢? */
/* 那岂不是前4页复制的代码会重叠 */
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1))) {
nandll_read_page(buf, i, large_block);
}
/* Read pages */
/* 还有为什么要分开读取呢?先读前4页,其他正常4K读取? */
for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}else if(large_block == 3) //K9GAG08U0E
{
/* Read pages */
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-2))) {
nandll_read_page(buf, i, large_block);
}
/* Read pages */
for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
else
{
for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
return 0;
}
经过
经过一天的试错和百度,终于弄懂其中微妙之处了。
首先,谢谢这位朋友的博文。我从中知道了nandflash启动的一个秘密。
既然知道这个秘密,但又没有找到相关的文档说明。所以决定证实一下这位朋友的说法。
首先我的代码流程是这样的:
测试代码如下:
/* 以下代码将在内存中运行 */
void DRAM_Main(void){
u_int32* ptr_ram1 = (u_int32 *)(0x50000000 + 4096);
u_int32* ptr_ram2 = (u_int32 *)(0x50000000 + 2 * 4096);
u_int32* ptr_ram3 = (u_int32 *)(0x50000000 + 3 * 4096);
u_int32* ptr_ram4 = (u_int32 *)(0x50000000 + 4 * 4096);
temp(*ptr_ram1);
temp(*ptr_ram2);
temp(*ptr_ram3);
temp(*ptr_ram4);
LED_on(LED2); /* 测试点:3, 点亮LED2 */
/* mprintf("This is in DRAM!!"); */
for(;;){
}
}
因为我是把nandflash中的0块,整个拷贝到内存了,所以通过指针,分别指向内存中的4K、8K、12K、16K的位置。相当于读取nandflash中的1页、2页、3页、4页(页地址从0开始)开头的4字节数据。读出的数据如下:
然后,查看二进制文件:
扫描二维码关注公众号,回复:
9066451 查看本文章
这是映像文件中的2K位置,和读出来的一样
这是映像文件中4K位置的数据,一样的
这是映像文件6K的位置,一样的
8K的位置,还是和串口输出的一样的
结果
从这里就可以证明,从nandflash启动时,BL0是将nandflash的块0的前4页中,每页头2K组合成8K,拷贝到steppingstone中的。BL0是厂家固化好的代码,我们改不了。如果我们要自己一些启动代码就需要这点。无论是写入,还是读取这8K的启动代码,也要遵循这样的约定。
现在回过头来看uboot的代码,终于明白为什么要buf+=(1<<(page_shift-1))了。
这也是为什么要先读取前4页,然后正常读取后面的页的原因。