版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、z-stack的flash驱动。在分析flash驱动之前,需要熟读cc2530的datasheet关于flash controller那一章节!我们先从hal_flash.c文件中的HalFlashRead函数开始: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
2、 + HAL_FLASH_PAGE_MAP) + (pg % HAL_FLASH_PAGE_PER_BANK) * HAL_FLASH_PAGE_SIZE); uint8 memctr = MEMCTR; / Save to restore.#if !defined HAL_OAD_BOOT_CODE halIntState_t is;#endif pg /= HAL_FLASH_
3、PAGE_PER_BANK; / Calculate the flash bank from the flash page.#if !defined HAL_OAD_BOOT_CODE HAL_ENTER_CRITICAL_SECTION(is);#endif / Calculate and map the containing flash bank into XDATA. MEMCTR = (MEMCTR & 0xF8) | pg; while (cnt-) *buf+ =
4、*ptr+; MEMCTR = memctr;#if !defined HAL_OAD_BOOT_CODE HAL_EXIT_CRITICAL_SECTION(is);#endif 在讲解这个函数之前,先说一下z-stack中对flash的布局。z-stack将256KBflash的最末八个字节作为zigbee中的IEEE地址,当然在这八个字节之后还有16个字节lock bits,这些flash的lock所需要用的,每2kb(1page)的flash有1bit的lock位,那么256kb的flash有128个2kb,当然也就有128(16X8)位
5、的lock bits了。从F8w2530.xcl文件中可以看出:-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
6、,_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)-D_ZIGNV_ADDRESS_SPACE_END=(_ZIGNV
7、_ADDRESS_SPACE_START+0x2FFF)-Z(CODE)ZIGNV_ADDRESS_SPACE=_ZIGNV_ADDRESS_SPACE_START-_ZIGNV_ADDRESS_SPACE_END我们知道0x3800为7个page即14KB,0x2FFF为6个page,则Z-STACK将最末的7个page的前6个page用来作为Nv存储,最后一个page用来存储其他信息,如IEEE地址。 好!我们接下来看这个函数。uint8 *ptr = (uint8 *)(offset + HAL_FLASH_PAGE_MAP) +
8、 (pg % HAL_FLASH_PAGE_PER_BANK) * HAL_FLASH_PAGE_SIZE);首先计算了这个地址映射到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所
9、在的bank映射到XDATA的0x80000xFFFF中,我们读取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的0x80000xFFFF中去,M
10、EMCTR的低三位为XDATA的bank选择位 while (cnt-) *buf+ = *ptr+; 很明显,将ptr指针指向的数据复制到buf指针所指向的地址去,这个buf和ptr变量是在运行时堆栈上的,只不过是将数据从XDATA的一个地放复制到sram中某个地方! 那么这个函数的最用就很明显了:它是将flash内部的某个page,相对其偏移量为offet地址处的数据,读取cnt个字节到buf中去。 接下来看看HalFlashInit这个函数:void HalFlashInit(void
11、) / Load the code to run from RAM into its reserved area of RAM once at startup. HalFlashRead(PAGE_OF_RAM_CODE, OSET_OF_RAM_CODE, ramCode, SIZE_OF_RAM_CODE);这个flash初始化函数直接调用了HalFlashRead函数,我们看看这几个实参数据,PAGE_OF_RAM_CODE值为51,OSET_OF_RAM_CODE值为0x6DD,SIZE_OF_RAM_CODE为0x23,ramCode为:#pragma loc
12、ation="RAM_CODE_XDATA"static _no_init uint8 ramCodeSIZE_OF_RAM_CODE;这个ramCode是不能初始化的静态数组这个ramCode是在RAM_CODE_XDATAsegment,打开F8w2530.xcl文件:-D_RAM_CODE_XDATA_START=0x01EDD-D_RAM_CODE_XDATA_END=(_RAM_CODE_XDATA_START+0x22)-Z(XDATA)RAM_CODE_XDATA=_RAM_CODE_XDATA_START-_RAM_CODE_XDATA_END很明显RAM_
13、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 address as the address in RAM to which the CODE will be copied to run. Thus, any part of the f
14、irst 8k of any bank can be dedicated to code that will run from RAM aslong as the corresponding relative address range is reserved in RAM by RAM_CODE_XDATA. 这时候我们看到这几句:#pragma location="RAM_CODE_FLASH"#if defined HAL_OAD_BOOT_CODEstatic void HalFlashWriteTrigger(void);#elsestatic _mon
15、itor void HalFlashWriteTrigger(void);#endif_monitor表示此函数不能被中断!这个函数的位置就是在RAM_CODE_FLASH处,-Z(CODE)RAM_CODE_FLASH=_RAM_CODE_FLASH_START-_RAM_CODE_FLASH_END-D_RAM_CODE_FLASH_START=0x39EDD-D_RAM_CODE_FLASH_END=(_RAM_CODE_FLASH_START+0x22)这个表示的code段RAM_CODE_FLASH范围,为0x39EDD0x39EFF,这个跟之前的那个51page,0x6DD是什么关
16、系呢?我们先看这个地址值出在什么位置,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字节处!这说明什么呢?
17、而且,从上面代码看出,这23个字节存储的就是HalFlashWriteTrigger这个函数的实现代码,不信反汇编代码去看看,这个函数代码就是23个字节。 那么在系统初始化flash的时候,0x39DEE映射到code空间,flash控制器将这23个字节的函数代码复制到sram(8KB)的末端23字节的地址处,这样当系统执行这个函数时,将这8KBsram映射到code空间的0x80000x8000+sram_size-1,cpu就在sram中执行这个函数,很显然,速度是超快的!那么正好这个函数要求不能被中断,那么它最好是越快越好!当然就把它放在sram中执行啦 flash驱
18、动先分析到这!下章介绍flash write函数! 今天来分析一下flash的write函数:void HalFlashWrite(uint16 addr, uint8 *buf, uint16 cnt) halDMADesc_t *ch = HAL_NV_DMA_GET_DESC(); HAL_DMA_SET_SOURCE(ch, buf); HAL_DMA_SET_DEST(ch, &FWDATA); HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN); HAL_DMA_SET_
19、LEN(ch, (cnt * HAL_FLASH_WORD_SIZE); HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE); HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE); HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_FLASH); HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1); HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
20、60; / The DMA is to be polled and shall not issue an IRQ upon completion. HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE); HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS); HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH); HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH); HAL_DMA_ARM_CH(HAL_NV_DMA_CH
21、); FADDRL = (uint8)addr; FADDRH = (uint8)(addr >> 8); HalFlashWriteTrigger();这个函数的功能就是向flash内部的addr地址处写cnt个字节的buf内容。我们知道flash-write operation 有两种方法:Using DMA transfer (preferred method)Using CPU, running code from SRAM肯定DMA是首选!DMA驱动在注意一点 DMA控制器传输的数据都是在XDATA地址空间范围内的,当然它可以存储在ra
22、m中也可以存储在flash中!只不过他们都必须映射到XDATA空间中!The DMA controller controls data transfers over the entire address range in XDATA memory space看到datasheet有这样几句:The CPU cannot access the flash, e.g., to read program code, while a flash write operation is in progress.Therefore, the program code executing the flash
23、write must be executed from RAM.CPU不能直接访问flash来读取程序代码,但是可以进行写flash操作!执行flash write的程序代码必须在RAM中执行!当然这是针对flash-write operation的第二种方法!如果我们用第一种方法,即DMA传输,我们先看一下流程图:
24、60;
25、60; DMA描述符的配置过程具体就不说了!看代码 FADDRL = (uint8)addr; FADDRH = (uint8)(addr >> 8); HalFlashWriteTrigger();将地址赋值给FADDRL:FADDRH,这个addr是16位的,但是如果我们想往地址0x3FFEE地址写数据,那岂不是写不了?这
26、里为什么是16位的地址呢?其实,我们在写flash之前都已经将要写的地址映射到了XDATA空间的XBANK区了! 我们先来看一下这个HalFlashWrite函数用在哪些地方!找到OSAL_Nv.c文件中有一两个函数调用了HalFlashWrite,分别是static void writeWord( uint8 pg, uint16 offset, uint8 *buf )static void writeWordM( uint8 pg, uint16 offset, uint8 *buf, uint16 cnt )这两个函数其实对HalFlashWrite的封装。我们可以对照一下H
27、alFlashRead函数的声明:void HalFlashRead(uint8 pg, uint16 offset, uint8 *buf, uint16 cnt)他们的返回值和参数都是一样的! 我们看下函数writeWord的代码 offset = (offset >> 2) + (uint16)pg << 9); if ( OSAL_NV_CHECK_BUS_VOLTAGE ) HalFlashWrite(offset, buf, 1); else
28、0; failF = TRUE; 这里为我们计算offset即为映射之后的地址值!这是咋计算出来的呢?假如我们要在121page的 offset为0的地址处写值,注意有这么一句:When accessed by the flash controller, the flash memory is word-addressable, where a word consists of 32 bits. 所以我们write flash时必须指定offset为4的整数倍,要不然会写不进去的!所以有了 offset>>2,即除以4,
29、我们通过flash controller访问flash时,看到的地址都是0x0000 0x0004 0x0008.即末位都是4的倍数的值,(uint16)pg << 9)即将pg乘以2KB再除以4,这个表达式相当于 offset = (offset + pg×2KB)/4,分子为pg,offset的真正地址,然后将其除以4,然后调用HalFlashWrite(offset, buf, 1);对应参数为,addr = offset,buf = buf, cnt = 1;所以执行HalFlashWrite,向offset地址处写4个字节我们看到有这么一句注
30、释:param addr - Valid HAL flash write address: actual addr / 4 and quad-aligned.param cnt - Number of 4-byte blocks to write.实际地址是addr/4,所以要将offset除以4!但是我们知道这个addr的值是XDATA地址空间的地址,我们是往flash中写数据,也就是说在write flash之前,必须将pg所在的bank映射到XBANK中,然后再将buf中数据写到XBANK的flash中!但是找了半天,没有发现执行映射的语句!这一点还没想通!在程序初始化的时候:_low_level_init函数中执行了 MEMCTR = (MEMCTR & 0xF
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度IT项目承建方保密与知识产权保护协议3篇
- 2024版物业服务合同标的调整协议
- 2025年度并购居间保密协议及并购双方信息披露义务约定3篇
- 2024版土地转让及补偿协议
- 2025年度出租车夜间运营承包租赁管理协议范本3篇
- 2025年度新能源储能技术保密协议3篇
- 2025年度三人共同投资风力发电合伙协议3篇
- 《二零二四年度协议离婚申请书编制标准与实例分析》3篇
- 2025年度高端医疗器械加工与临床试验测试服务协议4篇
- 专业护工服务协议模板
- 2025年度土地经营权流转合同补充条款范本
- 南通市2025届高三第一次调研测试(一模)地理试卷(含答案 )
- 2025年上海市闵行区中考数学一模试卷
- 2025中国人民保险集团校园招聘高频重点提升(共500题)附带答案详解
- 0的认识和加、减法(说课稿)-2024-2025学年一年级上册数学人教版(2024)001
- 医院安全生产治本攻坚三年行动实施方案
- 法规解读丨2024新版《突发事件应对法》及其应用案例
- Python试题库(附参考答案)
- 大断面隧道设计技术基本原理
- 41某31层框架结构住宅预算书工程概算表
- 成都市国土资源局关于加强国有建设用地土地用途变更和
评论
0/150
提交评论