为何写flash的时候要地址左移一位?


代码一:
#define Writeflash(addr,dat) *((volatile INT16U *)(addr<<1))=(INT16U)dat
#define Readflash(addr) (*((volatile INT16U *)(addr<<1)))
/*addr为读写操作的半字地址,data则为要写入的半字数据。因为ARM处理器是以字节为单位
进行数据处理的,而SST39VF160是16位数据宽度,所以,addr地址必须左移1位。*/

代码二:
//擦除是否为空
int SST39VF160_CheckBlank(INT32U addr,INT32U WordSize)
{
INT32U i,temp;
for (i=addr;i<(addr+WordSize);i++)
{
temp=*((volatile INT16U *)(i<<1)); //地址左移一位,也就得到16位的数据了。
if(temp!=0xffff) //因为扇区被擦除后,扇区的各位都是1.所以判断temp是否等于0xffff //0xffff
return 0; //如果扇区的各个地址都不为0xffff;则返回0
}
return 1;
}
在网上看到这么一段话,我琢磨不透。“S3C44B0X是按照字节编址的,而Flash ROM是以16位为一个存储单元”是怎样推出要“偏移一位”呢?代码一的注释和上一段一样,也没有给出是如何推导出来的。而且代码二中的下面这行代码的注释更是让我不解。前面的i被定义成INT32U 型,怎么通过左移一位就可以得到16的数据呢?恳请各位大侠给出较为详细的解释.
temp=*((volatile INT16U *)(i<<1)); //地址左移一位,也就得到16位的数据了。

解答:
关于那个错位,我不知道能不能跟你说清楚。首先,SST39VF16 FLASH是16位的,也就是以两个字节(半字)为最小操作单位的。也就是说你在FLASH地址上给0x00000,则它给出的数据是第一个16位的半字;在FLASH地址上给0x00001,它给出的是第二个16位的半字;在FLASH地址上给0x00002,它给出的是第三个16位的半字。。。但ARM的地址是以字节编址的,它可以以字节单位来读取或者写外设。
假设我们要读取FLASH的第一个字节,LDRB R0,[R1];将R1内容写0x00000,这个时候ARM执行的是这样的操作:
1、送出地址0x00000
2、在D0-D15上读取数据
3、将读到的16位数据的低8位给R0低8位(高24位为0)

假设我们要读取FLASH的第二个字节,LDRB R0,[R1];将R1内容写0x00001,
这个时候ARM执行的是这样的操作:
1、送出地址ox00001
2、在D0-D15上读取数据
3、将读到的16位数据的高8位给R0的低8位(高24位为0)

从上面的操作可以看到,如果我们一一对应的将ARM和FLASH得地址连接,那么我们想读FLASH的第2个字节的话,就没有办法读到了。因为你地址给0x00001,FLASH就在数据线上给的是第3个字节和第4个字节的数据,并将高8位(FLASH的第4个字节)给R0;如果你给的地址是0x00000的话,ARM的理解就是将数据线D0-D15的低8位给R0,显然这个16位的数据是FLASH的第1个字节和第2个字节的数据,低8位指的就是第一个自己的数据。显然怎么也读不到FLASH的第2个数据。
我们既要遵循ARM的规则,又要让FLASH给我们正确的数据。你自己想应该怎么办?很简单,把ARM给的地址最低位剪掉,把剩下的给FLASH。要读第2个字节,还是送0x00001,但是最后的1被剪掉了,FLASH得到的地址是ox00000,显然给出的数据是第1个和第二个字节。而ARM觉得送出的地址是0x00001啊,应该把高地址给R0啊,即把第2个字节给了R0。就是一个“欺上瞒下”的过程。
时间: 2024-09-23 22:10:16

为何写flash的时候要地址左移一位?的相关文章

flash-NXP单片机写Flash的问题

