关于CPU操作nor flash写入命令解锁时需要地址左移而读写数据时不用左移的问题

我在看韦东山老师嵌入式JZ2440裸板编程中的nor flash操作章节的时候发现一个问题想了很久才想明白,特来分享。

(大前提:s3c设为nor启动的时候nor flash基地址对应cpu编址为0)
**具体问题描述:**因为在此案例中cpu地址线和nor flash的地址线的连接方式是错位连接的。图中 cpu的地址线A1 - A20 分别连在nor flash地址线的A0 - 19,这样引起的问题就是cpu发出某个地址后nor flash所接受的地址被这样接法的硬件强行右移了一位。
如图:

在这里插入图片描述

	比如说cpu发送地址为0x555,那么nor flash所接受的地址就是0x2aa。
	如图:

在这里插入图片描述


右移一位后的数据:

在这里插入图片描述


那么为了方便编程,(站在cpu的角度)能够使我函数发出了地址能够与nor flash的地址对应上,即要在nor flash某地址上进行操作那么就要对地址进行特殊处理。这个处理就是我先把函数传入的地址参数左移一位。例如解锁命令在nor flash地址0x555写入0xaaa。那么cpu最后发送的地址应该就是0xaaa,然后nor flash得到的地址就是0x555。
即为了方便编程函数掺入的地址参数也应该给0X555。那么怎样才能使nor flash读到的地址也为0x555呢?解决办法就是我地址参数addr(0x555)先左移一位变成0xaaa,而后被地址线解法的硬件又移了一位变成了0x555。这样的传入函数的地址就能与nor flash接收到的地址对应起来了,我想在哪个地址读就在哪个地址读。

#define NOR_FALSH_ADDR_BASE		0

nor_cmd(0x555, 0xaa);    /* 解锁 */

/*调用下面函数*/

/* offset是基于NOR的角度看到 */
void nor_cmd(unsigned int addr, unsigned int cmd)
{
	nor_write_word(addr, cmd);
}


void nor_write_word( unsigned int addr, unsigned int val)
{
	volatile unsigned short *p = (volatile unsigned short *)(NOR_FALSH_ADDR_BASE + (addr<< 1));
	*p = val;	/*这里发出地址,写入数据*/
}
	我们这里nor_cmd()函数传入的地址是0x555,最终cmd数据写入的地址是addr经过左移一位得到的0xaaa,然后nor flash接收到的就是0x555.

**问题来了,在后续的nor flash某扇区擦除、某地址读和写的时候都没有对地址进行左移处理,而且程序写完烧写后实验能得到正确的数据,这是为什么呢?
下图为读数据没有进行地址左移时,编译烧写后用串口读nor flash 0x40地址与对应的烧写在norflash bin文件的对比结果:

在这里插入图片描述

	我一直倔强的觉得有问题,应该要左移处理。于是我对读某地址对应的的数据的函数中的地址参数也进行了左移处理,发现结果刚好相差了一个左移的一位的数据。**

代码:

