Z-STACK之cc2530 flash驱动详解上
?????? 有一段时间没有碰Z-STACK了,有点生疏,不过没关系!我们继续Z-STACK的驱动之旅!今天着重分析一下 z-stack的flash驱动。在分析flash驱动之前,需要熟读cc2530的datasheet关于flash controller那一章节! 我们先从hal_flash.c文件中的HalFlashRead函数开始: void HalFlashRead(uint8 pg,uint16 offset,uint8 *buf,uint16 cnt) #if !defined HAL_OAD_BOOT_CODE ? pg /= HAL_FLASH_PAGE_PER_BANK;? // Calculate the flash bank from the flash page. #if !defined HAL_OAD_BOOT_CODE ? // Calculate and map the containing flash bank into XDATA. ? while (cnt--) ? MEMCTR = memctr; #if !defined HAL_OAD_BOOT_CODE ?在讲解这个函数之前,先说一下z-stack中对flash的布局。z-stack将256KBflash的最末八个字节作为zigbee中的IEEE地址,当然在这八个字节之后还有16个字节lock bits,这些flash的lock所需要用的,每2kb(1page)的flash有1bit的lock位,那么256kb的flash有128个2kb,当然也就有128(16X8)位的lock bits了。从F8w2530.xcl文件中可以看出: -D_IEEE_ADDRESS_SPACE_START=(((_NR_OF_BANKS+1)*_FIRST_BANK_ADDR)-0x18) 注: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。 ? Z-STACK将flash的最末处的12KB(6page)用来作为Nv存储的,具体看: -D_ZIGNV_ADDRESS_SPACE_START=(((_NR_OF_BANKS+1)*_FIRST_BANK_ADDR)-0x3800) 我们知道0x3800为7个page即14KB,0x2FFF为6个page,则Z-STACK将最末的7个page的前6个page用来作为Nv存储,最后一个page用来存储其他信息,如IEEE地址。 ? 好!我们接下来看这个函数。 uint8 *ptr = (uint8 *)(offset + HAL_FLASH_PAGE_MAP) + 首先计算了这个地址映射到XDATA中之后的值,HAL_FLASH_PAGE_MAP为0X8000,HAL_FLASH_PAGE_PER_BANK值为16,HAL_FLASH_PAGE_SIZE值为2024即2KB,这个计算很显然了。 z-stack中的page是从0开始的,一直到127,总共128page,假如我们要读某一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选择位 ? ?while (cnt--) 很明显,将ptr指针指向的数据复制到buf指针所指向的地址去,这个buf和ptr变量是在运行时堆栈上的,只不过是将数据从XDATA的一个地放复制到sram中某个地方! ? 那么这个函数的最用就很明显了:它是将flash内部的某个page,相对其偏移量为offet地址处的数据,读取cnt个字节到buf中去。 ? 接下来看看HalFlashInit这个函数: void HalFlashInit(void) } 这个flash初始化函数直接调用了HalFlashRead函数,我们看看这几个实参数据,PAGE_OF_RAM_CODE值为51,OSET_OF_RAM_CODE值为0x6DD,SIZE_OF_RAM_CODE为0x23,ramCode为: #pragma location="RAM_CODE_XDATA" 这个ramCode是不能初始化的静态数组 这个ramCode是在RAM_CODE_XDATAsegment,打开F8w2530.xcl文件: -D_RAM_CODE_XDATA_START=0x01EDD 很明显RAM_CODE_XDATA这段范围是8kb的sram中最末的23个字节, 那么这个初始化函数的作用就是将flash中23个字节的代码加载到ram去运行。那么这个有什么用途呢?而且为什么是23字节呢?看到这个注释, Any code that will be run from RAM by setting XMAP of MEMCTL must have the same bank-relative ? 这时候我们看到这几句: #pragma location="RAM_CODE_FLASH" __monitor表示此函数不能被中断!这个函数的位置就是在RAM_CODE_FLASH处, -Z(CODE)RAM_CODE_FLASH=_RAM_CODE_FLASH_START-_RAM_CODE_FLASH_END -D_RAM_CODE_FLASH_START=0x39EDD 这个表示的code段RAM_CODE_FLASH范围,为0x39EDD~0x39EFF,这个跟之前的那个51page,0x6DD是什么关系呢?我们先看这个地址值出在什么位置,51page出在第三个bank里(注意bank是从0开始起的),那么将其映射到code memory(64KB)中就是在32KB+3page+0x6DD处,记住code空间的第一个为root bank,接着我们将 39EDD映射到code空间中,其bank为7,其值为115page+0x6DD(注意page也是从0开始的),16page为1个bank,映射之后再code中的值为32KB+3page+0x6DD,看到了吗? ? 这两个值在映射之后竟然为同一地址,而且这一地址都是在switch bank的开始8kb末端23字节处!这说明什么呢? ? 而且,从上面代码看出,这23个字节存储的就是HalFlashWriteTrigger这个函数的实现代码,不信反汇编代码去看看,这个函数代码就是23个字节。 ? 那么在系统初始化flash的时候,0x39DEE映射到code空间,flash控制器将这23个字节的函数代码复制到sram(8KB)的末端23字节的地址处,这样当系统执行这个函数时,将这8KBsram映射到code空间的0x8000~ 0x8000+sram_size-1,cpu就在sram中执行这个函数,很显然,速度是超快的!那么正好这个函数要求不能被中断,那么它最好是越快越好!当然就把它放在sram中执行啦~ ?flash驱动先分析到这!下章介绍flash write函数! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |