Z-STACK之cc2530 flash驱动详解下
???? 今天来分析一下flash的write函数: void HalFlashWrite(uint16 addr,uint8 *buf,uint16 cnt) ? HAL_DMA_SET_SOURCE(ch,buf); ? FADDRL = (uint8)addr; 这个函数的功能就是向flash内部的addr地址处写cnt个字节的buf内容。 我们知道flash-write operation 有两种方法: Using DMA transfer (preferred method) Using CPU,running code from SRAM 肯定DMA是首选!DMA驱动在 http://www.voidcn.com/article/p-wqbsrscv-kq.html中已讲的非常清楚了! 注意一点 DMA控制器传输的数据都是在XDATA地址空间范围内的,当然它可以存储在ram中也可以存储在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. CPU不能直接访问flash来读取程序代码,但是可以进行写flash操作!执行flash write的程序代码必须在RAM中执行!当然这是针对flash-write operation的第二种方法!如果我们用第一种方法,即DMA传输,我们先看一下流程图: ????????????????????????????????????????????????????????????????????????????????????????????? DMA描述符的配置过程具体就不说了!看代码 ?FADDRL = (uint8)addr; 将地址赋值给FADDRL:FADDRH,这个addr是16位的,但是如果我们想往地址0x3FFEE地址写数据,那岂不是写不了?这里为什么是16位的地址呢? 其实,我们在写flash之前都已经将要写的地址映射到了XDATA空间的XBANK区了! ? 我们先来看一下这个HalFlashWrite函数用在哪些地方! 找到OSAL_Nv.c文件中有一两个函数调用了HalFlashWrite,分别是 static void writeWord( uint8 pg,uint16 offset,uint8 *buf ) static void writeWordM( uint8 pg,uint16 cnt ) 这两个函数其实对HalFlashWrite的封装。我们可以对照一下HalFlashRead函数的声明: void HalFlashRead(uint8 pg,uint16 cnt) 他们的返回值和参数都是一样的! ? 我们看下函数writeWord的代码 ? offset = (offset >> 2) + ((uint16)pg << 9); ? if ( OSAL_NV_CHECK_BUS_VOLTAGE ) ? 这里为我们计算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,我们通过flash controller访问flash时,看到的地址都是0x0000 0x0004 0x0008..............即末位都是4的倍数的值, ((uint16)pg << 9)即将pg乘以2KB再除以4,这个表达式相当于 ?offset = (offset?+ pg×2KB)/4,分子为pg,offset的真正地址,然后将其除以4,然后调用 HalFlashWrite(offset,1);对应参数为,addr = offset,buf = buf, cnt = 1; 所以执行HalFlashWrite,向offset地址处写4个字节 我们看到有这么一句注释: @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 & 0xF8) | 0x01; 它将bank1 映射到XDATA中,即将这部分flash当做data使用!,但是好像我们不都是在bank1中写数据, That is a problem! ? 实际上,在程序执行的时候,是不允许write flash的,因为这样会破坏flash中的code,所以cc2530就想了个办法,当需要write flash时,将执行write flash的函数代码复制到sram中,然后从sram中执行这个函数,这样write flash 就得以进行!在这个http://e2e.ti.com/support/low_power_rf/f/155/t/231885.aspx里面解释了原因! ? 所以在上篇文章中提到的HalFlashWriteTrigger函数就是那个执行write flash的函数,在flash初始化的时候,复制到sram中,然后将sram映射到code空间中,CPU从sram中执行HalFlashWriteTrigger,进行write flash,当write complete时,此函数返回,同样sram switch back to XDATA,CPU继续执行code空间中的代码。 ? 以上的两个问题还没完全弄明白!可能哪儿理解还不到位! 最后是flash erase , void HalFlashErase(uint8 pg) 这个函数较为简单,根据datasheet ? ????????????????????? while(FCTL & 0X80) 一句可以不要!? 事实上在write flash时,要求先将该page erase,然后再写入值!这个原因可以在datasheet中找到! ? ????????? Z-STACK中的flash驱动主要是提供给OSAL_Nv,zigbee需要将IEEE地址或某些信息永久存储在flash中,所以就 非易失性 存储! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |