MTK优美代码赏析3:nvram存储和读取部分的分析

MTK提供的NVRAM存取方式有两种,一种读取单条数据,一种是读取结构数据.
读取单条数据的比较常见,在mtk代码中随处可以找到例子,主要的接口函数是ReadValue和WriteValue,函数中nDataType参数对应的是
1  typedef  enum      /*  Pixtel Defined enum  */
2  {
3      DS_BYTE  =   1 ,
4      DS_SHORT  =   2 ,
5      DS_DOUBLE  =   8
6  } DATASIZE;  /*  Enum for caching purposes  */

 

一般我的应用中,DS_BYTE 类型我们对应U8来使用,DS_SHORT对应U16,DS_DOUBLE 对应U64,(double的操作可以参考THEME_MANAGER_MAX_THEME_ID)
可根据数据的需求来用不同的类型,参数nDataItemId定义在custom_mmi_default_value.h中,对应不同类型分别放于BYTEDATA,SHORTDATA,DOUBLEDATA中.
  实际工作中我们最常用这种方法存储程序的开关,一般我们会使用DS_BYTE 类型来存储,实则用U8来存储一个0/1的数据太浪费了,所以我们一般要充分利用U8中的每个位,程序上在读出数据后进行位操作即可得到自己想要得数据,存储前的时候也要进行相应位操作后才能进行存储.比如我前面设计的呼吸灯的功能,对于不同情况下的呼吸需要存储开关,速度和效果,我根据数据特征将U8分成三个部分来分别存储,即AABBCCCC,AA开关,BB速度,CCCC效果,将开关设置两位是为了避免nvram存储值为0,不便于对nvram初始值进行判断.
 1  // 开关
 2  typedef  enum
 3  {
 4      SWITCH_NULL, // 增加该项使nvram存储值不为0
 5      SWITCH_ON,    
 6      SWITCH_OFF,
 7      
 8       // add item befor this
 9      RF_UTPLUS_SWITCH_END
10  }utplus_rf_breath_switch;
11  // 从nvram中获取初始化值
12  void  utplus_rf_breath_init_nvram_value( void )
13  {
14      U8 data  =   0 ;
15      U8 i;
16      S16 error;
17       for (i = 0 ;i < RF_UTPLUS_FEATRUE_END;i ++ )
18      {
19          ReadValue(NVRAM_RF_UTPLUS_SETTING_START  +  i  +   1 , & data, DS_BYTE ,  & error);
20          dbg_print( " \r\n UtPlus BreathLED init nvram read  data = %d , \r\n  " ,data);
21           if (data == 0xff ||  data  <   0x40   || error  != NVRAM_READ_SUCCESS)
22          {
23              dbg_print( " UtPlus BreathLED init nvram read err i = %d ,err = %d \r\n  " ,i,error);
24              data  =  ((U8)(ut_g_rfb[i].switch_id) << 6 ) | ( (U8)(ut_g_rfb[i].speed_level)  << 4 ) | ( (U8)(ut_g_rfb[i].breath_type_id));
25              dbg_print( " UtPlus BreathLED init nvram write  data = %d , \r\n  " ,data);
26              WriteValue(NVRAM_RF_UTPLUS_SETTING_START  +  i  +   1  , & data, DS_BYTE ,  & error);
27          }
28           else
29          {
30              dbg_print( " UtPlus BreathLED init nvram read success i = %d \r\n  " ,i);
31              ut_g_rfb[i].switch_id  =  (data & 0xC0 ) >> 6 ;
32              ut_g_rfb[i].speed_level  =  (data & 0x30 ) >> 4 ;
33              ut_g_rfb[i].breath_type_id  =  (data & 0x0f );
34          }
35      }
36  }
37  // 在nvram存储对应修改值
38  void  utplus_rf_breath_set_nvram_value(U8 index,utplus_rf_breath *  utrb)
39  {
40      U8 data  =   0 ;
41      S16 error;
42 
43      ASSERT(index < RF_UTPLUS_FEATRUE_END);
44      
45      data  =  ((U8)(utrb -> switch_id) << 6 ) | ( (U8)(utrb -> speed_level)  << 4 ) | ( (U8)(utrb -> breath_type_id));
46      dbg_print( " \r\n UtPlus BreathLED set nvram read index = %d  data = %d , \r\n  " ,index,data);
47      WriteValue(NVRAM_RF_UTPLUS_SETTING_START  +  index   +   1 , & data, DS_BYTE ,  & error);
48      ut_g_rfb[index].switch_id  =  utrb -> switch_id;
49      ut_g_rfb[index].speed_level  =  utrb -> speed_level;
50      ut_g_rfb[index].breath_type_id  =  utrb -> breath_type_id;
51  }
52 

 

读取结构数据也是比较常用的方式,可能初级的程序员还是比较少的接触这个的,常用的接口函数是WriteRecord和ReadRecord
这两个函数逻辑处理的核心数据是
ltable_entry_struct logical_data_item_table_comm_app[] 

 

在这个结构定义前MTK有如下说明:
 1 
 2  /* *
 3   * Steps of defining logical data item:
 4   * 1> Define LID of new logical data item into `nvram_LID_cust_enum' in 
 5   *    nvram_user_defs.h
 6   * 2> Define two constants: SIZE and TOTAL, in nvram_user_defs.h
 7   * 3> Define default value of that new logical data item in nvram_user_config.c
 8   * 4> Define attributes of that new logical data item into 
 9   *    `logical_data_item_table_cust'
10   * 5> Bypass.
11   * 6> Change version number CODED_DATA_VERSION in nvram_user_config.c
12    */
13  /* *
14   * The logical data item table.
15   * Note:
16   * Each logical data item must be:
17   * 1> Size must be EVEN
18   * 2> Size of default value must be equal to the logical data item's size.
19    */
20    /* *
21   * The rule for data item changes:
22   * 1. To add a new data item, its name must be the next of the current last LID, for example, 
23   *     the last LID in the CT reign now is CT20, the new one must be CT21. 
24   * 2. Version must be increased if 
25   *    (a) Size is changed, or 
26   *    (b) Number of sections is changed, or 
27   *    (c) Attribute is changed, or 
28   *    (d) data structure is changed.
29    */

 

上面已经将部分配置说明的比较清楚了,下面拿出mtk的一项举例说明:
 1  #ifdef __MMI_FILE_MANAGER__
 2      ,{
 3          NVRAM_EF_WPSS_FILENAME_LID,
 4          NVRAM_EF_WPSS_FILENAME_SIZE,
 5          NVRAM_EF_WPSS_FILENAME_TOTAL,
 6          NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT),
 7          NVRAM_ATTR_AVERAGE,
 8          NVRAM_CATEGORY_USER  |  NVRAM_CATEGORY_FACTORY,
 9           " MP1S " ,
10          VER(NVRAM_EF_WPSS_FILENAME_LID),
11           " Dispchar path " ,
12          NVRAM_APP_RESERVED
13      }
14  #endif  /* __MMI_FILE_MANAGER__ */

 


NVRAM_EF_WPSS_FILENAME_SIZE,定义为 sizeof(PHNSET_WPSS_FILENAME_STRUCT),单个结构体的大小
NVRAM_EF_WPSS_FILENAME_TOTAL 表示存储几个这样的结构体
NVRAM_NORMAL(NVRAM_EF_ZERO_DEFAULT)每个结构体的初始值,此处表示初始化值全为0, 如果想初始化需要的默认值可以参考NVRAM_EF_PROFILES_LID情景模式的初始值.
下面两个参数是

 

      nvram_attr_enum attr;           /* U16 */

     nvram_category_enum category;    /*  U32  */

 

 

这两个属性在系统进行nvram的read/write中用到,具体意义我也不太清楚,比如IMEI的NVRAM_EF_IMEI_IMEISV_LID就有NVRAM_ATTR_WRITEPROTECT属性.
下面的VER(NVRAM_EF_WPSS_FILENAME_LID)是将NVRAM_EF_WPSS_FILENAME_LID变为NVRAM_EF_WPSS_FILENAME_LID_VERNO,这个定义Record版本号,定义在common_nvram_editor_data_item.h,据说是系统升级后系统会自动对比这个版本号,如果这个版本号不同的话就会自动覆盖原先的值.有研究手段的朋友请告知我,谢谢啊.
  上面的byte,short,double的存储也是组合成record来进行的,其size都是NVRAM_CACHE_SIZE=512,也就是说存储byte的个数 上限是512个,short的个数上限是256个,double的个数的上限是64个(如果你的应用需要存储的数据量比较大最好新建record).他们分别对应NVRAM_EF_CACHE_BYTE_LID,NVRAM_EF_CACHE_SHORT_LID,NVRAM_EF_CACHE_DOUBLE_LID.所以对于一些常规的nvram修改如果不像格式化重新校准软件就可以升级对应的nvram版本号即可.  
  下面阐述关于NVRAM的编译生成和读取流程.
 NVRAM的编译生成主要依靠tools\NVRAMStatistic下的相关文件,src是相关源代码文件,通过NVRAMAutogen.bat每次生成新的nvram_auto_gen.exe,nvram数据的生成也是通过logical_data_item_table_comm_app为接口的.
  NVRAM系统读取得模块代码位于工程nvram目录下,系统的实现接口是
