s3c2440裸机-内存控制器(三-3、norflash编程之uboot中操作norflash)

2023-08-09  

前提:
norflash初始化正常,能够正常从nor上执行。

cpu总是从0地址读取指令执行程序。当cpu设置成nor启动时,0地址对应nor。cpu从nand启动时,0地址对应sram。


1.读取norFlash

我们将板子设为nor启动,那么0地址对应nor,我们先将uboot烧写到nor中。我们先看下这款NorFlash的手册,找到操作flash的命令表:

下面简单的举一些例子:


1)复位(reset):

往任何一个地址写入F0即可。

2)读ID:

很多的Nor Flash可以配置成位宽16bit(Word),位宽8bit(Byte),我们这款norflash数据位宽为16bit。下面我们按照nor手册上的命令表尝试一下:


往地址555H写入AAH(解锁)

往地址2AAH写入55H(解锁)

往地址555H写入90H(命令)

读0地址得到厂家ID(C2H)

读1地址得到设备ID(22DAH或225BH)

退出读ID状态(给任意地址写F0H就可以了)

上面的地址是对于norflash的,那么我们CPU要怎么发送地址呢?

从上面原理图我们知道CPU和nor的地址是错位相连的,也就是:

比如:

cpu地址 nor地址
A15~A1 A14~A0

那么可以看到cpu的地址实际相当于是nor地址左移了一位,那么比如要想给nor上的555H地址写入AAH,那么CPU要发出的地址应该为0x555<<1,也就是nor地址的2倍。

下面对在Nor Flash的操作,cpu的操作,U-BOOT上的操作进行比较,如下表:

Nor Flash的操作 cpu的操作 U-BOOT上的操作
往地址555H写入AAH(解锁) 往地址AAAH写入AAH(解锁) mw.w aaa aa
往地址2AAH写入55H(解锁) 往地址554H写入55H(解锁) mw.w 554 55
往地址555H写入90H(命令) 往地址AAAH写入90H(命令) mw.w aaa 90
读0地址得到厂家ID(C2H) 读0地址得到厂家ID(C2H) md.w 0 1 (1:表示读一次)
读1地址得到设备ID(22DAH或225BH) 读2地址得到设备ID(22DAH或225BH) md.w 2 1
退出读ID状态(给任意地址写F0H) 退出读ID状态(给任意地址写F0H) mw.w 0 f0

我们读出厂家id为c2, 设备id为2249,和我们的nor手册上是一致的。我们发出f0命令,进行复位,这时读取的数据就不再是厂家id和设备id了,而是我们norflash中的实际的数据17 00 00 ea。

3)读数据:

前面我们说过, nor可以像ram一样的读,所以只要做好内存控制器的初始化工作就可以直接读了。

我们再用ue以16进制打开我们烧进去的uboot.bin,发现内容一样,说明我们从norflash中读出来的数据是正确的。

4)读属性:

通常内核里面要识别一个 Nor Flash 有两种方法:

一种是 jedec 探测,就是在内核里面事先定义一个数组,该数组里面放有不同厂家各个芯片的一些参数,探测的时候将 flash 的 ID 和数组里面的 ID 一一比较,如果发现相同的,就使用该数组的参数。 jedec 探测的优点就是简单,只要通过flash的数组编号,即可访问该款flash属性,缺点是如果内核要支持的 flash 种类很多,这个数组就会很庞大。

一种是 CFI(common flash interface)探测,就是直接发各种命令来读取芯片的信息,比如 ID、容量等,芯片本身就包含了电压有多大,容量有有多少等信息。

我们的这款norflash属于cfi探测,下面对在Nor Flash上操作,2440上操作,U-BOOT上进行cfi 探测(读取芯片信息)。
下图是进入cfi模式后的一些flash属性查找表,可以按照表格命令查询norflash的一些属性(容量、电压、block信息等)。


1.根据命令表往55H地址写入98H进入cfi模式

2.读取`qry`

3.获取属性

Nor Flash上操作cfi 2440上操作cfi U-BOOT上操作cfi
往55H地址写入98H(进入cfi模式) 往AAH地址写入98H mw.w aa 98
读地址10H得到0051('q') 读地址20H得到0051 md.w 20 1
读地址11H得到0052('r') 读地址22H得到0052 md.w 22 1
读地址12H得到0059('y') 读地址24H得到0059 md.w 24 1
读地址27H得到容量 读地址4EH得到容量 md.w 4e 1
读地址1BH得到VCCmin 读地址36H得到VCCmin md.w 36 1

从测试结果我们看到容量为2^21=2M,Vcc最小提供电压是2.7v.

2.写norFlash

我们之前讲过norflash可以像内存一样,用md命令直接读取,不能像内存一样直接写,不信我们试试:

①我们在Nor Flash的0x10000的地址读数据;

由于我们的uboot只有162k,烧录到norflash后,norflash上的的0x100000地址还没有被写入数据,norflash的容量为2M(0~0x200000),所以读取NorFlash的0x10000的地址数据是0xffff...

②在Nor flash的10000的地址写数据下0x1234,然后在这个地址读数据;

③从上图我们验证了norflash可以像内存一样直接读,但不能像内存一样直接写,那么要怎样才能写norflash呢?

我们按照norflash手册上的命令表:

Nor Flash上写操作 2440上写操作 U-BOOT上写操作
往地址555H写AAH(解锁) 往地址AAAH写AAH(解锁) mw.w aaa aa
往地址2AAH写55H(解锁) 往地址554H写55H(解锁) mw.w 554 55
往地址555H写A0H 往地址AAAH写A0H mw.w aaa a0
往地址PA写PD 往地址0x100000写1234h mw.w 100000 1234

我们读取数据发现0x1234已被写入到地址0x100000.

④我们再次往0x100000地址处,写入0x5678;

这时我们发现0x100000地址处的数据不是0x5678,而是0x1230,为什么?

由于原来的数据已经是0x1234不是全0xffff,我们之前norflash原理中讲过只能将flash存储介质中的1变成0,不能将0变成1。所以在0x1234的基础上不去擦出直接继续去写0x5678是会有问题的。

0001 0010 0011 0100(0x1234)

0101 0110 0111 1000(0x5678)

----------------------------

0001 0010 0011 0000(0x1230)


所以flash写入前一定要先擦除。

⑤先擦除(参考Nor Flash芯片手册)

Nor Flash擦操作 u-boot擦操作
往地址555H写AAH mw.w aaa aa
往地址2AAH写55H mw.w 554 55
往地址555H写80H mw.w aaa 80
往地址555H写AAH mw.w aaa aa
往地址2AAH写55H mw.w 554 55
往地址PA写30H mw.w 100000 30

擦除后再读取发现数据就已经变成了0xffff,后面就可以进行写操作了。

⑥再写

现在数据就变成我们的0x5678了。

注意:在写norflash时,要注意不要写0地址或者是uboot所在的地址,这样写入后norflash上的uboot程序就被破坏了。比如本测试就是写了0x100000地址,这个地址在uboot之外。

问题拓展

1.基于jz2440开发板,用uboot发送md.w 0, md.w 2, md.w 4等偶地址命令能够读取norflash,但使用md.w 1, md.w 3,md.w 5就会出现死机,为什么?

由于我们的norflash是16bit数据位宽的,访问时要2byte对齐。如果不想以2byte为单位进行访问,那么要用uboot中用md.b 1,md.b 3这种单字节读取命令。

2.uboot中操作norflash进行擦写的时候能够解锁一次,擦写多次吗?

不能,每次擦写都要进行解锁动作。

3.uboot中擦除那么是以块(sector)为单位的,那么当进行擦除时发送的地址并不是以块对齐的,会有什么结果?

也能擦除成功,会根据地址范围确定在哪一个块中。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。