MMI 中的TASK总结_task使用总结

2020-02-27 其他工作总结 下载本文

MMI 中的TASK总结由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“task使用总结”。

MMI 中的TASK总结

一:Task简介:

MTK的基本执行单元是Task.Task是一个具有一定封装性的软件模块(Module),当该模块被执行的时侯 你可以把它理解为一个独立的进程。在整个手机系统运行的过程中,有很多的Task被执行。

它可以作为“服务器”处理来自客户Task的消息并完成预定义的服务,也可以变身为“客户端”通过发送消息向其他Task请求服务。Task对于开发人员来说是透明的,开发人员不不需要关心服务的具体实现,但是开发人员必须了解Task提供的服务,这样才能更有效地利用该模块提供更强大的功能。

MTK系统有很多内置Task(如负责处理音频,视频,图像,等相关请求的MediaTask),MTK平台也允许开发人员增加处理自己业务逻辑的自定义Task。

从操作系统的角度来理解,task 有些像线程而不是进程,进程之间的地址空间是相互隔离的,说白点就是进程之间的全局变量是不相互干扰的,而线程之间则是用同一个地址空间,MTK 的task 之间的地址空间也是共同的,也就是在MTK 编程里,定义了一个全局变量,那么在任何一个task里面都能引用,(这里举个例子,在实际编程过程中最好不要用全局变量,实在没有办法避开,那么全局变量也要分模块化,进行封装,扯远了)。所以说,MTK 的task 更像线程,MTK 用的是实时操作系统 nucleus,是非抢占式操作系统,也就是当高优先级的task 在运行时,底优先级的task是得不到运行时间的,除非等高优先级的task 因为种种原因挂起。

MTK 还有一个跟task 想关的概念 叫 module,它跟task 之间的关系是:一个task 可以对应多个module。task 主要表示是一个执行单元,module 主要是用于传递消息,在MTK 中,消息传递是module 为单位 src_mod – > des_mod,而不是以task为单位。

虽然MTK手机,是feature phone(功能机),不像symbian 6 那样可以同时运行多个应用。但是MTK还是有许多task组成。平时MTK的后台播放MP3就是一由一个task 完成的。具体以后分析。现在来看看MTK 最主要的task,MMI task,MTK 的应用程序都是在该task里面运行,它有一整套开发MTK 应用的framework。

下面以MMI_task为例详细讲解。

二:创建 MMI task 的函数:

kal_bool mmi_create(comptask_handler_struct **handle){

/*--*/

/* Local Variables

*/

/*--*/

static comptask_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;

return KAL_TRUE;} 这个函数的结构,是MTK 创建task的基本结构,系统初始化时,会调用该函数。看里面的结构体:

typedef struct {

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 控制块后,就要进入该函数来运行。本例中的MMI-task函数。

task 初始化函数,是在进入 task 入口函数之前被调用,用来初始化可能需要的资源,可选。本例中的MMI-Init函数。

task 终止函数是,当task 结束是要调用,用来释放资源,可选。其他两个函数我也不清楚干什么,希望知道的共享下

三:MMI task的初始化函数MMI_Init:

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();

return MMI_TRUE;}

初始化函数比较简单。

四:MMI 的入口函数MMI_task 下面来看MMI 的入口函数,这个函数是整个MMI 运行的核心。//为了简单,删除了大部分宏控制程序

void MMI_task(oslEntryType *entry_param){

MYQUEUE Meage;

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, &Meage);

//如果有消息,获得task 的index

OslGetMyTaskIndex(&my_index);

// 设置该task的获得mod 为MMI mod.OslStackSetActiveModuleID(my_index, MOD_MMI);

//保存该消息,用于放入到内部队列

ilm_ptr.src_mod_id = Meage.src_mod_id;

ilm_ptr.dest_mod_id = Meage.dest_mod_id;

ilm_ptr.msg_id = Meage.msg_id;

ilm_ptr.sap_id = Meage.sap_id;

ilm_ptr.local_para_ptr = Meage.local_para_ptr;

