加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Z-STACK之cc2530 flash驱动详解下

发布时间:2020-12-15 18:13:59 所属栏目:百科 来源:网络整理
导读:???? 今天来分析一下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_L

???? 今天来分析一下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_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);
? // 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);

? 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驱动在

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.
Therefore,the program code executing the flash write must be executed from RAM.

CPU不能直接访问flash来读取程序代码,但是可以进行写flash操作!执行flash write的程序代码必须在RAM中执行!当然这是针对flash-write operation的第二种方法!如果我们用第一种方法,即DMA传输,我们先看一下流程图:

?????????????????????????????????????????????????????????????????????????????????????????????

DMA描述符的配置过程具体就不说了!看代码

?FADDRL = (uint8)addr;
? FADDRH = (uint8)(addr >> 8);
? HalFlashWriteTrigger();

将地址赋值给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 )
? {
??? HalFlashWrite(offset,buf,1);
? }
? else
? {
??? 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,我们通过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)
{
? FADDRH = pg * (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE / 256);
? FCTL |= 0x01;
}

这个函数较为简单,根据datasheet

?

????????????????????? while(FCTL & 0X80) 一句可以不要!? 事实上在write flash时,要求先将该page erase,然后再写入值!这个原因可以在datasheet中找到!

?

????????? Z-STACK中的flash驱动主要是提供给OSAL_Nv,zigbee需要将IEEE地址或某些信息永久存储在flash中,所以就 非易失性 存储!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读