void do_read_nor_flash(void)
{
	unsigned int addr;
	volatile unsigned char *p;
	int i, j;
	unsigned char c;
	unsigned char str[16];
	
	/* 获得地址 */
	printf("Enter the address to read: ");
	addr = get_uint();

	p = (volatile unsigned char *)(addr<<1);		/*地址左移处理*/

	printf("Data : \n\r");
	/* 长度固定为64 */
	for (i = 0; i < 4; i++)
	{
		/* 每行打印16个数据 */
		for (j = 0; j < 16; j++)
		{
			/* 先打印数值 */
			c = *p++;
			str[j] = c;
			printf("%02x ", c);
		}

		printf("   ; ");

		for (j = 0; j < 16; j++)
		{
			/* 后打印字符 */
			if (str[j] < 0x20 || str[j] > 0x7e)  /* 不可视字符 */
				putchar('.');
			else
				putchar(str[j]);
		}
		printf("\n\r");
	}

烧写进开发板用串口工具调试对0x40进行读写,然后把结果与烧写在nor flash的bin文件作对比:

在这里插入图片描述


串口读nor flash地址为0x40的数据得到的却是0x80的数据,刚好是0x40左移一位后地址上的数据,这到底是怎么回事呢?
问题:
为什么执行nor flash解锁和读芯片ID等对应命令时函数传入的地址需要左移一位,而往nor flash对应扇区地址擦书、读、写数据是时函数对应的地址却不需要左移一位呢?如果左移却发现读到的数据不正确?

问题解答:

下面引入另一段相关知识:
我们知道nor flash可以像内存一样读,而且在s3c2440里面是统一编址的。那么我需要访问那个地址上的数据都是站在cpu的角度看的。(nor flash启动时nor flash的基地址对应 s3c2440 的0地址)
我们这里用到的nor flash是16位宽的,最小单元是2byte,所以它认为它自己是1M * 16bit的。所以它每次发送给cpu的数据是16位的。

而s3c2440 cpu访问的最小单元是byte,它每次读写数据都是8bit,在它眼里我们的NOR FLASH是2M * 8bit。
因为这里的不同而又为了能够正常准确的读写nor flash上的数据从而对他们的地址线的接法做出了要求。
在s3c2440芯片手册上可以找到如下图:

在这里插入图片描述


上图的示意和我们上面的硬件原理图的地址线错位接法是一致的,所以这种错位接法并不是硬件设计人员自己随意这么接的,是为了能工准确的操作不同位宽的nor flash硬件由nor falsh型号和cpu决定的。

其他的几种位宽或多个flash的地址线接法:

在这里插入图片描述


在这里插入图片描述

那么要怎样才能读写数据呢?
如图:

在这里插入图片描述


s3c2440 cpu访问的最小单元是byte,而16bit位宽的nor flash每个地址对应位16bit的数据,这16bit的数据相当于两个8bit的数据(高8bit数据和低8bit的数两个部分),cpu需要读出某个地址的数据时(8bit),cpu发出一份地址,nor flash得到的地址是相对于cpu发出的地址右移一位以后的地址,然后norflash会把该norf lash接收到的地址上对应的16bit数据发送给cpu。但是cpu只需要8bit的怎么办呢?这时候soc的memory controller会自己根据cpu的发送的地址来挑选出来其中的8bit给cpu。
例如(如上图):
cpu需要读0x03上的数据,这个地址由cpu发送出去,nor flash接收到的地址就是0x01,在这里cpu的本意是要读取nor flash上的第三个8bit的数据,而这个8bit数据正好为位于nor flash的0x01处。同时这种nor flash与cpu地址线的连接方法使nor flash接收的地址也正好为0x01。所以这时候nor flash将0x01上的16bit数据发送给soc的memory controller,然后memory controller根据cpu所给的地址0x03挑选出这16bit的数据中的高8bit发送给cpu,到此cpu成功得到它想要的8bit数据。

再例如
cpu需要读0x02上的数据,这个地址由cpu发送出去,nor flash接收到的地址也是0x01,在这里cpu的本意是要读取nor flash上的第2个8bit的数据,而这个8bit数据正好为位于nor flash的0x01处。同时这种nor flash与cpu地址线的连接方法使nor flash接收的地址也正好为0x01。所以这时候nor flash将0x01上的16bit数据发送给soc的memory controller,然后memory controller根据cpu所给的地址0x02挑选出这16bit的数据中的低8bit发送给cpu,到此cpu成功得到它想要的8bit数据。

所以cpu每次读取8bit数据,发送给norflash一个地址,关键在于cpu想要得到nor flash上的第几个8bit数据,而不关心nor flash的具体地址。
而且这种地址线的接法cpu地址对应的容量大小与norf lash对应地址处的容量才能对应上(如,cpu的地址0x10 00008bit 等于‭8388608‬bit,即‭1048576‬ byte,即1024kbyte,即1mb,与之对应的nor flash地址为0x80000,0x8000016bit也等于8,388,608‬bit,即‭1048576‬ byte,即1024kbyte,即1mb)。

总结:由于cpu的位宽和falsh的位宽不同以及flash的个数等原因,而又为了使cpu在每个地址上能够读写对应位宽的数据,所以有了这种地址线错位的接法。也正式这种接法能够使cpu在对应地址能够读写到对应位宽的准确数据,
所以该cpu只关心在第几个8bit上读写到数据,并不关心nor flash到底在哪个地址上读写的数据,又程序函数的地址参数又是站在cpu的角度上的,所以这里擦除、读、写 nor flash数据时并不需要进行地址左移。

那么在写命令和读nor flash ID等参数时必须要进行函数传入的地址参数左移一位呢?

那是因为目标地址是在nor flash的芯片手册上看到的,只有nor flash接收到了相应的准确地址和数据才能执行相应动作,并且比如把ID等读回来,就必须要去nor flash的准确地址读才能读到正确的数据(这里的地址是nor flash本身规定的,所以为了方便使函数传入的地址和nor falsh接收到的的地址一致,要把函数传入的地址参数先进行左移一位,然后由被错位地址线接法右移一位)。

本文图片截自于s3c2440芯片手册或MX29LV800BT/BB芯片手册以及个人手绘,第一次写博客有不足之处还望多多包涵和指教,谢谢。
另外文中使用的register tool工具为本人业余写的小工具,如果有兴趣欢迎去我的主页下载。

下载地址:Register tool v1.04

原文地址:https://blog.csdn.net/qq_28065701/article/details/105652765

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


  译序:JWMediaPlayer是开源的网页使用的Flash播放器。本文采摘于JWPlayer的官方文档,讲解了JWPlayer对于RTMP的使用方法,我们可以从JWPlayer客户端的角度来了解RTMP协议。以下是官方原文:      简介    RTMP(RealTimeMessagingProtocol
    Flash编程原理都是只能将1写为0,而不能将0写成1.所以在Flash编程之前,必须将对应的块擦除,而擦除的过程就是将所有位都写为1的过程,块内的所有字节变为0xFF.因此可以说,编程是将相应位写0的过程,而擦除是将相应位写1的过程,两者的执行过程完全相反.一、Nor和NandFlash
 上传setenvgatewayip192.168.1.1;setenvserverip192.168.1.7;setenvipaddr192.168.1.156;mw.b0x820000000xff0x1000000sfprobe0sfread0x8200000000x1000000tftp0x82000000test.bin0x1000000 下载mw.b82000000ff1000000tftp82000000test.bi
Error:FlashDownloadFailed-"Cortex-M3"出现一般有两种情况:1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HWreset/sysresetReq/Vectreset)默认是AutoDetect,改成SysResetReq即可。2.Jtag模式下,主要是芯片大小选错。Flash->ConfigureFalshTools配置窗口,切换到“Utilities"
jPlayer是一个用于控制和播放mp3文件的jQuery插件。它在后台使用Flash来播放mp3文件,前台播放器外观完全可以使用XHML/CSS自定义。支持:有一点比较好的是,在支持html5的浏览器上会使用html5的标签audio或者video,而不支持的浏览器上使用swf来播放选择需要播放的Mp3文件。播放、暂停
#ifndef__FONTUPD_H__#define__FONTUPD_H__#include"sys.h" //字库信息结构体定义33字节__packedtypedefstruct{u8fontok;//字库存在标志,0XAA,字库正常;其他,字库不存在u32ugbkaddr;//unigbk的地址u32ugbksize;//unigbk的大小u32f12addr;//gbk12地址u32g
ROM(ReadOnlyMemory)和RAM(RandomAccessMemory)指的都是半导体存储器。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,但是访问速度快。典型的RAM就是计算机的内存。RAM有两大类,一种称为静态RAM(StaticRAM/SRAM),SRAM速度非常快,是目前读写最快的存储
JSpc端和移动端实现复制到剪贴板功能实现在网页上复制文本到剪切板,一般是使用JS+Flash结合的方法,网上有很多相关文章介绍。随着HTML5技术的发展,Flash已经在很多场合不适用了,甚至被屏蔽。本文介绍的一款JS插件,实现了纯JS方法复制文本到剪切板。插件名是Clipboard.js,该插件不依
例子:R0=1R1=1R2=10R3=e000ed10R12=0LR=fffffff9(中断返回值)PC=0PSR=60000013或60000016或60000036(Z、C、EXCEPT_NUM:RTC_WKUP_IRQn、EXTI0_IRQn、USART2_IRQn)BFAR=e000ed38(不关心)CFSR=20000(INVSTATE:Invalidstateusagefault thePCvaluestackedf
 内存接口概念首先来分析下操作GPIO控制器和操作UART控制器两者的区别如图是S3C2440是个片上系统,有GPIO控制器(接有GPIO管脚),有串口控制器(接有TXDRXD引脚)配置GPIO控制器相应的寄存器,即可让引脚输出高低电平;配置UART控制器相应的寄存器,即可让引脚输出波形。前者相对简单,类
小编导语:    近几年来,网页游戏成为了游戏界关注的焦点,由于其制作简单,成本低并且收益率较高,因此成为了众多游戏厂商追逐的对象,但是除了商家夸张的炒作宣传外,很少有页游佳作出现。然而,随着Unity3D游戏引擎的出现,网页游戏的3D化成了页游冲出重围的杀手锏,那么在flash网页游戏称
1.指定数组到特定的Flash单元#pragmalocation=0x000FFF00 __rootconstcharFlash_config[]={0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0
继续研究发现,计算机的固件真的很有趣。参考了一些重要的资料,比如http://donovan6000.blogspot.com/2013/06/insyde-bios-modding-advanced-and-power-tabs.html等,对于IDA的使用也了解了一些。最后,总结一下目前看来可行性的方案:0.基础知识储备,包括UEFIBIOS的概念,InsydeBIOS的
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>navigator对象<itle></head><body><buttononclick="checkFlash()">检测</button>
修改网上流传的flash-marker.js(function(global,factory){typeofexports==='object'&&typeofmodule!=='undefined'?module.exports=factory():typeofdefine==='function'&&define.amd?define(factory
shareObject本地缓存存储位置:win7系统用户到C:\Users\[你的用户名]\AppData\Roaming\Macromedia\FlashPlayer\#SharedObjects\XP或2003用户到:C:\DocumentsandSettings\用户名\ApplicationData\Macromedia\FlashPlayer\#SharedObjects\ ---------------------作者:iteye_
安装谷歌浏览器之后经常遇到Flash崩溃或者浏览器在浏览Flash内容时卡死的情况。在网上查找资料大多都认为应该是浏览器自带的Flash插件工作模式引起的问题,解决方法如下:首先在地址栏输入chrome://plugins/显示浏览器使用的插件。点击右上角的详细信息,可以看到Flash插件为进程外
之前一直使用的W25Q16spiflash都没问题,换了一款W25Q80后发现工作不正常,经过测试,初步定位到问题在于初始化SPI后是否将CS拉高。于是又去查看了一下原厂代码:发现原厂的代码初始化SPI接口时是专门拉高CS的。结论:网上很多代码初始化SPI接口时没有专门拉高CS,对某些型号可能确实
======================================================NANDFlash最小存储单元:写数据操作:通过对控制闸(ControlGate)施加高电压,然后允许源极(SOURCE)和汲极(RRAIN)间的N信道(N-Channel)流入电子,等到电流够强,电子获得足够能量时,便会越过浮置闸(FloatingGate)底下的二氧化硅层(S
安装CnarioPlayer3.8.1.156或其他版本时,有时会出现如下提示:Warning4154.AdobeFlashPlayer13...notcorrectlyinstalled:请前往AdobeFlash网站,并选择下图示的版本下载安装: