MTK_NVRAM等操作
手机MTK指令大收集

手机MTK指令大收集本文将详细介绍手机MTK指令的相关知识,包括MTK指令的定义、常用的MTK指令及其功能、如何使用MTK指令等方面。
如果您对MTK指令感兴趣,那么本文一定会为您带来参考价值。
一、MTK指令的定义MTK指令(全称为MediaTek指令),是指一种用于控制手机芯片的指令,其功能非常强大,能够用来控制手机的各种功能,也可以用来进行手机维护工作。
MTK指令常常被手机维修工程师所使用,但是,如果你掌握了MTK指令的使用方法,那么就能够在日常使用中更好地保护手机,提高手机的使用效率,为日常生活带来更多的便利。
二、常用的MTK指令及其功能1. AT指令AT指令是指"Attention"(注意)的缩写,是MTK芯片中常用的指令之一。
它能够用来控制手机的通信模块,实现各种通讯功能。
例如,通过AT指令,可以查询手机的网络状态、发送短信、拨打电话等。
2. ENG模式ENG模式是指工程模式,也被称为测试模式。
使用ENG模式,可以访问手机的各种硬件信息,并进行测试和调整。
ENG 模式还可以用来解锁手机、清空手机中的所有数据等。
3. NVWiFiNVWiFi是指Non-Volatile Wireless LAN,非易失性无线局域网,可以用来设置和管理WLAN网络。
NVWiFi可以启用或关闭WLAN功能,查看和配置当前WLAN连接等。
4. AT+EGMRAT+EGMR指令可以用来设置手机的IMEI号码。
IMEI号码是手机的唯一标识,各个手机IMEI号码都不相同。
如果由于一些原因IMEI号码被更改,那么就有可能导致手机无法正常使用。
通过AT+EGMR指令,可以设置和修改手机的IMEI号码。
5. AT+EGPSAT+EGPS是指通过MTK芯片来控制GPS定位功能。
通过AT+EGPS指令,可以对手机的GPS模块进行初始化、查询GPS 信号强度、设置GPS自动更新时间等。
6. AT+EGSMAT+EGSM指令可以用于控制手机信号的强度。
MTK之NVRAM研究

5,在文件:“nvram_user_config.c”中的结构体数组 logical_data_item_table_cust[]中新添加一 个条目(Add a new entry);
- vendor_nvram_editor_data_item.h: for CV use 现在我们回头去看步骤 5,添加新的条目的操作中,我们会问,为什么要添加新的条目,而 且在这些变量中,各个项的涵义是什么呢? 如下:
ex: { NVRAM_EF_PORT_SETTING_LID, NVRAM_EF_PORT_SETTING_SIZE, NVRAM_EF_PORT_SETTING_TOTAL, NVRAM_EF_PORT_SETTING_DEFAULT, NVRAM_ATTR_AVERAGE, NVRAM_CATEGORY_USER, "MP1y", VER(NVRAM_EF_PORT_SETTING_LID), "Port Settings\0", NVRAM_RESERVED_VALUE },
2,线性固定数据元(linear fixed EF):这个类型的数据项的记录的大小远大于一个 byte;所 有的数据按线性存储; 如下图所示:
一,先来看“线性固定数据元” 首先我们来新建一项 NV;分析每个步骤的原理; 总的步骤必须遵循如下几步: 1,在 文件: “nvram_user_defs.h” 的枚 举结构体 “nvram_LID_cust_enum” 中定 义一个新 的
NVRAM_ATTR_AVERAGE,
NVRAM_CATEGORY_USER,
MTK中的nvram的操作实现

