MTK6261D旧平台与RDA8851开机详解。注意,MTK新平台框架已经变了,所以开机流程与下面的有差异!
L4是MMI/AT和协议栈的适配层。ATCI是AT命令解析器。UEM是用于抽象如键盘、LED、通用输入/输出等基本设备,是用户设备模块。PHB就是电话本。SMU是安全管理单元(SIM、STK)。CSM是呼叫服务管理。RAC是登记访问控制。SMSAL是SMS应用层。
内核服务包括定时器、任务管理和进程间通信、资源和内存管理、日志和异常处理。
OSL是封装OS API的层,而KAL(kernel adpat layer)则是封装内核的层,应当在OSL以上来开发。
数据类型定义(VRE的头会比MTK更乱吗?)
* 基本数据类型:kal_non_specific_general_types.h。* KAL相关的定义:kal_release.h。(好变态的名字,对不对啊?)* MMI任务中和OSL相关的数据类型定义:PixtelDataTypes.h。
任务之间的通信是通过SEND_ILM来完成的,从实现来看是通过一个消息队列来完成的,关注struct ilm_struct定义,SAP是业务访问点。发送消息之前,首先要把本地参数缓冲区分配出来,然后赋值发送请求。
Highlight事件是用户通过键盘触发的事件,与提示信息关联。
SetProtocolEventHandler实际上就是MMI FRAMEWORK提供的回调函数注册工具,与MMI相关的所有事件都可以通过这个函数登记——包括网络。
按键码需要注意的几个特殊键:KEY_END是挂机键、KEY_SEND是摘机键。
MMI字符串资源的加入:
1)在ref_list.txt中加入字符串。2)把字符串ID加入到ID枚举中。3)使用ADD_APPLICATION_STRING2来加入字符串。4)使用 GetString_r()获得字符串。5)使用APP_BASE来保证字符串ID的唯一性。
图片资源的加入:
1)把图片加入应用程序目录。2)把图片ID加入枚举类型中。3)使用ADD_APPLICATION_IMAGE2来加入图片资源。4)绘图时就可以直接使用图片ID来绘制了。5)使用APP_BASE来保证图片ID的唯一性。
MMI各模块对应的目录:
Idle Screen:plutommi\mmi\IdleScreenMain Menu:plutommi\mmi\MainMenuPhone Book:plutommi\mmi\PhoneBookMessages:plutommi\mmi\MessagesCall History:plutommi\mmi\CallsCall Management:plutommi\mmi\CallManagementSetting:plutommi\mmi\SettingFile Manager:plutommi\mtkapp\FileMgrFun &Games:plutommi\mmi\FunAndGamesUser Profiles:plutommi\mmi\PROFILESOrganizer:plutommi\mmi\OrganizerServices:plutommi\mmi\SATShortcuts:plutommi\mmi\ShortcutsAudio Player:plutommi\mtkapp\AudioPlayerCamera:plutommi\mtkapp\CameraFMRadio:plutommi\mtkapp\FMRadioPhoto Editor:plutommi\mtkapp\PhotoEditorSound Recorder:plutommi\mtkapp\SoundRecorder
MMI特性定义文件在mcu\plutommi\Customer\CustResource\MMI_features[PROJ].h。
菜单的定义在GlobalMenuItems.h中。
MTK开机过程-系统启动
以下开机过程都是在simulator上跑时得出的结论
第一步:启动simulator的时候,直接进入:MMI_task()
1. iacMemInit();
2.进入一个while(1)循环。以后的过程都是通过消息机制,即:一直在这个循环中读取消息,然后做相应的处理。
第一次进入while(1)之后,OslReceiveMsgExtQ(qid, &Message)就读取到一个消息:PRT_MMI_TIMER_IND。然后就一直在这个循环中读消息。
mmi_frm_fetch_msg_from_extQ_to_circularQ();//消息转化(从外部队列取出消息并放入循环队列)count = OslNumOfCircularQMsgs();//获得消息总数while (count> 0){ if (OslReadCircularQ(&Message))//从循环队列中读取消息 { switch (Message.msg_id) { case MSG_ID_MMI_EQ_POWER_ON_IND: ...... default: } } msg_get_ext_queue_info(mmi_ext_qid, &queue_node_number);//获取消息 count--;}
第二步:Power On
读取到消息:MSG_ID_MMI_EQ_POWER_ON_IND
caseMSG_ID_MMI_EQ_POWER_ON_IND:
gdi_init();
switch (p->poweron_mode) //判断power on的模式
{
case POWER_ON_KEYPAD: //用户按下开机键
OslMemoryStart(TRUE);
g_charbat_context.PowerOnCharger = 0; //不是因为充电而开机的
InitializeAll(); //初始化,重点学习
OslDumpDataInFile();//这个函数不能进入,直接跳过
InitNvramData(); //加载保存在NVRAM中的设置的参数
mmi_pwron_entry_animation_screen(); //开机动画
break;
case POWER_ON_PRECHARGE:
case POWER_ON_CHARGER_IN:
g_pwr_context.PowerOnMode = p->poweron_mode;
InitializeChargingScr();
break;
case POWER_ON_ALARM: //定时开机
AlmInitRTCPwron();
break;
case POWER_ON_EXCEPTION: //For abnormal reset when invalid SIM
OslMemoryStart(TRUE);
SetAbnormalReset();
InitializeAll();
OslDumpDataInFile();
ClearInputEventHandler(MMI_DEVICE_ALL);
ClearKeyHandler(KEY_END, KEY_LONG_PRESS);
InitNvramData();
AlmReInitialize();
InitAllApplications();
mmi_pwron_exception_check_display();
break;
}
case .......
case.......
执行过开机(Power On)之后,就不会进入default这里了。
第三步、在模拟器上随便按键,就进入default这里:
default:
ProtocolEventHandler(
(U16) Message.oslMsgId,
(void*)Message.oslDataPtr,
(int)Message.oslSrcId,
(void*)Message.oslPeerBuffPtr);
break;
以上是总体的开机过程。
下面重点学习InitializeAll的具体内容:
InitializeAll();
{
InitUnicodeSupport(); //设置使用的编码函数
gdi_init(); //图形库初始
mdi_audio_init(); //音频初始化
jdi_audio_init();
InitProtocolEvents(); //初始化协议事件(函数是空的)
InitFramework(); //初始化事件的处理函数,以及histroy等。
{
InitEvents(); //Initialize event handlers
InitProcessKeyEvent(); //Initialize keyprocess
InitHistory(); //Initialize history
}
InitHardwareEvents(); //设置一些硬件事件的protocol handler。
InitTime();
InitMMI_App();
setup_UI_wrappers(); //初始化图形界面相关的参数
PopulateResData();//装载资源包括:menu, string, image---------------------重点之重点学习
{
//增加applications
ADD_APPLICATION(APP_MAINMNNU,
APP_IDLEAPP,
APP_BOOTUP,
APP_SIMTOOLKIT,
APP_GLOBALDEFS,
APP_CHARGER,
APP_UIFRAMEWORK,
APP_HONEBOOK,
APP_SHORTCUTS,
APP_SERVICES,
APP_ORGANIZER, APP_MESSAGES,
APP_CHAT,
APP_SETTINGS,
APP_CALLMANAGEMENT,
APP_DEMOAPP,
APP_CLLHISTORY,
APP_CALLSETUP,
APP_PROFILES,
APP_NEWORKSETUP,
APP_DATAACCOUNT,
APP_PHONESETUP,
APP_TODOLIST,
APP_INPUTMETHOD......);
装载每一个application的资源(MUNE, IMAGE, STRING)
(1)PopulateNFBProgressImg(); //0—9及其他的image
(2)PopulateGlobalData();
装载全局资源:主要就是加载字串ADD_APPLICATION_STRING2和加载图像ADD_APPLICATION_IMAGE2。注意:有很多image的图像是空的,即在显示时,即使设置了显示的image ID,但还是没有图片。只有STRING。
(3)PopulateMainMenuRes();
在代码中有3个此函数,利用宏的控制以达到不同的应用。GW606进入的是中间的这个函数,即:
宏 __MMI_BI_DEGREE_MAIN_MENU_STYLE__ 关闭,
宏 __MMI_VERSION_2__ 打开。
加载左软件开始进入的九宫图MENU。
ADD_APPLICATION_MENUITEM((
IDLE_SCREEN_MENU_ID,0,9,
MAIN_MENU_PHONEBOOK_MENUID,
MAIN_MENU_MESSAGES_MENUID,
MAIN_MENU_CALL_HISTORY,
MAIN_MENU_SETTINGS_MENUID,
MAIN_MENU_MULTIMEDIA_MENUID,
MAIN_MENU_FILE_MNGR_MENUID,
MAIN_MENU_PROFILES_MENUID,
MAIN_MENU_EXTRA_MENUID,
MAIN_MENU_SERVICES_MENUID,
0,
INSERTABLE,
MATRIX_MENU
MAIN_MENU_MENU_TEXT,
MAIN_MENU_PHONEBOOK_ICON));
装载电话簿的MENU(SIM卡有效)
ADD_APPLICATION_MENUITEM((MAIN_MENU_PHONEBOOK_MENUID。。。
装载电话簿的MENU(SIM卡无效)
ADD_APPLICATION_MENUITEM((MAIN_MENU_PHONEBOOK_NO_SIM_MENUID。。。
装载通话记录的MENU
ADD_APPLICATION_MENUITEM((MAIN_MENU_CALL_HISTORY。。。
装载功能设置的MENU
ADD_APPLICATION_MENUITEM((MAIN_MENU_SETTINGS_MENUID。。。
装载没有SIM卡时,电话设置的MENU
ADD_APPLICATION_MENUITEM((MAIN_MENU_SETTINGS_NO_SIM_MENUID,MENU_SIM_OPTION_ID,。。。
装载多媒体娱乐的MENU
ADD_APPLICATION_MENUITEM((MAIN_MENU_MULTIMEDIA_MENUID
装载文件管理的MENU
ADD_APPLICATION_MENUITEM((MAIN_MENU_FILE_MNGR_MENUID。。。
装载网络服务的MENU
ADD_APPLICATION_MENUITEM2((MAIN_MENU_SERVICES_MENUID。。。
装载工具箱的MENU
ADD_APPLICATION_MENUITEM((MAIN_MENU_EXTRA_MENUID。。。
到这里,就装载了九宫图的MENU,以及其其大部分MENU的child MENU。
红色的两个:MAIN_MENU_MESSAGES_MENUID(信息), MAIN_MENU_PROFILES_MENUID(情景模式)没有装载其child MENU。
加载以上MENU中需要使用的STRING和IMAGE。
(4)PopulateIdleMenuRes();加载IDLE application使用的资源
{
PopulateStatusIconResources(); 加载IDLE界面的image
PopulateCommonCategoryResources();
PopulateThemeResources();
}
(5)PopulatePbResData (); Populate phone book resource data
加载【电话簿】中的每个EMNU的child menu,stirng,image。
(6)PopulateMainDemoRes(); Populating Main Demo Resources
(7)populateSettingMenu(); Populating Setting Resources
加载【功能设置】中的每个child menu的各种资源。包括:话机设置,通话设置,网络设置,GPRS连接设置,安全设置,恢复出厂值,音效,蓝牙。
{
加载[话机设置]的child menu,string和image,以及下一层…的child menu,stirng,image。
ADD_APPLICATION_MENUITEM((MENU9102_INITIAL_SETUP。。。
PopulateNetworkSetupResData(); //加载【网络设置】资源
populateManageCalls(); //加载【通话设置】资源
PopulatePhoneSetupResData(); //刚进入populateSettingMenu()的时候,加载了【话机设置】中一部分的资源。更多的资源是在这个函数中加载的。
populateSecuritySetup(); //加载【安全设置】资源
PopulateLanguageStrings();
#ifdef __MMI_SOUND_EFFECT__
PopulateSoundEffectResData();
#endif
#ifdef __FLIGHT_MODE_SUPPORT__
PopulateFlightModeResData();
PopulateConnectSetting();
#endif
}
(8)populateFunAndGamesMenu(); Populating Fun & Games Resources
(9)PopulateSimDetectionMenuRes(); Populating SIM Detect Resources
(10)PopulateChgrPwrOnScrRes(); Populating Charger Power On
(11)PopulateCommonScreensResData(); Populating Common Screen
(12)PopulateEMSObjectResources(); Populating EMS object Resources
(13)PopulateCmResData(); Populating CM Resources
加载通话过程中使用的各种资源
首先加载来电时,各种状态下的资源:MENU,STIRNG,IMAGE
然后调用PopulateCmOutResData();加载呼出电话时各种资源
(14)PopulateQuickAccessData(); Populating Quick Access Resources
(15)PopulateInputMethodRes(); Populating Input Method Resources
(16)PopulateprofileMenu(); Populating Profiles Resources
。。。。。。
//加载资源结束
}//?PopulateResData
PopulateResGetBaseIDTable();
PowerAndEndKeyHandler(); //sets power key & end key handlers
}//?InitializeAll
MMI部分流程
通过VC模拟器调试,整理出一条大概的MMI开机流程,后续完善。
备注:参考文档《MMI Platform Source Code Training.pdf》,以下部分通过VC模拟器调试:
①- 创建MMI task进程mmi_create()
②- MMI task初始化MMI_Init()mmi_frm_init_key_event() // 按键初始化L4InitTimer() // 计时器初始化setup_UI_wrappers() // WGUI初始化mmi_fe_init() // 字体初始化
③- MMI task接收消息事件MMI_task()InitEventHandlersBeforePowerOn() // 事件初始化MMI_MTPNP_master_init()以及MMI_MTPNP_slave_init() // 主副SIM卡初始化msg_get_ext_queue_info() // 获取消息mmi_frm_fetch_msg_from_extQ_to_circularQ() // 消息转换OslNumOfCircularQMsgs() // 获取消息个数OslReadCircularQ() // 读取消息信息switch (Message.msg_id){ ... case MSG_ID_MMI_EQ_POWER_ON_IND: // 开机事件 break; ...}SetDateTime() // 设置时间gdi_init() // GDI初始化switch (p->poweron_mode){ ... case POWER_ON_KEYPAD: // 按键开机 ...}MTPNP_AD_Init() // AD初始化,还不太清楚PhnsetSetUARTConfig() // UART配置DTGetRTCTime(&StartUpTime); // 获取开机时间
④- MMI 启动流程mmi_bootup_start()mmi_bootup_entry_disk_check() // 磁盘检查mmi_frm_power_on_init_procedure() // 开机初始化FlightModeCheckBeforeAnimation() // 检测飞行模式InitializeAll() // APP初始化InitNvramDataBeforeAnimation() // NV初始化
⑤- APP初始化InitializeAll()InitUnicodeSupport() // Unicodegdi_init() // GDImdi_audio_init() // AUDIOmdi_init() // MDImdi_webcam_init() // 网络摄像头InitMMIUsbContext() // USBInitProtocolEvents() // Protocol EventInitFramework() // FrameworkInitHardwareEvents() // Protocol EventInitTime() // Date Timesetup_UI_wrappers() // WGUIPopulateResData() // 资源文件,包括字符串、图片、音频等PowerAndEndKeyHandler() // Power And End Key HandleInitStringLanguage() // 多国语言mmi_um_init() // 短消息mmi_dispatch_init() // 彩信InitCallManagement() // 通话记录mmi_vt_init() // Video Telephonymmi_ucm_init() // 呼叫initialize_UI_demo() // UI环境InitNetWorkBootUpEventsCallBack() // 网络InitProfileApp() // 情景模式InitSimDetection() // SIM卡 短消息...
⑥- 初始化完成后,开机动画switch (p->poweron_mode){ ... default: ProtocolEventHandler(...); break; // 默认处理 ...}MTPNP_AD_Bootup()mmi_bootup_dual_sim_start() // SIM卡mmi_bootup_dual_sim_start_bootup_by_mode() // SIM卡MTPNP_PFAL_Master_Startup_Normal() // SIM卡PowerOnNormalMode() // 正常模式开机mmi_bootup_entry_animation() // 开机动画mmi_pwron_entry_animation_screen() // 开机动画界面gui_start_timer(force_stop_time, mmi_pwron_force_terminate_display) // 设置强制关闭动画计时器mmi_pwron_show_image_callback() // 动画完成回调EntryPhnseFactoryDefaultCalibrationScr() // 屏幕校准mmi_bootup_exit_animation() // 动画结束mmi_bootup_entry_low_battery_warning() // 检查电量mmi_bootup_entry_security_check() // 安全检查,包括SIM卡密码,SIM卡是否可用等goto_opening_screen()InitAllApplications() // 重复初始化,直接returnexit_custom_startup_screen() // 退出动画ShowWelcomeScr() // 显示welcom界面ShowIdleAppSubLcd() // 显示子屏mmi_bootup_exit_welcome_screen() // 退出welcom界面mmi_bootup_entry_network_searching() // 搜网EntryIdleScreen() // 进入待机界面