uboot研读笔记 | 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)
Posted Neutionwei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uboot研读笔记 | 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)相关的知识,希望对你有一定的参考价值。
0. 教程完整目录
- 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理
- 01 - 下载uboot源码并使用VSCode远程查看源码、编译uboot(2012.04.01版本)
- 02 - 详细探索uboot启动过程(基于S3C2410处理器)
- 03 - 初步移植uboot 2012.04到JZ2440(修改时钟,配置串口)
- 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)
- 05 - 移植uboot 2012.04到JZ2440(支持Nand Flash读写)
- 06 - 移植uboot 2012.04到JZ2440(支持DM9000C网卡)
- 07 - 移植uboot 2012.04到JZ2440(裁剪uboot大小)
- 08 - 移植uboot 2012.04到JZ2440(设置mtd分区表)
- 09 - 移植uboot 2012.04到JZ2440(设置默认环境变量参数)
- 10 - 移植uboot 2012.04到JZ2440(烧写Linux内核、烧写yaffs2文件系统)
- 11 - 移植uboot 2012.04到JZ2440(移植完成,制作uboot补丁)
在上一篇文章中初步的移植了 uboot 到JZ2440开发板,参考文章:
在支持Nor Flash操作之前,首先要对Nor Flash的读写方法有一定的了解,参考文章:
uboot启动之后正常打印出了CPU信息(比如时钟信息),但是接下来uboot程序提示flash出错,并且死机,如图,在本文中讲述如何定位问题,解决问题,使uboot支持nor flash读写:
1. 定位Flash读写出错问题
定位出错问题所在的方法很简单,定位到红色的日志信息 “Flash:” 在程序中的位置即可,这个内容搜索在VS Code全局搜索中很慢,所以沿着uboot启动过程寻找,很快,在arch/arm/lib/board.c
文件中找到,在函数board_init_r
中,也就是uboot启动的第2阶段。
在代码中可以看到:
此处首先打印出日志信息“Flash:”,然后调用 flash_ini t获取 flash_size,接着对获取到的flash_size进行判断,如果flash_size等于0,则再打印“failed”日志,并且调用hang函数,挂起CPU,即死机:
那么,初步定位,问题就在于 flash_init 函数有问题,进入该函数查看其源码。
flash_init 函数的源码定义在drivers/mtd/cfi_flash.c
文件中,在该函数中,重点代码如图:
可以看到uboot很尽力了,首先调用flash_detect_legacy函数获取Flash的CFI信息,如果获取失败,则调用flash_get_size 函数获取CFI信息,获取之后,将CFI信息中的Flash 大小赋值给size变量,然后返回。
所以,目前问题变为:这两种获取Flash中CFI信息的方法中出现了错误,没有获取到CFI信息。
- 第一种方法:flash_detect_legacy
通过跳转到其定义,可以看到源码是通过宏定义CONFIG_FLASH_CFI_LEGACY配置的,在smdk2440.h文件中搜索一下,可以看到被定义,所以flash_detect_legacy相关方法启用:
在函数的源码中,有一句调试信息通过debug语句输出,可以通过该条语句来查看读取出的三个ID值:
默认情况下,debug函数是被关闭的, 在该文件最开始开启debug的宏定义:
再次编译uboot:
make distclean
make smdk2440_config
make
然后下载u-boot.bin到Nor Flash去,启动,查看串口输出结果:
是不是很棒!
在输出的调试信息中可以看到,Flash的CFI被读出来了,但Flash仍然失败,有待进一步分析,接着根据源代码分析问题原因。
2. 读出ID正确但Flash还是失败的原因
在调试信息中可以看到,读取出的ID信息为c2 2249 0
,查看Nor Flash芯片手册可以看到,0xc2为Manifacture ID,0x2249为Device ID,读出的信息是正确的,但是为什么系统仍然提示Flash出现错误呢?
问题就在于,JEDEC这种古老的标准,它在读取出 ID 信息之后,跑去和Flash库(一个数组)中的信息进行对比匹配,如果匹配到了,就取出预先已经定义好的信息,比如Flash大小之类的信息,如图中红框所示:
jedec_flash_match函数定义在drivers/mtd/jedec_flash.c
文件中,源码如图:
翻译一下这个函数的注释就明白了:
将jedec id 和table相比进行匹配,如果匹配到值,则填充整个flash_info结构体!
所以,读取到的ID值正确,但是系统仍然报错Flash的情况只有一个:预先设置的table中不存在目前的FlashID所匹配的信息。
3. 添加板载Nor Flash的jedec信息
jedec_table同样定义在该文件中(drivers/mtd/jedec_flash.c
)。
首先是类似于 CONFIG_SYS_FLASH_LEGACY_256Kx8 这样的宏定义,对Flash进行大概的分类,JZ2440开发板板载Nor Flash型号是MX29LV160DBTI-70G,大小是16M-bit
,换算是字节大小就是2MB
。
在jedec_table的最后发给仿照其它信息,添加本款Flash的jedec信息:
- ① mfr_id
该信息为Manifacture ID,在文件include/flash.h
中定义,这里使用MX的:
- ② dev_id(器件ID)
器件ID在文件drivers/mtd/jedec_flash.c
中宏定义,如图,添加本款Flash的:
- ③ name
这个按喜好写就行。
- ④ uaddr(unlock addr,解锁地址)
使用16位的解锁地址宏定义 MTD_UADDR_0x0555_0x02AA 即可。
- ⑤ DevSize(器件容量大小)
容量大小也在drivers/mtd/jedec_flash.c
文件中设置,这里选择SIZE_2MiB:
- ⑥ CmdSet(使用的指令集)
使用默认的CFI_CMDSET_AMD_LEGACY即可。
- ⑦NumEraseRegions(擦除区域种类个数)
本款Flash芯片的擦除扇区结构总共有4种,如图:
- ⑧regions
使用ERASEINFO()宏定义填写上面擦除区域种类的详细信息,该宏定义的格式如下:
ERASEINFO(size,blocks) //表示sIze大小(单位是字节)的扇区有blocks个
综合以上分析,最后填充的本款Flash信息为:
/* JZ2440开发板板载NoR FLASH */
#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16
{
.mfr_id = (u8)MX_MANUFACT,
.dev_id = MX29LV160DBTI,
.name = "MX MX29LV160DBTI",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = CFI_CMDSET_AMD_LEGACY,
.NumEraseRegions = 4,
.regions = {
ERASEINFO(16*1024, 1),
ERASEINFO(8*1024, 2),
ERASEINFO(32*1024, 1),
ERASEINFO(64*1024, 31),
}
},
#endif
添加信息完成后,在单板配置文件include/configs/smdk2440.h
中开启这款Flash的宏定义:
编译,下载,在串口终端查看输出:
可以看到flash检测不会卡死,uboot正常启动到命令行界面,但是仍然有一个报错信息,根据报错信息在文件中搜索,找到该行日志的打印位置,可以看到,当扇区数量大于宏定义CONFIG_SYS_MAX_FLASH_SECT时,系统就会打印出这行日志信息:
找到该宏定义在单板配置文件中,该款Flash实际扇区是35个,修改该宏定义:
编译,下载,再次查看串口输出:
可以看到,Flash检测没有任何问题,uboot正常启动到命令行界面,并且命令可以正常使用,调试完毕,不用输出调试信息,所以将drivers/mtd/cfi_flash.c
文件中开头添加的宏定义关掉:
再次编译输出,可以看到Flash的检测调试信息不会打印。
4. 修改uboot命令行打印头信息
在之前的打印信息中,uboot命令行可以正常使用,但是打印头信息还是"smdk2410",这里可以在单板配置文件include/configs/smdk2440.h
中修改宏定义,如图,改为我们需要显示的信息:
修改之后再次编译,下载,查看串口输出,结果符合预期:
补充,可以使用uboot命令flinfo
查看当前flash存储器信息,与上面的知识进行对比理解:
扇区起始地址与数据手册相对应(RO是uboot软件中指定的,RO标示出的是当前程序存储区):
接收更多精彩文章及资源推送,欢迎订阅我的微信公众号:『mculover666』。
以上是关于uboot研读笔记 | 04 - 移植uboot 2012.04到JZ2440(支持Nor Flash读写)的主要内容,如果未能解决你的问题,请参考以下文章
uboot研读笔记 | 12 - uboot目录结构分析(2016.03版本)
uboot研读笔记 | 01 - 下载uboot源码并使用VSCode远程查看源码编译uboot(2012.04.01版本)
uboot研读笔记 | 02 - 详细探索uboot启动过程(基于S3C2410处理器)
uboot研读笔记 | 00 - 嵌入式Linux系统中Bootloader的作用和基本运行原理