NVRAM读写操作详解在MTK中,NVRAM是作为一个独立的task来运行的。
在nvram_main.c文件中,(代码有删减, 注释部分用黄色标出, 便于阅读)void nvram_task_main(task_entry_struct *task_entry_ptr){kal_get_my_task_index(&my_index);/* nvram special service */nvram_special_service();while (1){//从Q中得到消息receive_msg_ext_q(task_info_g[task_entry_ptr->task_indx].task_ext_qid, ¤t_ilm);stack_set_active_module_id(my_index, current_ilm.dest_mod_id);// 处理消息nvram_main(¤t_ilm);// 释放消息free_ilm(¤t_ilm);}}Nvram_main函数, 处理NVRAM相关的消息void nvram_main(ilm_struct *ilm_ptr){if (ilm_ptr != NULL){if ((ilm_ptr->msg_id >= MSG_ID_NVRAM_CODE_BEGIN) && (ilm_ptr->msg_id <= MSG_ID_NVRAM_CODE_END)){if (ilm_ptr->msg_id == MSG_ID_NVRAM_STARTUP_REQ){//STARTUP消息nvram_startup_handler(ilm_ptr);}else if (ilm_ptr->msg_id == MSG_ID_NVRAM_RESET_REQ){//RESET消息nvram_reset_handler(ilm_ptr);}else if (ilm_ptr->msg_id == MSG_ID_NVRAM_READ_REQ){nvram_read_handler(ilm_ptr); //READ消息}else if (ilm_ptr->msg_id == MSG_ID_NVRAM_WRITE_REQ){nvram_write_handler(ilm_ptr); //WRITE消息}else if (ilm_ptr->msg_id == MSG_ID_NVRAM_SET_LOCK_REQ){nvram_set_lock_handler(ilm_ptr); //LOCK消息, 比较多用在TST中}}} /* end of module main function */也可以看到NVRAM task处理几个消息.READ流程从NV中读取一个数据, 例如读取语言设置信息:ReadValue (NVRAM_SETTING_LANG, &data, DS_BYTE, &error);我们需要注明, NVRAM的LID, 读取数据存放的指针, 数据类型, 和返回错误信息的地址. #define ReadV alue(nId,pBuffer,nDataType,pError)\ReadValueInt(nId,pBuffer,nDataType,pError,__FILE__,__LINE__)ReadValue精简了两个参数, 不需要注明文件和第多少行, 方面了应用使用. 看一下ReadValueInt这个函数.我们来看看这个函数到底干了什么事情:S32 ReadValueInt(U8 nDataItemId, void *pBuffer, U8 nDataType, S16 *pError, S8 *fileName, S32 lineNumber){switch (nDataType){case DS_BYTE:{// byteDataReadFlag先记住这个标志, 它标志了byte的数据是否已经被读取, 所以从这里我们可以猜测, NVRAM的数据, 应该不是每次都从硬件读取的, 而是有缓存的(记住这个假设, 稍后验证)/* second time reading, it alwasy return one request item */if (byteDataReadFlag){// 这个注释就更加明白了/* Data is cached no need to read from NVRAM */memcpy(pBuffer, &byte_data[nDataItemId * nDataType], nDataType);status = DS_BYTE;error = NVRAM_READ_SUCCESS;}/* process first time reading all data and return first request item data */else{/* Read data from the NVRAM file */// 这才从NVRAM文件中读取// 这个BUFFER的大小, 8*512 = 4KU8 tempBuffer[NVRAM_CACHE_SIZE];// 这个函数重点分析status = ReadRecordInt(NVRAM_EF_CACHE_BYTE_LID,1,tempBuffer,sizeof(tempBuffer),&error,fileName,lineNumber);/* copy out all total reading data */// 把读取的数据copy到byte_data里面去memcpy(byte_data, tempBuffer, sizeof(tempBuffer));// 这个时候把这个flag置上了byteDataReadFlag = 1;/* return first request item data */memcpy(pBuffer, &byte_data[nDataItemId * nDataType], nDataType);status = DS_BYTE;error = NVRAM_READ_SUCCESS;}break;} /* End of case DS_BYTE */// 后面的SHORT, DOUBLE同样道理case DS_SHORT:{} /* End of case DS_SHORT */case DS_DOUBLE:{} /* End of case DS_DOUBLE */}*pError = error;return status;}ReadValueInt总结:这个函数, 就是把以前读好的三个数组的数据拿出来, 如果还没有从NVRAM读取到cashe 里面, 就读一次. 关键的函数是: ReadRecordInt.第一次读BYTE类型的数据之前, 三个数组都是空的, flag也是空的, 读一个之后, byte数据被从NVRAM文件中读入到cashe中, 放在byte的数组里面, byteflag也被置上了. 下次再读的byte, 就只需要从CACHE中读取就可以了. 同理, short和double数据也相同.来看看它是怎么做的#define ReadRecordInt(nFileId,nRecordId,pBuffer,nBufferSize,pError,fileName,lineNumber)\ AccessRecordInt(nFileId,nRecordId,pBuffer,nBufferSize, 1, pError, MMI_FALSE, MMI_TRUE, fileName,lineNumber)S32 AccessRecordInt (U16 nFileId, U16 nRecordId, void *pBuffer, U16 nBufferSize, U16 nRecordAmount, S16 *pError, pBOOL isWrite, pBOOL isValue,S8 *filename, S32 lineNumber) {MYQUEUE queueNode;S32 status = -1;U32 my_index;circularQ_check_enum circularQ_check_result = circularQ_check_never_check;static U8 nvram_req_count = 0;MMI_BOOL toPush;if (isWrite){//WRITE的先放一下, 先看READ的再说}else{// 发了一个消息SendNVRAMReadReq(nFileId, nRecordId, nRecordAmount);// 这个函数调用了Message.oslMsgId = MSG_ID_MMI_EQ_NVRAM_READ_REQ;//OslMsgSendExtQueue(&Message), 发了一个REQ消息到Q上去.}in_nvram_procedure++;// REQ消息发完了, 接下来就等RSP消息来while (1){/* if more than 1 access request exist, go through the circular Q */if ((nvram_req_count > 0) && (circularQ_check_result == circularQ_check_never_check)){circularQ_check_result = NVRAMCheckCircularQ(&queueNode, nFileId);}if (circularQ_check_result != circularQ_check_found){OslReceiveMsgExtQ(mmi_ext_qid, &queueNode);OslGetMyTaskIndex(&my_index);OslStackSetActiveModuleID(my_index, MOD_MMI);}// 这个标志位先置空, 不管, 先记住它toPush = MMI_FALSE;switch (queueNode.msg_id){// 这里列出了很多消息, 其他不管, 先找READ_RSP消息再说case MSG_ID_MMI_EQ_PLAY_AUDIO_RSP:case MSG_ID_MMI_EQ_STOP_AUDIO_RSP:case MSG_ID_MMI_EQ_EXE_GPIO_LEVEL_RSP:case MSG_ID_MMI_EQ_SET_VOLUME_RSP:case MSG_ID_MMI_EQ_KEYPAD_DETECT_IND:case MSG_ID_TIMER_EXPIRY:// 就它了case MSG_ID_MMI_EQ_NVRAM_READ_RSP:{mmi_eq_nvram_read_rsp_struct *readMessage;readMessage = (mmi_eq_nvram_read_rsp_struct *)queueNode.oslDataPtr;{if (readMessage->result.flag == MMI_OK){// 读成功了, 再比较一下数据大小是不是合格if (readMessage->length > nBufferSize){}else if (readMessage->length < nBufferSize){}else{memcpy(pBuffer, readMessage->data, readMessage->length);*pError = NVRAM_READ_SUCCESS;}status = readMessage->length;}OslFreeInterTaskMsg(&queueNode);}toPush = MMI_TRUE;break;}case MSG_ID_MMI_EQ_NVRAM_WRITE_RSP:}// 这个flag标志是否读取成功if (toPush == MMI_TRUE){ilm_struct ilm_ptr;flag = OslWriteCircularQ(&ilm_ptr);OslFreeInterTaskMsg(&queueNode);}}}AccessRecordInt总结:这个函数是个真正的读取函数, 发REQ消息给NVRAM TASK, 等待RSP消息, 得到读取数据.写入流程重点分析WriteValueInt这个函数S32 WriteValueInt(U8 nDataItemId, void *pBuffer, U8 nDataType, S16 *pError, S8 *fileName, S32 lineNumber){switch (nDataType){// 还拿BYTE来说case DS_BYTE:{// 已经从NVRAM 到CACHE里面了/* second time access, it always sets the request item */if (byteDataReadFlag){/* Data is cached no need to read from NVRAM */memcpy(&byte_data[nDataItemId * nDataType], pBuffer, nDataType);/* write into NVRAM module, if not wait for falshing directly */if (!byteDataWriteFlashFlag){status = WriteRecordInt(NVRAM_EF_CACHE_BYTE_LID,1,byte_data,NVRAM_CACHE_SIZE,&error,fileName,lineNumber);}status = DS_BYTE;error = NVRAM_WRITE_SUCCESS;}// 还没有读到CACHE里面/* process first time access all data and return first write item data */else{// 那就读到CACHE/* Read all data from the NVRAM file */status = ReadRecordInt(NVRAM_EF_CACHE_BYTE_LID,1,byte_data,NVRAM_CACHE_SIZE,&error,fileName,lineNumber);memcpy(&byte_data[nDataItemId * nDataType], pBuffer, nDataType);//读好了,就写吧/* write into NVRAM module, if not wait for falshing directly */if (!byteDataWriteFlashFlag){// 关键还是WriteRecordIntstatus = WriteRecordInt(NVRAM_EF_CACHE_BYTE_LID,1,byte_data,NVRAM_CACHE_SIZE,&error,fileName,lineNumber);}byteDataReadFlag = 1;status = DS_BYTE;error = NVRAM_WRITE_SUCCESS;}break;} /* End of case DS_BYTE */case DS_SHORT:{} /* End of case DS_SHORT */case DS_DOUBLE:{} /* End of case DS_DOUBLE */}}看看WriteRecordInt函数:S32 WriteRecordInt(U16 nFileId,U16 nRecordId,void *pBuffer,U16 nBufferSize,S16 *pError, S8 *filename, S32 lineNumber){// 打开文件handle = FS_Open((PU16) fileNameU, FS_CREATE_ALWAYS);{// 写文件retValue = FS_Write(handle, pBuffer, nBufferSize, &iBytes);}}WriteRecordInt总结:其实, 就做了一个写文件的操作, 但是每次都把CACHE里面的数据写到文件里面去.为什么不使用OFFSET的方式呢?写入的数据量也小呀.MP数据MP, for MTK/PMT common applications; 在nvram_common_config.c定义一般存放比较大的数据量, 不能BYTE, SHORT, DOUBLE来分类的那种.读取和写入使用另外接口, ReadRecord和WriteRecord, 直接通过文件读写操作.比如我们要做黑白名单, 就可以在MP这里做.。
MTK方案操作手册

MTK方案操作手册菜单设置:按遥控器的setup键进行功能选择:可以进行以下五个页面的设定:通用设定(General Setup)、音频设定(Audio Setup)、视频设定(Video Setup)、初期设定页(Preference Page)、密码设定(Password Setup).通用设定音频设定视频设定初期设定页密码设定退出设定按左(left),右(right)键进行页面间的切换,按上(up),下(down)键页面内的选择,按play键选种页面里面的功能,按左键(left)返回到上一个状态。
1.通用设定(General Setup)(此页面有六项设定)1.1电视机形式(TV Display)注:只对16:9碟片有效1.1.1正常/全景(Normal/PS)适用于一般尺寸电视机,播放宽屏幕图像时,图像左右边缘被切除,把图像放映到整个屏幕上PS1.1.2正常/信箱Normal/LB)对于一般尺寸电视机,播放宽屏幕图像时,电视屏幕的顶部和底部出现黑色边框。
LB1.1.3宽银幕(wide)适用于宽屏幕电视机16:9 raw1.1.4 wide squeeze16:9宽屏幕电视机播放4:3屏幕图像时,两边将被拉伸,故需在水平方向进行压缩,宽屏幕两边将出现黑边。
squeeze1.2 角度标记(Angle Mark)可对角度标记进行“开、关”选择。
播放记录多角度画面碟片时,选择“开”角度标记在屏幕显示出来,“关”则不显示。
1.3显示语言(OSD LANG)可对屏幕上的显示(OSD)进行“ENGLISH、中文”等进行选择。
1.4隐藏字幕(CAPTION)对NTSC制式电视机,可对内含CLOSED CAPTION功能的碟片进行CAPTION显示或隐藏选择。
须电视和碟片支持,否则无法进行该操作。
1.5屏幕保护(screen save)可对屏幕保护设置进行“开、关”选择。
选择“开”时,机器停止播放一定时间后,屏幕出现屏幕保护画面;选择“关”,屏幕保护画面不会出现。
MTK平台生产软件 使用说明

版本号: 编号: 编制: 日期:
1.测试流程
1.1 SMT 后段测试流程图 (其中软件下载、BSN 写入、校准、综测、功能测试有对应的软件)
图1 1.2 组装测试流程图
( 其中软件升级、整机终测、写IMEI 号有对应的软件)
图2
2.下载
2.1 概述 • MTK 系列主板存储系统有两个Flash 构成,一个是主Flash,用于存放手机代码部分和其他参数;
使用。另外工程人员可以通过口令进入到设置模式下,改变一些常规的设置,而高级的设置则需要 工程人员到相应的配置文件里面修改。
MTK_ATEDEMO.EXE 工具校准项分为射频和基带两个部分,射频部分包括AFC 、APC 、 Path Loss, 基带部分包括ADC • AFC 自动频率控制 • APC 自动功率控制 • Path Loss 接受增益控制 • ADC 电池电量校准
4.2 软件安装
MTK_ATEDEMO.EXE 安装非常简单,只需将整个MTK_ATEDEMO.EXE 目录Copy
到本地即可。如果想删除只需Delete 整个目录。 4.3 硬件环境 4.3.1 设备清单:
• 工控机:Generic Pentium III or above PC • 测试仪:Agilent 8960 、CMU200 • 数控电源:Agilent66xx 、Keithly23xx • GPIB 卡:NI、Agilent(and Driver) • RF Cable、测试线/夹具
另外一个NAND Flash,用于存放MP3。 • 图1 中的下载工位(SMT 后段) 是将手机软件的SOFT 代码部分下载到主板上的Flash 并且将
参数格式化,而图2 中的下载(升级) 工位( 组装段)只是将手机软件的SOFT 代码部分更
MTK

情景模式默认设置的修改,以及铃声的修改替换一、查找情景模式的NVRAM 存储ID1、运行模拟器,并清除所以的断点(CTRL+ALT+F9(光标在文件里))。
2、找到EntryNewScreen函数,运行模拟器调试状态(F5)3、按如下顺序进入菜单主菜单—>情景模式—>标准模式—>customize→Tone setting4、进入这个菜单后,在我们代码EntryNewScreen函数里面设置断点。
光标放在return前,按F95、在手机模拟器上任意点击,例如点击ring 46、断到断点处。
然后我们查看Call stack 窗口。
(view→debug windows→call stack)7、我们在这个窗口里,查找调用POP框的函数,并双击这个函数。
代码就会找到这个调用的函数。
并且这个函数的前面会有一个绿色的箭头。
如图所示8、我们查看函数,并在调用POP框的下一个语句,设置断点。
如图所示:按F5,运行,断到刚才设的断点出。
然后按F11,或者鼠标点击进入setRingToneId函数里。
9、进入这个函数后,按F10 单步运行。
并看到如下语句。
按F11进入后,我们在这个函数里看到如下语句。
在这里,我们就是NVRAM的ID,NVRAM_EF_PROFILES_LID。
二、修改不同模式下的设置默认值1、我们通过source insight 全工程搜索(Ctrl + /)情景模式的NVRAM ID,即NVRAM_EF_PROFILES_LID。
查找后,如图所示:2、我们进入VER(NVRAM_EF_PROFILES_LID),如图所示3、我们发现了上述黄色高亮的变量,我们在全工程搜索它。
方法是首先光标放在它的上面,然后ctrl + / ,按回车。
查看它的值。
如图所示:在NVRAM_common_cofig.c文件里在这里数组里,就是情景模式不同模式下的不同选项的默认值。
我们以开关机铃声默认值为例,详细描述。
MTK编译命令详细介绍

mcp_check cleanlog cleanbin genverno libs $(BIN_FILE) done
功能: remake是重新编译整个工程的ARM版,该动作只是简单的重新编译链接有改动的部分。它不检查依赖关系.不扫描资源,只扫描代码的改变,有改变的重编,资源和无改变的代码不编。
过程简要说明:remake->mcp_check->cleanlog->cleanbin->genverno->libs->$(BTLD_BIN_FIKE)->cmmgen->done。
依赖指令:mcp_check,cleanlog,cleanbin,genverno,libs,$(BIN_FIKE),cmmgen,done。其中最重要的两个指令是libs,$(BIN_FIKE)。Libs调用编译器和连接器将各个模块目录下的C文件编译连接为独立的库。$(BIN_FIKE)是将各个模块编译连接的库和mtk_lib目录下的库一起连接起来得到一个映像文件,然后使用ADS的工具fromelf将映像文件生成以变量BIN_FILE命名的二进制文件,该文件可以下载到硬件板上运行。
New 清除并重新编译所有的文件
主要完成工作 gsm2.mak
cleanall cmmgen mmi_feature_check asngen codegen asnregen operator_check_lite update
功能:全新开始构建整个工程的ARM版,包括图片、声音、字符串等资源都要重做。在构建工程过程中,清除所有的目标文件,库文件,日志文件等。New指令还会自动创建必要的目录、移除临时文件和中间脚本、更新日志文件。
MTK手机MODEM上网操作指南(适用于MTK平台)

MTK手机MODEM上网操作指南(适用于MTK平台)第一步:开通 GPRS 功能确定您的SIM卡开通了GPRS功能和手机互联网业务,如果没有开通,可拨打相应运营商电话(如:移动10086)申请开通或到当地营业厅开通。
第二步:连接PC 和手机(USB Modem 驱动程序安装详见附件)将随机所配的数据线插入PC端的某个USB端口,将手机连接至数据线另一端,在手机上的“USB设定”界面选择“串口”。
第三步:查看COM 口点击“我的电脑”右键中的“属性” —→ 选择“硬件”—→选择“设备管理器”—→“端口”查看此设备使用的端口号。
如下图:第五步:Modem 属性设置点击“属性”—→选择“高级”功能项,在额外设置中输入AT 命令:AT+CGDCONT=1,"IP","CMNET","",0,0 ,然后点击“更改默认首选项”。
具体设置如下图示:第六步:新建拨号连接:新建一个使用上面 Modem 的拨号连接:在“控制面板”—“网络连接”界面,点击“创建一个新的连接”,创建步骤如以下图示:第七步:设置拨号连接:打开新建的拨号连接,用户名和密码都空着,拨号号码为*99#;点击“属性”,具体设置步骤如以下图示:第八步:拨号:在拨号窗口点击“拨号”,如下图(23)所示:拨号成功,电脑会跳出连接成功的提示,另可查看到如下图所示的拨号连接状态。
此时您就可以利用手机提供的MODEM 功能享受上网冲浪了。
注:以上示例是基于 Windows XP 操作系统的,Windows 2000 设置步骤与XP 一致。
附:USB 转串口驱动安装过程:第一步:将相应机型的 PC 同步软件解压保存在电脑上第二步:用数据线连接 PC 和手机,然后依照电脑提示安装USB 转串口驱动步骤 1:将随机所配的数据线插入PC 端的某个USB 端口,将手机连接至数据线另一端,在手机上的“USB 设定”界面选择“串口”。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MTK 中nvram 的读写操作定义NVRAM 数据有三种方式:(一)、在nvram_editor_data_item.h、nvram_data_item.h、nvram_data_item.c三个文件中添加。
1、在nvram_editor_data_item.h文件中定义自己保存在nvram 中的结构体数据类型。
例如:typedef struct{Int a;Char b;}my_nvram_data_t;2、在nvram_data_item.h 文件中的nvram_lid_core_enum 枚举中定义自己的nvram ID(建议在最后面添加,但必须添加到NVRAM_EF_LAST_LID_CORE 的前面)。
再定义两个宏,一个宏是前面定义的结构体的字节大小,另一个是在nvram中保存的数据个数,如果在nvram 中只需要保存一个数据的话,就定义为1。
例如:typedef enum{…………My_nvram_data_lid, //自己定义的nvram IDNVRAM_EF_LAST_LID_CORE}nvram_lid_core_enum;#define my_nvram_data_size sizeof( my_nvram_data_t )#define my_nvram_data_total 13、在nvram_data_items.c文件中的lobical_data_item_table_core 结构体数组中添加自己的项。
建议添加在最后,仿照前面的添加。
例如:Itable_entry_struct logical_data_item_table_core[] ={…………,{My_nvram_data_lid , //前面定义的枚举IDmy_nvram_data_size , //前面定义的宏,结构体大小my_nvram_data_total , //前面定义的宏,nvram中数据的个数NVRAM_EF_ZERO_DEFAULT,NVRAM_A TTR_A VERAGE,NVRAM_CATEGORY_USER,“ MT1D” ,// 根据前面的数据项递增VER( My_nvram_data_lid ),“ my nvram test\0” ,//数据描述,只做参考,无其他作用NVRAM_RESERVED_VALUE}, { NVRAM_EF_RESERVED_LID}}4、my_nvram_data_t my_nvram_data = {0};S16 error ;//将my_nvram_data中的数据写到nvram中My_nvram_data_lid 标志处,error保存错误标志WriteRecord(My_nvram_data_lid, 1, &my_nvram_data, sizeof(my_nvram_data_t ), & error);//将nvram中My_nvram_data_lid 标志处的数据读到my_nvram_data中,error保存错误标志ReadRecord(My_nvram_data_lid, 1, &my_nvram_data, sizeof(my_nvram_data_t ), & error);二、在common_nvram_editor_data_item.h、nvram_user_defs.h、nvram_user_config.c 中定义1、common_nvram_editor_data_item.h 此处定义nvram 中保存数据的结构体数据类型2、nvram_user_defs.h 此处定义nvram ID 和结构体数据大小、数据总数3、nvram_user_config.c 此处填充nvram 结构数据内容及defult值(在MTK 下建议使用此方法修改nvram)(mtk 中nvram 的读写操作(一,二)/epll_apple/blog/item/94b29c22083a14a84723e846.html)三、在coustom_mmi_default_value.h、common_mmi_cache_config.c中定义1、在custom_mmi_default_value.h 文件中有三个枚举类型BYTEDATA,SHORTDATA和DOUBLEDATA。
分别占1个字节,2个字节,8个字节。
根据自己的所要保存的数据大小在相应的枚举里定义自己的nvram ID。
建议在最后面添加,但都必须添加在最后一项的前面。
例如:typedef enum{…………Nvram_my_shortdata_id,NVRAM_LAST_SHORT_ELEMENT}SHORTDATA;2、在common_mmi_cache_config.c文件中存在三个结构体数组common_mmi_cache_byte[]、common_mmi_cache_short[],common_mmi_cache_double[]。
在对应的数组里添加自己的数据项,设置nvram 的初始值。
例如:mmi_cache_short_entry common_mmi_cache_short[] ={…………SHORT_ENTRY(Nvram_my_shortdata_id, 0x00, 0x00) ,{0xFF, 0xFF, 0xFF, “”, “”,””}};3、short int myNvramData;S16 error;//写nvramWriteValue(Nvram_my_shortdata_id , &myNvramData , DS_SHORT , &error) ;//读nvramReadValue(Nvram_my_shortdata_id , &myNvramData , DS_SHORT, &error) ;(注意:在模拟器下,修改了nvram 最后是在DOS 下用new 命令全部重新编译一次)MTK提供的NVRAM存取方式有两种,一种读取单条数据,一种是读取结构数据.读取单条数据的比较常见,在mtk代码中随处可以找到例子,主要的接口函数是ReadValue 和WriteValue,函数中nDataType参数对应的是1typedef enum/* Pixtel Defined enum */2{3 DS_BYTE = 1,4 DS_SHORT = 2,5 DS_DOUBLE = 86} 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//开关2typedef enum3{4 SWITCH_NULL,//增加该项使nvram存储值不为05 SWITCH_ON,6 SWITCH_OFF,78//add item befor this9 RF_UTPLUS_SWITCH_END10}utplus_rf_breath_switch;11//从nvram中获取初始化值12void utplus_rf_breath_init_nvram_value(void)13{14 U8 data = 0;15 U8 i;16 S16 error;17for(i=0;i<RF_UTPLUS_FEATRUE_END;i++)18 {19 ReadValue(NVRAM_RF_UTPLUS_SETTING_START + i + 1,&dat a, DS_BYTE , &error);20 dbg_print("\r\n UtPlus BreathLED init nvram read data = %d , \r\n ",data);21if(data==0xff|| data < 0x40 ||error !=NVRAM_READ_SUCCE SS)22 {23 dbg_print("UtPlus BreathLED init nvram read er r 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 }28else29 {30 dbg_print("UtPlus BreathLED init nvram read succes s 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存储对应修改值38void utplus_rf_breath_set_nvram_value(U8 index,utplus_rf_breat h* utrb)39{40 U8 data = 0;41 S16 error;4243 ASSERT(index<RF_UTPLUS_FEATRUE_END);4445 data = ((U8)(utrb->switch_id)<<6)|( (U8)(utrb->speed_leve l) <<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,&dat a, 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有如下说明:12/**3 * Steps of defining logical data item:4 * 1> Define LID of new logical data item into `nvram_LID_cust _enum' in5 * nvram_user_defs.h6 * 2> Define two constants: SIZE and TOTAL, in nvram_user_defs. h7 * 3> Define default value of that new logical data item in nv ram_user_config.c8 * 4> Define attributes of that new logical data item into9 * `logical_data_item_table_cust'10 * 5> Bypass.11 * 6> Change version number CODED_DATA_VERSION in nvram_user_c onfig.c12 */13/**14 * The logical data item table.15 * Note:16 * Each logical data item must be:17 * 1> Size must be EVEN18 * 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 m ust be CT21.24 * 2. Version must be increased if25 * (a) Size is changed, or26 * (b) Number of sections is changed, or27 * (c) Attribute is changed, or28 * (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_RESERVED13 }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_CA CHE_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 * FUNCTION3 * nvram_main4 * DESCRIPTION5 * This is main() function of NVRAM module.6 * PARAMETERS7 * ilm_ptr [IN] The primitives8 * RETURNS9 * void10 ************************************************************* ****************/11void nvram_main(ilm_struct *ilm_ptr)12{13/*----------------------------------------------------------------*/14/*L o c a l V a r i a b l e s */15/*----------------------------------------------------------------*/1617/*----------------------------------------------------------------*/18/*C o d e B o d y */19/*----------------------------------------------------------------*/20 ASSERT(ilm_ptr != NULL);2122if (ilm_ptr != NULL)23 {24if ((ilm_ptr->msg_id >= MSG_ID_NVRAM_CODE_BEGIN) && (i lm_ptr->msg_id <= MSG_ID_NVRAM_CODE_END))25 {2627if (ilm_ptr->msg_id == MSG_ID_NVRAM_STARTUP_REQ)28 {29 nvram_startup_handler(ilm_ptr);30 }31else if (ilm_ptr->msg_id == MSG_ID_NVRAM_RESET_REQ)32 {33 nvram_reset_handler(ilm_ptr);34 }35else if (ilm_ptr->msg_id == MSG_ID_NVRAM_READ_REQ)36 {37 nvram_read_handler(ilm_ptr);38 }39else if (ilm_ptr->msg_id == MSG_ID_NVRAM_WRITE_REQ)40 {41 nvram_write_handler(ilm_ptr);42 }43else if (ilm_ptr->msg_id == MSG_ID_NVRAM_WRITE_IMEI_REQ)44 {45 nvram_write_imei_handler(ilm_ptr);46 }47else if (ilm_ptr->msg_id == MSG_ID_NVRAM_SET_LOCK_ REQ)48 {49 nvram_set_lock_handler(ilm_ptr);50 }51 }52 #ifdef TST_HANDLER53else54 {55/* not nvram defined message */56if (ilm_ptr->msg_id == MSG_ID_TST_INJECT_STRING)57 {58 nvram_tst_handler(ilm_ptr);59 }60 }61#endif /* TST_HANDLER */6263 }64} /* end of module main function */主要处理的是: startup,reset,read,write,write_imei,set_lock在这里对imei的单独处理可能跟他的NVRAM_ATTR_WRITEPROTECT属性有关吧.作者:张素丰,转载请注明出处:/zhangsufeng/archive/2010/09/11/1824100.html这只是表面的分析,深入的研究需要更多的能力,我现在还比较欠缺,渴望和大家多交流,我QQ号是275000205。