图2 程序存储器Nor 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。便是一个“欺上瞒下”的进程。