ilm_ptr.peer_buff_ptr = Meage.peer_buff_ptr;

//放入内部队列

// 这个内部队列是个简单的循环队列

flag = OslWriteCircularQ(&ilm_ptr);

// 对 timer 消息进行特殊处理

if(Meage.src_mod_id!= MOD_TIMER)

{

hold_local_para(ilm_ptr.local_para_ptr);

hold_peer_buff(ilm_ptr.peer_buff_ptr);

OslFreeInterTaskMsg(&Meage);

}

}

else

{

// 把外部消息放入到内部消息

mmi_frm_fetch_msg_from_extQ_to_circularQ();

}

//处理内部消息

count = OslNumOfCircularQMsgs();

while(count > 0)

{

OslGetMyTaskIndex(&my_index);

OslStackSetActiveModuleID(my_index, MOD_MMI);

if(OslReadCircularQ(&Meage))

{

CheckAndPrintMsgId((U16)(Meage.msg_id));

//是否是 wap 的消息

// 这里就体现了一个task 可以对应多个mod

if(Meage.dest_mod_id == MOD_WAP)

{

}

else

{

switch(Meage.msg_id)

{

//timer 消息 具体看 MTK timer 小结 2

case MSG_ID_TIMER_EXPIRY:

{

kal_uint16 msg_len;

//处理stack timer消息

EvshedMMITimerHandler(get_local_para_ptr(Meage.oslDataPtr, &msg_len));

}

break;

//开机消息

//具体分析 见后文

case MSG_ID_MMI_EQ_POWER_ON_IND:

{

mmi_eq_power_on_ind_struct *p(mmi_eq_power_on_ind_struct*)Meage.oslDataPtr;

=

/* To initialize data/time */

SetDateTime((void*)&(p->rtc_time));

gdi_init();

g_pwr_context.PowerOnMMIStatus MMI_POWER_ON_INDICATION;

switch(p->poweron_mode)

{

case POWER_ON_KEYPAD:

OslMemoryStart(MMI_TRUE);

g_charbat_context.PowerOnCharger 0;

g_pwr_context.PowerOnMode POWER_ON_KEYPAD;

DTGetRTCTime(&StartUpTime);

memset(&LastDuration, sizeof(LastDuration));

mmi_bootup_entry_disk_check();

break;

case POWER_ON_PRECHARGE:

case POWER_ON_CHARGER_IN:

g_pwr_context.PowerOnMode p->poweron_mode;

InitializeChargingScr();

if(!g_charbat_context.isChargerConnected)

{

QuitSystemOperation();

}

break;

case POWER_ON_ALARM:

=

= =

0,=

g_pwr_context.PowerOnMode = POWER_ON_ALARM;

gdi_layer_clear(GDI_COLOR_BLACK);

AlmInitRTCPwron();

break;

case POWER_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)Meage.oslMsgId,(void*)Meage.oslDataPtr,(int)Meage.oslSrcId,(void*)&Meage);

break;

}

}

OslFreeInterTaskMsg(&Meage);

}

msg_get_ext_queue_info(mmi_ext_qid, &queue_node_number);

count--;

}

}

} } MMI task 的工作方式:从外部队列获取消息放入内部消息队列,内部消息队列根据消息类型注册的回调函数,进行调用(event 机制,这个又是MMI framework的主要部分之一)。

四;创建一个Task 在MTK上,用户(开发人员)可以根据需要,创建task。创建一个task 分为 4 步:增加一个task index 到 custom_task_indx_type。增加一个mod index 到 custom_module_type。把mod 关联到 相应的 task上,因为一个task 可以对应多个mod,所以需要把mod 挂载到 task上。(用挂载这个词,应该就比较好理解了,task 是MTK 执行的基本单位,所以一个mod 要能独立运行,就要挂载到某个task 上,为什么不一个mod一个task呢,我想task越多,多系统效率影响就越大。那么就可以考虑互斥的mod 挂载到一个task上,反正互斥的,不会同时需要运行,就像音乐,视频,照相机一样,不会同时运行)。创建 task 基本信息 到 custom_comp_config_tbl。下面来具体看一个例子:

