real210移植记录-支持eMMC,增加菜单操作

本次记录的移植是使该u-boot支持eMMC,开发板为real210最新版的开发板,标配eMMC 8GB flash,之前的移植都是在之前的210硬件上进行的核心板版本为v2,flash为nand 512MB。本次修改让其支持eMMC,并且添加菜单操作。

首先考虑到emmc和SD卡操作协议兼容,那么之前做的u-boot是不是可以启动呢,说做就做,使用配带的u-boot把我自己的u-boot烧写进开发板,嘿嘿,可以跑起来,我下载的u-boot已经把环境变量的保存修改为了SD卡。结果环境变量也可以正常保存。开发板emmc接的是SD0通道。

说的是支持,其实基本什么也没做,呵呵。

既然可以用,那么就相对容易多了。下面就是怎么使用自己制作的u-boot下载自己的u-boot,而且可以正常跑起来。想法是正确的,现实是残酷的,~~~~(>_<)~~~~ 。

好不容易成功的把u-boot能够烧写进emmc了,可是无法启动,并且提示check num error。虽然没有启动,但是提示的错误就很明显了,校验和校验失败。那么怎么会校验失败呢,原因就是在写入的时候没有进行校验和计算。

所以就改进加入了校验和的计算代码,再次写入,嘿嘿,OK了,可以正常跑起来了。

下面说说修改方法:

使用命令tftp 3ff00000 /u-boot/u-boot.bin把u-boot加载进内存(这里建立在有u-boot能够启动的情况下,这里的u-boot是使用板子配带的u-boot烧写的)

烧写BL1,命令是mmc write 3ff00000 1 10,注意这里的数字是16进制,那么这条命令的含义是什么呢,烧写u-boot的前16个blocks的数据,一个block大小为2k,实际上BL1只使用了8K,所以只要不少于8K的代码,都是可以的,当然了不能大于48了,因为第49 block开始存放的是BL2,也即完整的u-boot。

烧写BL2,命令是mmc write 3ff00000 31 400,起始为第49 block(16进制为31),大小为1024 blocks(16进制为400)。

完成后重启,悲剧了,error。原因是校验和校验失败,因此需要在烧写时对前8K进行校验和计算再写入才行。

那么问题就来了,命令行无法进行校验和计算啊,所以需要用代码实现了。

那好,就编写代码吧,另外我为了调试方便,顺便增加了调试用的菜单选项。

主要函数如下

void tftp_burn(char *cmd)
{
	if (!strcmp(cmd, "u-boot"))
	{
		char *buf;
		ulong checksum = 0;
		int i = 0;
		ExecuteCmd("tftp 3ff00000 /u-boot/u-boot.bin");/*先拷贝u-boot.bin到内存3ff00000处*/
		buf = 0x3ff00000 + 16;/*把u-boot首地址偏移16字节的内存地址赋值给buf,此时u-boot的首地址是3ff00000*/
		for(i = 16;i < 8192;i++)/*循环进行u-boot的前8K代码校验和校验,i赋值为16是因为u-boot的前16字节可不必要校验和校验*/
		{
			checksum += *buf;
			buf++;		
		}
		*((volatile u32 *)(0x3ff00000 + 0x8)) = checksum;/*把计算出的校验和写入3ff00008地址处等待写入EMMC*/
		printf("\nBL1 checksum is:%08x\n\n", checksum);
		
		/*printf("erase start block 1 (count 1073 blocks)...");
		ExecuteCmd("mmc erase 1 431");*/

		printf("writing BL1 start block 1 (count 16 blocks)...");
		ExecuteCmd("mmc write 3ff00000 1 10");/*烧写BL1到eMMC的第一个block,长度为16 block(注意此时是10,但是为16进制)*/
		
		printf("\n");
		printf("writing u-boot.bin start block 49 (count 1024 blocks)...");
		ExecuteCmd("mmc write 3ff00000 31 400");/*烧写u-boot到eMMC的第49个block,长度为1024 block(注意此时是400,但是为16进制)*/
	}
	else if(!strcmp(cmd, "debug"))	
	{
		ExecuteCmd("tftp 3ff00000 /u-boot/u-boot.bin");
		printf("Run u-boot in 3ff00000\n");
		ExecuteCmd("go 3ff00000");	
	}
}
void realarm_tftp()
{
	unsigned char select;
	while(1)
	{
		printf("\n#**** Select the fuction ****#\n");
		/*由于system过大,所以tftp下不能下载文件系统*/
		printf("[1] Tftp burn u-boot\n");
		printf("[2] Tftp burn kernel\n");
		printf("[3] Tftp debug u-boot\n");		
		printf("[4] Exit\n");
		printf("Enter your Selection:");
	
		select = getc();
		printf("%c\n", select >= ' ' && select <= 127 ? select : ' ');	
	
		switch(select) 
		{
			case '1':
				tftp_burn("u-boot");
				break;
			
			case '2':
				tftp_burn("kernel");
				break;
					
			case '3':/*此选项功能需要屏蔽u-boot配置头文件中的#define CONFIG_SKIP_LOWLEVEL_INIT,且CONFIG_SYS_TEXT_BASE需要修
				   改为3ff00000*/
				tftp_burn("debug");/*u-boot 调试命令,tftp下载u-boot然后使用go命令运行之*/
				break;
			
			default:
				break;
		}
	}	
}



static void ExecuteCmd(char *cmd)
{
	parse_string_outer(cmd, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
}

校验和计算部分为:

		ulong checksum = 0;
		int i = 0;
		ExecuteCmd("tftp 3ff00000 /u-boot/u-boot.bin");/*先拷贝u-boot.bin到内存3ff00000处*/
		buf = 0x3ff00000 + 16;/*把u-boot首地址偏移16字节的内存地址赋值给buf,此时u-boot的首地址是3ff00000*/
		for(i = 16;i < 8192;i++)/*循环进行u-boot的前8K代码校验和校验,i赋值为16是因为u-boot的前16字节可不必要校验和校验*/
		{
			checksum += *buf;
			buf++;		
		}
		*((volatile u32 *)(0x3ff00000 + 0x8)) = checksum;/*把计算出的校验和写入3ff00008地址处等待写入EMMC*/
		printf("\nBL1 checksum is:%08x\n\n", checksum);

把realarm_tftp函数放入main_loop中,要放到延时之后。

完成后会有如下的界面

  
 
选择1即可自动进行烧写u-boot到emmc了,该方式是使用tftp实现u-boot到内存中的,既可以实现下载,也可以很方便的调试修改的u-boot,很方便。

选项3的功能是tftp下载了u-boot之后直接跳转到指定内存地址运行,不烧写到emmc中,这个是为了防止由于修改错误导致emmc启动失败而带来的麻烦,是调试更加的有效率,O(∩_∩)O~!

本次记录到此。




你可能感兴趣的:(移植,u-boot)