虽然MTK手机,是feature phone(功能机),不像symbian 6 那样可以同时运行多个应用。但是MTK还是 有许多task组成。平时MTK的后台播放MP3就是一由一个task 完成的。具体以后分析。现在来看看MTK 最主要的task,MMI task,MTK 的应用程序都是在该task里面运行,它有一整套开发MTK 应用的framework。
先来看创建MMI task的函数
kal_bool mmi_create(comptask_handler_struct **handle) {/*----------------------------------------------------------------*//* Local Variables *//*----------------------------------------------------------------*/staticcomptask_handler_struct mmi_handler_info = { MMI_task,/* task entry function */MMI_Init,/* task initialization function */NULL, NULL,/* task reset handler */NULL,/* task termination handler */};/*----------------------------------------------------------------*//* Code Body *//*----------------------------------------------------------------*/*handle = &mmi_handler_info;returnKAL_TRUE; }这个函数的结构,是MTK 创建task的基本结构,系统初始化时,会调用该函数。看里面的结构体
typedefstruct{ kal_task_func_ptr comp_entry_func; //task 的入口函数 task_init_func_ptr comp_init_func; //task 的初始化函数 task_cfg_func_ptr comp_cfg_func; //task 的配置函数 task_reset_func_ptr comp_reset_func; //task 的重置函数 task_end_func_ptr comp_end_func; //task 的终止函数 } comptask_handler_struct;task 的入口函数是必须的,这个函数告诉系统,初始化完相应的task 控制块后,就要进入该函数来运行。
task 初始化函数,是在进入 task 入口函数之前被调用,用来初始化可能需要的资源,可选。
task 终止函数是,当task 结束是要调用,用来释放资源,可选。
其他两个函数我也不清楚干什么,希望知道的共享下
先看MMI task 的初始化函数.
MMI_BOOL MMI_Init(task_indx_type task_indx) {//创建一个mutex(互斥体)mmi_mutex_trace = kal_create_mutex("mmi_trace");//这个是初始化 2step 按键, 2step 按键是指 有一些按键具有半按下状态//比如照相功能,按下一半进行聚焦,再按下一半拍照mmi_frm_get_2step_keys();//初始化timer,具体可以看MTK timer 小结 系列L4InitTimer();//初始化 UI 相关信息,里面有许多画点,图等函数setup_UI_wrappers();returnMMI_TRUE; }
初始化函数比较简单。
下面来看MMI 的入口函数,这个函数是整个MMI 运行的核心。
//为了简单,删除了大部分宏控制程序voidMMI_task(oslEntryType *entry_param) { MYQUEUE Message; oslMsgqid qid; U32 my_index; U32 count = 0; U32 queue_node_number = 0;// 获得task的外部消息队列id,通过这个id,获得别的task 往MMI task发送的消息// MMI task 有两个消息,外部消息队列和内部消息队列// 外部消息队列的消息不直接处理,只是简单的存放到内部消息队列,// 这样使内部消息队列的优先级稍微高一点qid = task_info_g[entry_param->task_indx].task_ext_qid; mmi_ext_qid = qid;// 初始化 event 处理函数,这个几个event 必须在获得消息前就进行注册// 不让可能使得这个event 丢弃。具体event 事件,下次介绍InitEventHandlersBeforePowerOn();//进入task 的while 循环// task 的while(1) 循环使得这个task 不会结束,只有挂起或者运行while(1) { {// 判断是否有 key 事件需要处理if(g_keypad_flag == MMI_TRUE) { mmi_frm_key_handle(NULL); }// 获得外部消息队列里,消息的个数msg_get_ext_queue_info(mmi_ext_qid, &queue_node_number);// 如果没有任何消息需要处理(内部消息和外部消息都没有,同时也没有按键需要处理)// OslNumOfCircularQMsgs 获得内部消息队列消息的个数if((queue_node_number == 0) && (OslNumOfCircularQMsgs() == 0) && (g_keypad_flag == MMI_FALSE)) { U8 flag = 0; ilm_struct ilm_ptr;//去外部消息队列里获得消息,这是一个阻塞函数,也就是说,如果外部消息队列里,//没有任何消息,那么这个task 将被阻塞,或者说挂起,也就是不在运行,//直到有消息到达,才会被唤醒, 看过操作系统原理的,应该不难理解这个意思和这个本质OslReceiveMsgExtQ(qid, &Message);//如果有消息,获得task 的indexOslGetMyTaskIndex(&my_index);// 设置该task的获得mod 为MMI mod.OslStackSetActiveModuleID(my_index, MOD_MMI);//保存该消息,用于放入到内部队列ilm_ptr.src_mod_id = Message.src_mod_id; ilm_ptr.dest_mod_id = Message.dest_mod_id; ilm_ptr.msg_id = Message.msg_id; ilm_ptr.sap_id = Message.sap_id; ilm_ptr.local_para_ptr = Message.local_para_ptr; ilm_ptr.peer_buff_ptr = Message.peer_buff_ptr;//放入内部队列// 这个内部队列是个简单的循环队列flag = OslWriteCircularQ(&ilm_ptr);// 对 timer 消息进行特殊处理if(Message.src_mod_id != MOD_TIMER) { hold_local_para(ilm_ptr.local_para_ptr); hold_peer_buff(ilm_ptr.peer_buff_ptr); OslFreeInterTaskMsg(&Message); } }else{// 把外部消息放入到内部消息mmi_frm_fetch_msg_from_extQ_to_circularQ(); }//处理内部消息count = OslNumOfCircularQMsgs();while(count > 0) { OslGetMyTaskIndex(&my_index); OslStackSetActiveModuleID(my_index, MOD_MMI);if(OslReadCircularQ(&Message)) { CheckAndPrintMsgId((U16) (Message.msg_id));//是否是 wap 的消息// 这里就体现了一个task 可以对应多个modif(Message.dest_mod_id == MOD_WAP) { }else{switch(Message.msg_id) {//timer 消息 具体看MTK timer 小结 2caseMSG_ID_TIMER_EXPIRY: { kal_uint16 msg_len;//处理stack timer消息EvshedMMITimerHandler(get_local_para_ptr(Message.oslDataPtr, &msg_len)); }break;//开机消息//具体分析 见后文caseMSG_ID_MMI_EQ_POWER_ON_IND: { mmi_eq_power_on_ind_struct *p = (mmi_eq_power_on_ind_struct*) Message.oslDataPtr;/* To initialize data/time */SetDateTime((void*)&(p->rtc_time)); gdi_init(); g_pwr_context.PowerOnMMIStatus = MMI_POWER_ON_INDICATION;switch(p->poweron_mode) {casePOWER_ON_KEYPAD: OslMemoryStart(MMI_TRUE); g_charbat_context.PowerOnCharger = 0; g_pwr_context.PowerOnMode = POWER_ON_KEYPAD; DTGetRTCTime(&StartUpTime); memset(&LastDuration, 0,sizeof(LastDuration)); mmi_bootup_entry_disk_check();break;casePOWER_ON_PRECHARGE:casePOWER_ON_CHARGER_IN: g_pwr_context.PowerOnMode = p->poweron_mode; InitializeChargingScr();if(!g_charbat_context.isChargerConnected) { QuitSystemOperation(); }break;casePOWER_ON_ALARM: g_pwr_context.PowerOnMode = POWER_ON_ALARM; gdi_layer_clear(GDI_COLOR_BLACK); AlmInitRTCPwron();break;casePOWER_ON_EXCEPTION: g_pwr_context.PowerOnMode = POWER_ON_EXCEPTION; gdi_layer_clear(GDI_COLOR_BLACK); OslMemoryStart(MMI_TRUE); SetAbnormalReset(); InitializeAll(); OslDumpDataInFile(); ClearInputEventHandler(MMI_DEVICE_ALL); ClearKeyHandler(KEY_END, KEY_LONG_PRESS); InitNvramData(); InitAllApplications(); mmi_pwron_exception_check_display();break;default:break; } }break;// event 时间,这个也是MMI task 的一个重点default: ProtocolEventHandler( (U16) Message.oslMsgId, (void*)Message.oslDataPtr, (int)Message.oslSrcId, (void*)&Message);break; } } OslFreeInterTaskMsg(&Message); } msg_get_ext_queue_info(mmi_ext_qid, &queue_node_number); count--; } } } }
MMI task 内容比较多,删除了一些代码,留下主要的骨干。
总体来看,1 把外部消息放入内部消息队列
2 处理各种消息,开机消息,按键消息 和event 机制注册的各种其他消息
原文转载自:http://blog.youkuaiyun.com/yanwuxufeng/article/details/5762361