1: 添加 task indextypedef enum(在sysGen1.pl文件中)

{

INDX_CUSTOM1 = RPS_CUSTOM_TASKS_BEGIN,INDX_CUSTOM2, #ifdef TASK_CREATE_TEST

INDX_TASK_TEST, #endif

RPS_CUSTOM_TASKS_END } custom_task_indx_type;

我们增加了一个 task index INDX_TASK_TEST添加一个 mod index(在sysGen1.pl文件中)typedef enum {

MOD_CUSTOM1 = MOD_CUSTOM_BEGIN,MOD_CUSTOM2, #ifdef TASK_CREATE_TEST

MOD_TASK_TEST, #endif

MOD_CUSTOM_END } custom_module_type;我们增加了一个mod index MOD_TASK_TEST 挂载mod 到 task上(在sysGen1.pl文件中)

custom_task_indx_type custom_mod_task_g[ MAX_CUSTOM_MODS ] = {

INDX_CUSTOM1,/* MOD_CUSTOM1 */

INDX_CUSTOM2,/* MOD_CUSTOM2 */ #ifdef TASK_CREATE_TEST

INDX_TASK_TEST, #endif

INDX_NIL

/* Please end with INDX_NIL element */ };这样就把 MOD_TASK_TEST 挂载到 INDX_TASK_TEST上面了,这里的映射关系是通过index 来控制的,也就是说要的到MOD_TASK_TEST 对应的 task index,只要这样 task index = custom_mod_task_g[MOD_TASK_TEST];,所以创建过程中,顺序一定要对应好,不然容易出错。---------------------------4 创建task 信息(在sysGen1.pl文件中)

const comptask_info_struct custom_comp_config_tbl[ MAX_CUSTOM_TASKS ] = {

/* INDX_CUSTOM1 */

{“CUST1”, “CUST1 Q”, 210, 1024, 10, 0, #ifdef CUSTOM1_EXIST

custom1_create, KAL_FALSE #else

NULL, KAL_FALSE #endif

},/* INDX_CUSTOM2 */

{“CUST2”, “CUST2 Q”, 211, 1024, 10, 0, #ifdef CUSTOM2_EXIST

custom2_create, KAL_FALSE #else

NULL, KAL_FALSE #endif

}, #ifdef TASK_CREATE_TEST

/* INDX_TASK_TEST */

{“TAST_TEST”, “TASK_TEST Q”, 212, 1024, 10, 0,task_test_create, KAL_FALSE

}, #endif };这样就创建好了task 的信息,这里说task 需要的信息 typedef struct {

kal_char

*comp_name_ptr;//task 的name

kal_char

*comp_qname_ptr;//外部队列name

kal_uint32

comp_priority;

//优先级

kal_uint16

comp_stack_size;//stack 大小

kal_uint8

comp_ext_qsize;//外部队列大小

kal_uint8

comp_int_qsize;//内部队列大小

kal_create_func_ptr comp_create_func;//task 创建函数

kal_bool

comp_internal_ram_stack;//是否是internal_ram_stack } comptask_info_struct;

task 的优先级是数值越大,优先级越低。由于是MTK 用的是实时操作系统,高优先级的task 只要需要,就会先运行,一直运行,所以task的优先级定义时需要考虑清楚。comp_internal_ram_stack 表示是否使用internal ram stack,internal ram 相对速度要快,但是数量很有限,一般自己创建的不要去使用,容易引起问题。

更详细的Task创建过程可以参考 《《走出山寨-MTK芯片开发指南 第八章 Task》》!

《MMI 中的TASK总结.docx》
将本文的Word文档下载,方便收藏和打印
推荐度:
MMI 中的TASK总结
点击下载文档
相关专题 task使用总结 MMI task task使用总结 MMI task
[其他工作总结]相关推荐
    [其他工作总结]热门文章
      下载全文