最近在看CC2530的Flash部分,翻阅一些文章,将记录下来,做为笔记以免遗忘,如有错误之处请指出。
参考文章:
http://www.cfanz.cn/?c=article&a=read&id=173767
http://www.xuebuyuan.com/1035130.html
http://blog.csdn.net/crystal736/article/details/8727111
https://wenku.baidu.com/view/b640309043323968001c925d.html
http://www.xuexila.com/diannao/rumen/607222.html
http://www.cnblogs.com/felixfang/p/3420462.html
一、基础知识
我使用的TI的芯片型号为CC2530-F256,拥有256K的 Flash,8K SRAM,内核为8051,只支持64K访问空间,以下为一些基本概念。
1.CODE. A read-only memory space for program memory. This memory
space addresses 64 KB.
2.DATA. A read/write data memory space that can be directly or indirectly accessed by a single-cycle CPU instruction. This memory space addresses 256 bytes. The lower 128 bytes of the DATA memory space can be addressed either directly or indirectly, the upper 128 bytes only indirectly.
3.XDATA. A read/write data memory space, access to which usually requires 4–5 CPU instruction cycles.This memory space addresses 64 KB. Access to XDATA memory is also slower than DATA access, as the CODE and XDATA memory spaces share a common bus on the CPU core, and instruction
prefetch from CODE can thus not be performed in parallel with XDATA
accesses.
4.SFR. A read/write register memory space which can be directly accessed by a single CPU instruction.This memory space consists of 128 bytes. For SFR registers whose address is divisible by eight, each bit is also individually addressable.
在此处我们只需要记住 DATA和 XDATA 存在 SRAM 上,而 CODE存在 Flash上即可。
二、CC2530中的 Flash 结构
由于CC2530只支持64K寻址,因此,采用 Bank映射的方式寻址,其中,32K作为 ROOT,用于存放启动代码等,地址空间为 0x0000~0x7FFF;剩余32K用于映射不同的 Bank(0~7),地址为0x8000~0xFFFF.在查询某个 Bank 的数据或代码时,将该 Bank映射到地址空间 0x8000 ~ 0xFFFF即可。
通过ZigBee协议栈中的定义
#define HAL_FLASH_PAGE_SIZE 2048
我们可以知道每页page的大小为2K,定义每16个page为1个Bank,下图为Bank与page的关系
Bank地址:
Bank0: 0x00000 ~ 0x07FFFF
Bank1: 0x18000 ~ 0x1FFFFF
Bank2: 0x28000 ~ 0x2FFFFF
Bank3: 0x38000 ~ 0x3FFFFF
Bank4: 0x48000 ~ 0x4FFFFF
Bank5: 0x58000 ~ 0x5FFFFF
Bank6: 0x68000 ~ 0x6FFFFF
Bank7: 0x78000 ~ 0x7FFFFF
三、计算Bank的数据或代码的地址
在计算地址前,首先了解物理地址与逻辑地址的概念,及两者之间的转换公式。
1、物理地址与逻辑地址
物理地址:加载到内存地址寄存器中的地址,内存单元的真正地址。在前端总线上传输的内存地址都是物理内存地址,编号从0开始一直到可用物理内存的最高端。这些数字被北桥(Nortbridge chip)映射到实际的内存条上。物理地址是明确的、最终用在总线上的编号,不必转换,不必分页,也没有特权级检查(no translation, no paging, no privilege checks)。
逻辑地址:CPU所生成的地址。逻辑地址是内部和编程使用的、并不唯一。例如,你在进行C语言指针编程中,可以读取指针变量本身值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址(偏移地址),不和绝对物理地址相干。
2、物理地址与逻辑地址的转换
(1)确定虚拟地址(物理地址)的有效位
例如:假设页面大小1KB,共32页。(页面:逻辑地址 页框:物理地址)
由32(KB)=32×1024(B) 即等于32×1024 字节
二进制用多少位能有效表示这么多字节呢?
答案是:15位 因为32×102 4=2^5×2^10=2^15
(2)再次确定逻辑地址页面位数 你应该知道:逻辑地址=页号+页面
还是以上假设,那么页面大小为1KB=1024字节 同样的方法计算出表示位数:10位
如果给你逻辑地址:0000 1111 1000 0000
那么由:011+11100000000(相当于 页号+页面(10位))推得出页号011=3
(3)根据页号找出对应的页框号
由 物理地址=页框号×页块大小(页块大小是等于页面大小的)+页内位移(即页面逻辑地址)//物理地址=块的大小(即页的大小L)*块号f+页内地址d
根据上面 物理地址=页框号×1024B + 1110000000 ( 这里的相加是指位置上而言)
例如:110+110=110110(即高地址+低地址)
有了以上的知识,我们来看一看CC2530的Flash的读写是怎样通过逻辑地址找到物理地址的
void HalFlashRead(uint8 pg, uint16 offset, uint8 *buf, uint16 cnt)
{
..............
// Calculate the offset into the containing flash bank as it gets
mapped into XDATA.
uint8 ptr = (uint8 )(offset + HAL_FLASH_PAGE_MAP) +
((pg % HAL_FLASH_PAGE_PER_BANK) * HAL_FLASH_PAGE_SIZE);
.............
}
ptr为物理地址,offset为偏移量, pg为页数
#define HAL_FLASH_PAGE_MAP 0x8000
#define HAL_FLASH_PAGE_PER_BANK 16
#define HAL_FLASH_PAGE_SIZE 2048
假如我们要读某一page中的数据,那么我们必须先把这个page所在的
bank映射到XDATA的0x8000~0xFFFF中,我们读取page值为100,偏移量为20的数据时,这个地址通过上面的表达式就很容易计算出来为20+0x8000+(100%16)2024 = 0x9FB4,注意这个地址转换成了(uint8 ),即为XDATA空间的地址。
pg /= HAL_FLASH_PAGE_PER_BANK;
计算page所在的bank,如果pg为100,则其所在bank值为100/16= 6
MEMCTR = (MEMCTR & 0xF8) | pg;
这句是将刚才计算所得的bank映射到XDATA的0x8000~0xFFFF中去,
MEMCTR的低三位为XDATA的bank选择位
四、其他地址
1、IEEE
-D_IEEE_ADDRESS_SPACE_START=(((_NR_OF_BANKS+1)*_FIRST_BANK_ADDR)-0x18)
-D_IEEE_ADDRESS_SPACE_END=(_IEEE_ADDRESS_SPACE_START+7)
-Z(CODE)IEEE_ADDRESS_SPACE=_IEEE_ADDRESS_SPACE_START-_IEEE_ADDRESS_SPACE_END
注:0x18 = 24 = 16 +8;
_IEEE_ADDRESS_SPACE_START容易算出来,_NR_OF_BANKS值为0x07,_FIRST_BANK_ADDR值为0x8000,这些值是在options...里面设置的。所以_IEEE_ADDRESS_SPACE_START的值为0x40000 - 0x18 = 0x3FFE8,_IEEE_ADDRESS_SPACE_END值就为0x3FFE8+7 = 0x3FFEF。
(备注:每2kb(1page)的flash有1bit的lock位)
2、NV
Z-STACK将flash的最末处的12KB(6page)用来作为Nv存储的,具体看:
-D_ZIGNV_ADDRESS_SPACE_START=(((_NR_OF_BANKS+1)*_FIRST_BANK_ADDR)-0x3800)
-D_ZIGNV_ADDRESS_SPACE_END=(_ZIGNV_ADDRESS_SPACE_START+0x2FFF)
-Z(CODE)ZIGNV_ADDRESS_SPACE=_ZIGNV_ADDRESS_SPACE_START-_ZIGNV_ADDRESS_SPACE_END