TIMAC 开发随笔 一: CC2530的Flash在线读写
引用请注明出处!!我的邮箱qinxiaoyu@163.com
身处安全设备行业,人员的位置信息是非常重要的。所以,定位设备是解决这类需求的根本。
定位设备有很多种了。地面,可以使用GPS实现定位,误差在1米以内应该是比较容易做到的。但是要是在井下,恐怕卫星信号就很难直达地底了。所以人们就想到了各种定位设备。我现在的公司以前就在做这种设备了,他们使用CEL的ZICM2410模块就解决了这种需求。ZICM2410模块集成了硬连线的MAC层,所以,可以实现CSMA。降低数据的丢包率。
现在,公司打算使用更廉价的CC2530芯片来做原来的方案。于是,我们要接触TIMAC的东西了。
TI公司提供了一系列的解决方案,最简单的电灯程序,点对点发送数据的程序,TIMAC,SimpliciTI Compliant Protocol Stack,ZStack等。
我使用了TIMAC来实现原来的方案,其实就是看中了他的CSMA机制,和它的易用性。
好了,有了前因,我就说说我本章想说的东西,TIMAC的Flash读写的实现。
由于TIMAC已经实现了HAL层,所以!我们也不想做再造轮子的事情了,直接使用就可以了。这里为了方便,我们还是移植了ZStack的OSAL_Nv.c和OSAL_Nv.h过来。
安装ZStack软件包,在安装目录下面直接搜索OSAL_Nv找到.c和.h文件。OSAL_Nv.c复制到\Components\osal\common下面,OSAL_Nv.h复制到\Components\osal\include。在IAR IDE的工程文件Application下add files OSAL_Nv.c。这样就算是把OSAL_Nv导入到工程里了。
分析一下OSAL_Nv.c:
从这些定义就可以知道:
#define HAL_FLASH_PAGE_SIZE 2048 每个page有2k的大小
#define HAL_NV_PAGE_CNT 6 总共使用6个page
#define HAL_NV_PAGE_END 126 最后一个page的id为126 CC2530共有127个page
#define HAL_NV_PAGE_BEG (HAL_NV_PAGE_END-HAL_NV_PAGE_CNT+1) 我们可以使用的起始page
OSAL_Nv还引入了item(条目)的概念,也就是说。我们可以在一个page下面设立多个条目,定义更多的条目,实现更加合理的管理。
看一些最主要的函数,也就是我们一会儿要用到的函数。
void osal_nv_init( void *p ) 初始化NV管理
uint8 osal_nv_item_init( uint16 id, uint16 len, void *buf ) 初始化item
uint8 osal_nv_write( uint16 id, uint16 ndx, uint16 len, void *buf ) 写某page下的某item
uint8 osal_nv_read( uint16 id, uint16 ndx, uint16 len, void *buf ) 读某page下的某item
很可惜,我只想要在flash里面保存一小串数据,总共才8个字节,就不打算写n多的item啦!
第一步:初始化NV
在msa_Main.c的main函数中添加 osal_nv_init(NULL); 如下:
int main(void) { /* Initialize hardware */ HAL_BOARD_INIT(); /* Initialze the HAL driver */ HalDriverInit(); /* Initialize NV System */ osal_nv_init(NULL); /* Initialize MAC */ MAC_Init(); /* Initialize the operating system */ osal_init_system(); /* Enable interrupts */ HAL_ENABLE_INTERRUPTS(); /* Setup Keyboard callback */ HalKeyConfig(MSA_KEY_INT_ENABLED, MSA_Main_KeyCallback); /* Blink LED on startup */ HalLedBlink (HAL_LED_4, 0, 40, 200); /* Start OSAL */ OSAL_START_SYSTEM(); return 0; }
第二步:定义必要参数
#define APP_BUSINESS_NV_LEN 10 #define APP_BUSSINESS_NV_ID 0x0001 //这里一定要小于0x0006
第三步:初始化id
uint8 osal_init_system( void ) { // Initialize the Memory Allocation System osal_mem_init(); // Initialize the message queue osal_qHead = NULL; // Initialize the timers osalTimerInit(); // Initialize the Power Management System osal_pwrmgr_init(); // Initialize the system tasks. osalInitTasks(); AppBusinessNvInit(); <span style="font-family:Microsoft YaHei;">//这是自己定义的函数</span> // Setup efficient search for the first free block of heap. osal_mem_kick(); return ( SUCCESS ); } uint8 AppBusinessNvInit(void) { uint8 status; uint16 size; size = APP_BUSINESS_NV_LEN; status = osal_nv_item_init( APP_BUSSINESS_NV_ID, size, NULL );<span style="font-family:Microsoft YaHei;">//初始化我们定义的page id</span> return status; }
第四步:写Flash
uint8 APP_BUSINESS_DEFAULT_DATA[10] ="111156789X"; DEBUG_APP_BU("APP::AppBusinessSetDefaultNv\r\n"); osal_nv_write( APP_BUSSINESS_NV_ID, 0, APP_BUSINESS_NV_LEN, &APP_BUSINESS_DEFAULT_DATA);
将数据APP_BUSINESS_DEFAULT_DATA中的111156789X写入到APP_BUSSINESS_NV_ID,偏移量为0的地址去,长度为APP_BUSINESS_NV_LEN
第五步:读Flash
void AppBusinessReadFlashData(void) { uint8 APP_BUSINESS_DEFAULT_DATA_temp[10] ="0000000000"; DEBUG_APP_BU("APP::AppBusinessReadDefaultData\r\n"); if(!(osal_nv_read(APP_BUSSINESS_NV_ID,0,APP_BUSINESS_NV_LEN,&APP_BUSINESS_DEFAULT_DATA_temp))) { DEBUG_APP_BU_TYPE("%c",APP_BUSINESS_DEFAULT_DATA_temp,APP_BUSINESS_NV_LEN); } DEBUG_APP_BU("\r\n"); }
从PP_BUSINESS_DEFAULT_DATA位置开始,偏移量为0的位置开始读取数据,读取长度为APP_BUSINESS_NV_LEN,数据保存在APP_BUSINESS_DEFAULT_DATA_temp中。
在按键响应的地方,或者其他的地方调用写Flash的代码,然后再调用读Flash的代码,就可以将数据保存在flash中了。关机后再次开机,直接调用读flash的代码,发现debug出的数据正是"111156789X"。在此,flash的读写就算是写完了。