问题描述 NXP单片机写Flash的问题 写Flash函数 for(writelen=0;writelen<_get_file_size(fileHd);) { uiLen = OSFileRead(GpcBufFileRead, sizeof(GpcBufFileRead), fileHd); /* 读出文件 */ dstaddr = (uint32_t)(APP_START_ADDR + writelen);//dst address. RamToFlash(dstaddr,(uint32_

u盘-U盘host可以升级了,现在是我写flash的时候是按bin文件大小来写的,每次改变bin文件

问题描述 U盘host可以升级了,现在是我写flash的时候是按bin文件大小来写的,每次改变bin文件 U盘host可以升级了,现在是我写flash的时候是按bin文件大小来写的,每次改变bin文件这个程序里面748是bin文件字节大小,就要程序里面改他大小,能不能自动获取文件大小或者怎么写flash OSFileSeek(fileHd, 0, SEEK_SET); /* 文件指针移到文件末尾 / for(writelen=0;writelen<748;) { uiLen = OSFileRe

wwinfrom 为Url写一个正则表达式 要求输入地址做判断

问题描述 wwinfrom 为Url写一个正则表达式 要求输入地址做判断 在一个文本框内要求 输入一个地址 要求可以这样 http://www.xxx.com http://www.xxx.cn http://192.168.xx.xx/load/xxx.html 解决方案 http://[a-zA-Z.0-9/-_]+ 解决方案二: 一个URL正则表达式

补码转原码(算术左移一位负变正)

一.文章来由 还是上一篇关于移位的问题,那么什么 int 型数只算术左移一位就可以从负数变成正数??? 二.又谈补码 很早之前写过一篇关于补码的文章,但是长时间不看又差不多忘记了,翻出来看发现写的挺烂的,有点没说明白,所以希望这里能说明白~~ 关于补码,我们知道: 在计算机中,一切的一切都是用补码存储 打一个比喻,东西在计算机中是用各种编码存储,不论是字符还是指针(指针也是存储的数据),都是用补码存储.我们写的代码相当于是一个外文的说明书,而编译器是翻译器,将我们的说明书翻译告诉机器如何解读那些

oracle-ORACLE怎么写先排序后分组的前5位

问题描述 ORACLE怎么写先排序后分组的前5位 select * from (select a.*, row_number() over(partition by ordered order by cdate desc) px from (select a.*, b.user_name username from view_hjzx a, gjjx.sys_users b where a.userid = b.userid(+) and a.HANDSET like '%15901054535

c语言-问题:输入一个错位后的字符串,输出打字员本来想打出的句子。(将输入的字母在键盘上左移一位)

问题描述 问题:输入一个错位后的字符串,输出打字员本来想打出的句子.(将输入的字母在键盘上左移一位) #include char *s = "1234567890-=QWERTYUIOP[]ASDFGHJKL;'ZXCVBNM,./"; int main() { int i, c; while ((c = getchar()) != EOF) { for (i = 1; s[i] && s[i] != c; i++); { if (s[i]) putchar(s[i -

我用批处理写的windows服务启动不了哪位大神知道怎么解决不

问题描述 我用批处理写的windows服务启动不了哪位大神知道怎么解决不,提示本地计算机上的服务启动后停止.某些服务在未由其他服务或程序使用时将自动停止 解决方案 解决方案二:你试试手动启动指定的服务解决方案三:应该是你的服务报错了啊,加一些诊断log看看------------------------------------------------------------------------------------------------解决方案四:记录你的程序执行了哪些步骤的程序之后才跳

我想用java写一个扫描局域网mac地址的程序!希望大家帮帮忙谢谢

问题描述 就是给IP段,扫描MAC地址,希望各位大侠帮帮我!谢了 解决方案 解决方案二:你想干嘛?解决方案三:给你提供一个方法,经测试可以使用的,如果有一定的基础肯定能看懂,无注释,不解释packagetools;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.LineNumberReader;publicclassMacAddressSearcher{publicstaticStringgetMac

在域的选择公式中写啥公式获取服务器地址

问题描述 如题:新手求帮助!!!! 解决方案 解决方案二:B/S,试试这3个字段名作为你的那个域的计算公式,应该有个是你需要的Remote_AddrRemote_HostServer_Name解决方案三:公式的话就@servername解决方案四:引用2楼的回复: 公式的话就@servername 同學習了,謝謝解决方案五:引用2楼的回复: 公式的话就@servername 同學習了,謝謝解决方案六:B/S的话建立CGI计算域Server_Name就可以拿到help.nsf里TableofCGI