kal_bool nvram_create(comptask_handler_struct **handle)
比较核心的处理函数是;void nvram_main(ilm_struct *ilm_ptr)
 1  /* ****************************************************************************
 2   * FUNCTION
 3   *  nvram_main
 4   * DESCRIPTION
 5   *  This is main() function of NVRAM module.
 6   * PARAMETERS
 7   *  ilm_ptr     [IN]        The primitives
 8   * RETURNS
 9   *  void
10   **************************************************************************** */
11  void  nvram_main(ilm_struct  * ilm_ptr)
12  {
13       /* ---------------------------------------------------------------- */
14       /*  Local Variables                                                 */
15       /* ---------------------------------------------------------------- */
16 
17       /* ---------------------------------------------------------------- */
18       /*  Code Body                                                       */
19       /* ---------------------------------------------------------------- */
20      ASSERT(ilm_ptr  !=  NULL);
21 
22       if  (ilm_ptr  !=  NULL)
23      {
24           if  ((ilm_ptr -> msg_id  >=  MSG_ID_NVRAM_CODE_BEGIN)  &&  (ilm_ptr -> msg_id  <=  MSG_ID_NVRAM_CODE_END))
25          {
26 
27               if  (ilm_ptr -> msg_id  ==  MSG_ID_NVRAM_STARTUP_REQ)
28              {
29                  nvram_startup_handler(ilm_ptr);
30              }
31               else   if  (ilm_ptr -> msg_id  ==  MSG_ID_NVRAM_RESET_REQ)
32              {
33                  nvram_reset_handler(ilm_ptr);
34              }
35               else   if  (ilm_ptr -> msg_id  ==  MSG_ID_NVRAM_READ_REQ)
36              {
37                  nvram_read_handler(ilm_ptr);
38              }
39               else   if  (ilm_ptr -> msg_id  ==  MSG_ID_NVRAM_WRITE_REQ)
40              {
41                  nvram_write_handler(ilm_ptr);
42              }
43               else   if  (ilm_ptr -> msg_id  ==  MSG_ID_NVRAM_WRITE_IMEI_REQ)
44              {
45                  nvram_write_imei_handler(ilm_ptr);
46              }
47               else   if  (ilm_ptr -> msg_id  ==  MSG_ID_NVRAM_SET_LOCK_REQ)
48              {
49                  nvram_set_lock_handler(ilm_ptr);
50              }
51          }
52      #ifdef TST_HANDLER
53           else
54          {
55               /*  not nvram defined message  */
56               if  (ilm_ptr -> msg_id  ==  MSG_ID_TST_INJECT_STRING)
57              {
58                  nvram_tst_handler(ilm_ptr);
59              }
60          }
61       #endif  /* TST_HANDLER */ 
62 
63      }
64  }    /*  end of module main function  */

 


主要处理的是 : startup,reset,read,write,write_imei,set_lock
在这里对imei的单独处理可能跟他的NVRAM_ATTR_WRITEPROTECT属性有关吧.

作者:张素丰,转载请注明出处:http://www.cnblogs.com/zhangsufeng/archive/2010/09/11/1824100.html

  这只是表面的分析,深入的研究需要更多的能力,我现在还比较欠缺,渴望和大家多交流,我QQ号是275000205。

20100912 0:22补充:

今日研究了下电话本的nvram存储,不惑,得一高人点拨,发现在记录里还有一个重要的特性:

     LID_BIT VER_LID(NVRAM_EF_WPSS_FILENAME_LID)
     nvram_wpss_filename_struct *NVRAM_EF_WPSS_FILENAME_TOTAL
     {
     };
用来将LID和结构体关联,而且我们找LID所用的结构可以快速的通过这个找到。

关于这方面的详细介绍请见:http://blog.ednchina.com/Jerome_home/1801884/message.aspx

posted on 2010-09-11 19:44  Anpher Zhang 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/zhangsufeng/archive/2010/09/11/1824100.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值