首页 > 代码库 > tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动

tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动

       我们知道 s5pv210启动方式有非常多种,sd卡和nand flash 启动就是当中的两种,前面我们实现的都是基于sd卡启动,这节我们開始实现从nand flash 启动:  

    从 NAND 启动 u-boot,须要 BL1 初始化 NAND 控制器,然后从 NAND 拷贝 BL2 到 DDR 内存。这里的BL1 即我们移植的 u-boot-spl.bin,BL2 即我们移植的 u-boot.bin。在 u-boot.bin 中的 NAND 驱动比較大,它包括了非常多功能,而 u-boot-spl.bin 中仅仅须要从 NAND 拷贝BL2 到 DDR 即可了,因此我们能够在 u-boot-spl.bin 进行简单的 NAND 控制器初始化,然后使用三星提供的带 8 位硬件 ECC 的 NAND 拷贝函数来拷贝 u-boot.bin 到 DDR 内存。我们改动 board/samsung/tiny210/tiny210.c 中的 copy_bl2_to_ram 函数,在这个函数中首先推断当前是从 SD 卡启动还是从 NAND 启动,假设是从 NAND 启动则进行 NAND 初始化,然后从 NAND 拷贝BL2 到 DDR 内存,假设是从 SD 卡启动,则从 SD 卡拷贝 BL2 到 DDR 内存。我们通过读取 OMR 寄存器来推断 S5PV210 当前是从哪个设备启动的。參考手冊 Table  6-3,手冊上并没有说 OM  寄存器的地址,我是參考的三星原厂的 u-boot 代码。代码中都有具体凝视,具体请看代码:

void copy_bl2_to_ram(void)
{
/*
** ch:  通道
** sb:  起始块
** bs:  块大小
** dst: 目的地
** i: 	是否初始化
*/
#define CopySDMMCtoMem(ch, sb, bs, dst, i) 	(((u8(*)(int, u32, unsigned short, u32*, u8))	(*((u32 *)0xD0037F98)))(ch, sb, bs, dst, i))
	
#define MP0_1CON  (*(volatile u32 *)0xE02002E0)
#define	MP0_3CON  (*(volatile u32 *)0xE0200320)
#define	MP0_6CON  (*(volatile u32 *)0xE0200380)	

#define NF8_ReadPage_Adv(a,b,c) (((int(*)(u32, u32, u8*))(*((u32 *)0xD0037F90)))(a,b,c))
	
	u32 bl2Size = 250 * 1024;	// 250K
	
	u32 OM = *(volatile u32 *)(0xE0000004);	// OM Register
	OM &= 0x1F;					// 取低5位
	
	if (OM == 0x2)				// NAND 2 KB, 5cycle 8-bit ECC
	{
		u32 cfg = 0;
		struct s5pv210_nand *nand_reg = (struct s5pv210_nand *)(struct s5pv210_nand *)samsung_get_base_nand();
		
		/* initialize hardware */
		/* HCLK_PSYS=133MHz(7.5ns) */
		cfg =	(0x1 << 23) |	/* Disable 1-bit and 4-bit ECC */
				/* 以下3个时间參数略微比计算出的值大些(我这里依次加1),否则读写不稳定 */
				(0x3 << 12) |	/* 7.5ns * 2 > 12ns tALS tCLS */
				(0x2 << 8) | 	/* (1+1) * 7.5ns > 12ns (tWP) */
				(0x1 << 4) | 	/* (0+1) * 7.5 > 5ns (tCLH/tALH) */
				(0x0 << 3) | 	/* SLC NAND Flash */
				(0x0 << 2) |	/* 2KBytes/Page */
				(0x1 << 1);		/* 5 address cycle */
	
		writel(cfg, &nand_reg->nfconf);
		
		writel((0x1 << 1) | (0x1 << 0), &nand_reg->nfcont);
		/* Disable chip select and Enable NAND Flash Controller */
	
		/* Config GPIO */
		MP0_1CON &= ~(0xFFFF << 8);
		MP0_1CON |= (0x3333 << 8);
		MP0_3CON = 0x22222222;
		MP0_6CON = 0x22222222;		
		
		int i = 0;
		int pages = bl2Size / 2048;		// 多少页
		int offset = 0x4000 / 2048;			// u-boot.bin在NAND中的偏移地址(页地址)
		u8 *p = (u8 *)CONFIG_SYS_SDRAM_BASE;
		for (; i < pages; i++, p += 2048, offset += 1)
			NF8_ReadPage_Adv(offset / 64, offset % 64, p);
	}
	else if (OM == 0xC)		// SD/MMC
	{
		u32 V210_SDMMC_BASE = *(volatile u32 *)(0xD0037488);	// V210_SDMMC_BASE
		u8 ch = 0;
		
		/* 參考S5PV210手冊7.9.1 SD/MMC REGISTER MAP */
		if (V210_SDMMC_BASE == 0xEB000000)		// 通道0
			ch = 0;
		else if (V210_SDMMC_BASE == 0xEB200000)	// 通道2
			ch = 2;
		CopySDMMCtoMem(ch, 32, bl2Size / 512, (u32 *)CONFIG_SYS_SDRAM_BASE, 0);
	}
}

   又一次编译,但编译之前要加入nand所用的头文件:#include <asm/arch/nand_reg.h>成功生成 spl/tiny210-spl.bin 和 u-boot.bin,将它们所有复制到 tftp server文件夹下,然后就能够使用上一节移植的 u-boot 来烧写最新的 u-boot 到 NAND FLASH。

首先从 SD 卡启动开发板 ,擦除整个 NAND FLASH:

技术分享

使用 tftpboot 下载 tiny210-spl.bin 到 DDR 的起始地址 0x20000000

技术分享

烧写 tiny210-spl.bin 到 NAND 的 0 地址:

技术分享

使用 tftpboot 下载 u-boot.bin 到 DDR 的起始地址 0x20000000

技术分享

烧写 u-boot.bin 到 NAND FLASH 的 0x4000 地址(0x0~0x3FFF 预留给 tiny210-spl.bin)

技术分享

拨动拨码开关,从 NAND 启动开发板,能够观察到u-boot正常启动了,如今我们的u-boot功能基本都实现了,我把代码放在这里 ,有兴趣的朋友能够看看:tiny210_u-boot_201404_v2.0,之后即可我们都代码和功能的完好。



tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动