移植u-boot学习笔记6-----修改代码支持nor flash

支持了nand flash启动并不是说支持了以后对nand flash的读写操作,支持nand flash启动只需要在重定位时(把代码从nand flash拷贝到SDRAM的函数copy_code_to_sdram)x写出一个nand flash的读函数nand_read_ll(),吧代码从nand flash复制到sdram里面去就可以了,

1、分析

(1)烧写代码,重启开发板,查看输出信息


输出信息表示flash失败后重启开发板

(2)在u-boot中搜索代码“Flash:”,在board.c中存在


(3)board.c分析

打印“Flash:”的语句


初始化 flash,如果flash的大小大于0就打印flash的大小,否则打印failed,调用hang()函数,flash_init是对nor flash的初始化函数



hang()函数是打印出错误信息,然后死循环,让系统在此卡死


(4)修改

把hang函数注释掉,也就是把死循环去掉,程序就可以继续往下跑。加上puts("0KB\n\r")这一段是为了避免从nand flash启动时,会在这里卡死,因为从nand flash启动时,那个nor flash是没办法访问的


(5)归根结底要分析flash_init()函数

怎样才能flash_init()函数里面识别出我们的nor flash


也就是下面所说的数组jedec_table[]里面的项

2、看flash_init()函数

(1)搜索此函数,在driverst/mtd/cfi_flash.c


(2)第1条语句是指用旧的方法检测nor flash,如果不成功再用下面那种方法检测nor flash


(3)第1条语句flash_detect_legacy()分析

先看宏cfi_flash_bank_addr,在linux下搜索


在100行中里有注释


宏CONFIG_SYS_FLASH_BANK_LIST为0x00000000,也就是最终返回0地址


也就是说flash_detect_legacy()左边参数是0,经过分析用旧的方法读不出来。

(2)新的方法flash_get_size(),实现了nor flash的访问

打印调试信息


debug函数的宏定义如下


这里debug_cond函数的实现,如果cond存在就打印信息,也就是说根据宏_DEBUG为1时,才能打印


所以定义宏


(3)新的方法flash_get_size(),实现了nor flash的访问

只要确定基地址、块数


(4)编译、烧写

先拷贝修改过的board.c和cfi_flash.c

要烧写到nor flash里面去,因为要从nor flash启动。


输入flinfo命令查看( flinfo 打印Flash存储器的信息,并列出所有Sector。flinfo N 单独打Flash存储器N Block的信息

下面的RO是uboot在软件上指定相应的块是只读的,想烧写它的话需要执行protect off all ,这是软件上的一种限制


3、看打印信息分析

(1)下面是nor flash发出的各种命令(u-boot下对nor flash的操作)。识别出ID 


(2)搜索ID

打印出ID,用jedec_flash_match函数看是否匹配,看打印信息是读出来了,但跟数组比较不成功


jedec_flash_match函数会把ID值跟某个数组jedec_table[]比较,如果数组没有含有他表示找不到。我们的是1M×16位的,如果找到就知道nor flash的参数


在数组后面添加一项

第一个是厂家ID,第二个是设备ID,第三个是名字,第4个是解锁地址,nor flash可以像内存一样读,但是要写它的话就必须先解锁,解完锁后发出命令,下面的555和2AA是两个解锁地址,解锁地址是nor flash看到的地址,而后面的555是发命令地址,0表示8位,1表示16位;第5个参数是设备大小为2M,第6个参数是命令集,第7个参数是擦除区域的个数,第8个参数是大小为16K(16*1024字节)的块的个数是1......



(3)看jz2440板中nor flash芯片的手册,看他的ID

我的nor flash芯片型号是mx29lv160db,搜索到相关手册,下图是读取厂家ID和设备ID 的命令操作,经过3个周期写入指令,再经过一个周期读取地址00,得厂家ID值c2,我们的nor flash是16位的,看原理图可知,因而用word.对于设备ID,可由下面知为2249



(4)关于解锁地址

由于CPU是8位的,而nor flash是16位的,因而CPU的A0不接,CPU的A1接到nor flash里面的A0,我们从芯片手册上看到的地址555和2AA是nor flash自身感受到的,我们CPU发出的地址是555左移1位


(5)关于擦除区域

也就是nor flash的擦除块是多少。只有一种格式是为1,有两种格式是2个,如下面块的结构有4种,因而有4种擦除区域。

(6)块的结构

总共有4个,这里16KB的有一个,8KB的有2个,32KB的有1个,64KB的有31个


4、烧写实验

(1)用旧u-boot引导新u-boot下载


(2)我们u-boot本身有512K,转换成16进制是80000.因而擦除80000后的数据,擦除80000到90000.从内存30000000拷贝10000到nor flash的80000那里,也就是64K。


md.b命令查看内存30000000的内容


md.b命令查看nor flash为80000的内容


往地址30000000这个地址写值12345678,然后重新擦除nor flash,然后重新拷贝,cp.b命令会分辨80000这个地址,发现是nor flash的地址后,会调用nor flash的写函数发出各种命令,然后再来烧写数据。用md.b 80000命令查看地址为80000的数据。出现78是因为md.b中b是字节的意思,也就是说只写一个字节。


用cmp.b命令比较内存地址30000000和nor flash地址80000的10000字节数据是否全是一样的


从上面可以看出有一个地方不对,是否源里面的数据被改变?

修改内存地址,也就是复制不同的内存中的内容,从30000000改为32000000.复制后内容完全一样。


为什么之前的30000000地址烧写进去有问题,现在的32000000地址就没问题,是不是之前的设置有问题。看看内存有没有被用到。内存之前设置了栈(在0x30000f80这个地方),但是在启动函数board_init_f里面会把gd_t结构体复制到SDRAM 的高地址上去,以后用的都是高地址那一块内存。难道栈没有被重新设置设置,从0x30000f80转向指到高地址的地方。


栈没有被重新设置,没有从0x30000f80转向指到高地址的地方。也就是栈一直在0x30000f80这个地方,每调用一个C函数,栈都会有变化,所以30000000后的地方由于函数的执行导致里面的数据发生变化。

看一下C语言调用汇编,是先在汇编里先用global关键字定义,表示是全局的变量。在C语言中用extern定义关键字,表示是外部文件变量。


因而重新设置栈

在C函数中定义、保存变量board.c



在汇编中start.S

需要先跳到SDRAM里面执行,然后才重新设置栈,

这条指令才会在SDRAM里面设置那个变量。如果不先跳到SDRAM里面去的话,有可能变量base_sp现在在nor flash上面。去操作它时无法读写,因为是用相对跳转的指令取地址的。




超级终端(用串口下载)是迫不得已的办法

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值