S5PV210的NandFlash应用(二)

准备分析

        《S5PV210的NandFlash应用(一)》有很多bug,为了文章完整性就不在原文上进行修改了。(一)是在调试nand_cp.c的时候,程序运行过之后,灯立即亮了起来,让我误以为我的NandFlash读操作正常了,最后在往下进行大文件拷贝的时候出现异常,我不得不重新回到这个Nand_cp.c这里来。这次结合Uart打印出NandFlash读出的数据,和210.bin文件进行对比,发现后边错误很多,但是我的程序也能运行。总结出了(一)里边的bug有: 1.nand_cp.c中应该调用board_init_f_nand(),而非copy_uboot_to_ram_nand()。2.board_init_f_nand中的跳转代码uboot = (void *)0xd024010明显有误,为什么能够运行,就是实质都没有调用;3.是在start.S中通过相跳转到了main函数的,而非链接地址跳转的,造成了假象。 用一天冷静下来,重新来理清思路。 1.先把Uart调试通。2.通过Uart打印出NFDATA8_REG寄存器的值。3.和210.bin二进制文件对比。4.自己做二进制文件到210.bin的后边,进行对比。
        

资源工具

        同《  S5PV210的LED应用(一)
        NandFlash: K9GAG08U0F (2G)

着手写程序
        (1) void board_init_f_nand ((unsigned long bootflag)) ,负责调用copy_uboot_to_ram_nand()和uboot = (void *)0xd0024010;
        (2) int copy_uboot_to_ram_nand (void),判断NandFlash类型页的大小。调用int nandll_read_blocks。
        (3) int nandll_read_blocks (ulong dst_addr, ulong size, int large_block),读一块大小。
        (4) int nandll_read_page (uchar *buf, ulong addr, int large_block),读一页大小,并通过串口打印出NFDATA8_REG寄存器的值。
具体的实现:

void board_init_f_nand(unsigned long bootflag)
{
	__attribute__((noreturn)) void (*uboot)(void);
	copy_uboot_to_ram_nand();

	/* Jump to U-Boot image */
	uboot = (void *)0xd0024010;
	(*uboot)();
	/* Never returns Here */
}

int copy_uboot_to_ram_nand (void)
{
	int large_block = 0;
	int i;
	vu_char id;

	NAND_CONTROL_ENABLE();
  NAND_ENABLE_CE();
  NFCMD_REG = NAND_CMD_READID;
  NFADDR_REG =  0x00;

	/* wait for a while */
  for (i=0; i<200; i++);
	id = NFDATA8_REG;
	id = NFDATA8_REG;

	if (id > 0x80)
		large_block = 1;
		
	if(id == 0xd5)
	{ //page_size = 8k
		large_block = 3;
	}

	/* read NAND Block.
	 * 128KB ->240KB because of U-Boot size increase. by scsuh
	 * So, read 0x3c000 bytes not 0x20000(128KB).
	 */
	//return nandll_read_blocks(CONFIG_SYS_TEXT_BASE, COPY_BL2_SIZE, large_block);
	return nandll_read_blocks(0xd0024000, 0x4000, large_block);
}

/*
 * 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 (1 == large_block)
	{
		page_shift = 11;
	
		/* Read pages */
		for (i = (0x6000>>page_shift); i < (size>>page_shift); i++, buf+=(1<<page_shift)) 
		{
			nandll_read_page(buf, i, large_block);
		}
	}
	else if(3 == large_block)
	{
		page_shift = 13;
		
		for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1))) 
		{
		        nandll_read_page(buf, i, large_block-1);
		}
	}
        
	return 0;
}

/*
 * 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;
	volatile char c;
	int page_size = 512;

	if (1 == large_block)
		page_size = 2048;
		
	else if (2 == large_block)
		page_size = 4096;
	
	else if (3 == large_block)
		page_size = 8192;

	NAND_ENABLE_CE();

	NFCMD_REG = NAND_CMD_READ0;

	/* 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;

	if (large_block)
		NFCMD_REG = NAND_CMD_READSTART;

        NF_TRANSRnB();

	/* for compatibility(2460). u32 cannot be used. by scsuh */
	for(i=0; i < page_size; i++) 
	{
		c = NFDATA8_REG; 
		*buf++ = c;
		puthex(c);
		putc(' ');
                
  }

	NAND_DISABLE_CE();
	return 0;
}

下载运行

        同《  S5PV210的LED应用(一)

运行调试
       
        对比如图所示:



        得到结论,前16k代码在NandFlash存储方式如下:
         

遗留问题
  
        1.无



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

袁保康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值