文章目录
1、分析启动时Flash: *** failed ***
错误
上一节启动uboot出现如下所示,我们搜索下错误代码Flash:
上面的Flash: *** failed ***
是属于uboot第二阶段函数board_init_r()
里的代码,代码如下所示,位于arch/arm/lib/board.c
/*第二阶段*/
void board_init_r(gd_t *id, ulong dest_addr) //gd uboot重定位地址
{
... ...
puts("Flash: "); //打印flash:
flash_size = flash_init(); //初始化nor_flash
if (flash_size > 0)
{
... ...
print_size(flash_size, "\n"); //打印nor_flash的大小
}
else
{
puts(failed); //打印数组failed[]="*** failed ***\n";
hang(); //进入while中,并打印: ### ERROR ### Please RESET the board ###
}
#if defined(CONFIG_CMD_NAND)
puts("NAND: "); //打印NAND:
nand_init(); //初始化nand_flah
... ...
}
从上面代码看出,board_init_r()
会来初始化nor
,由于新的uboot
不支持nor
,所以flash_init()
初始失败,然后打印一串错误代码后等待复位。
由于2440在nand启动时,会自动装载nand的前4k内容,所以不支持nor flash,因为nor的前4k内容被nand占用。
2、修改nor 初始化的代码
为了避免nand启动一直卡住,board.c
中修改为:
因为hang
就是卡死,所以将其去掉:
在下列函数中打印如下信息:
board_init_r
flash_init
flash_get_size
其中debug:
根据_DEBUG
在u-boot-2012.04.01\drivers\mtd\cfi_flash.c
文件中增加定义:
编译:make
把服务器上的u-boot.bin传回pc上;
usb 1 30000000,再使用dnw下载u-boot.bin
protect off all :去除nor flash 的写保护
erase 0 7FFFF :0(开始地址)7FFFF(结束地址)共512k
cp.b 30000000 0 80000 :把程序烧写到0地址,烧写大小为0x80000
程序出错:
打印出nor flash
的厂家ID=0xC2
,设备ID=0x2249
,显然uboot匹配读出的ID没有成功。
搜索JEDEC PROBE
字段,找到位于board_init_r()->flash_init()->flash_detect_legacy():
如上图所示,该函数会进入board_init_r()->flash_init()->flash_detect_legacy()->jedec_flash_match()
,里面会通过两个ID来匹配jedec_table[]
。
3、在数组jedec_table[]里添加nor flash
修改u-boot-2012.04.01\drivers\mtd\jedec_flash.c
中的jedec_table[]
数组,参考手册如下:
在jedec_table[]
数组最后加上如下内容:
- 其中的
NumEraseRegions
是擦除区域:
擦除区域只有一种:NumEraseRegions = 1
。
擦除区域只有两种:NumEraseRegions = 2
。
我们有4种。
- 其中:
regions
表示每一种擦除区域有多少个块。
我们使用的nor flash
扇区结构如下:
下面8字就是16字节,即16K有1种;8K有2种。。。。
如大小为16*1024
的共有1
块;
如大小为8*1024
的共有2
块;
。。。
重新编译下载烧写:
出现错误:ERROR:too many flash sectors
,说flash的扇区太多了,搜索找到位于drivers/mtd/jedec_flash.c
中:
显然是CONFIG_SYS_MAX_FLASH_SECT
宏小于我们flash
的扇区,所以打印ERROR。
修改:u-boot-2012.04.01\include\configs\smdk2440.h
中宏CONFIG_SYS_MAX_FLASH_SECT
的大小:
所以修改CONFIG_SYS_MAX_FLASH_SECT
宏定义(位于include/configs/smdk2440.h)
,并去掉之前定义的DEBUG
调试宏(位于u-boot-2012.04.01\drivers\mtd\cfi_flash.c)
4、重新烧写nor flash
再次编译:make
把服务器上的u-boot.bin传回pc上;
usb 1 30000000,再使用dnw下载u-boot.bin
protect off all :去除nor flash 的写保护
erase 0 7FFFF :0(开始地址)7FFFF(结束地址)共512k
cp.b 30000000 0 80000 :把程序烧写到0地址,烧写大小为0x80000
其中RO
表示uboot
在软件层面指定当前地址为只读,可以使用protect off all
去除。
然后通过uboot命令,检测nor的读写是否正确:
查看内容:
往内存写数据:
使用0x32000000
地址再次烧写,数据正确。
5、重新设置栈
拷贝的数据和源数据内容不同,可能是我们的栈设置有问题。
由于之前重定位,清除bss之后栈一直指向30000000
的位置,每调用一个函数栈应该会变化。由于我们的设置问题,导致栈一直卡在30000000
的位置,所以拷贝数据后再比较源数据和目的数据就会出错。
在board_init_f
中 addr_sp
就是栈的地址
那么在c程序中用到汇编中定义的变量如下图:
其中汇编中定义_bss_end_ofs
变量,在c程序中直接使用。
修改start.S
启动文件:添加全局变量
在board_init_f
函数中:声明base_sp
在调用第二阶段代码之前重新设置栈:
在board_init_f
函数中将之前的栈的地址传回来:
再次make
时出现报错:
在 include\configs\smdk2440.h
中屏蔽CONFIG_YAFFS2
:
重新烧写测试:
usb 1 30000000 //使用usb下载到SDRAM上,1表示一直下载,直到完成
//然后打开DNW,传输新的uboot.bin给usb
protect off all //关闭nor的写保护
erase 0 +7FFFF //擦除nor上的 0~7FFFF地址内容, (512k*1024-1)=+7FFF=擦除长度=512kb,要大于新的uboot.bin才行
cp.b 30000000 0 80000 //将SDRAM上的新的uboot.bin,拷贝到nor上(烧写512K)
protect off all
erase 80000 8ffff /*擦除512K*/
cp.b 32000000 80000 1000 /*从32000000拷贝1000字节数据到80000位置*/
cmp.b 32000000 80000 1000 /*比较拷贝的数据是否相同*/
现在nor flash
就支持了nor
的操作了。
上一节:4、移植UBOOT之支持nand启动