MTK task 小结 2

本文主要探讨了MTK平台中的MMI任务,它是MTK应用程序运行的核心。介绍了创建MMI任务的基本结构,包括任务入口函数、初始化函数和终止函数。MMI任务初始化简单,而入口函数则是处理外部消息和事件的关键,负责将消息放入内部队列并进行相应处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽然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                                                */
    /*----------------------------------------------------------------*/

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

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

    return MMI_TRUE;
}

初始化函数比较简单。

下面来看MMI 的入口函数,这个函数是整个MMI 运行的核心。

//为了简单,删除了大部分宏控制程序
void MMI_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 的index
                OslGetMyTaskIndex(&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 可以对应多个mod
                    if (Message.dest_mod_id == MOD_WAP)
                    {
                   
                    }
                   
                    else
                    {
                        switch (Message.msg_id)
                        {
                            //timer 消息 具体看 MTK timer 小结 2
                            case MSG_ID_TIMER_EXPIRY:
                            {
                                kal_uint16 msg_len;
                                //处理stack timer消息
                                EvshedMMITimerHandler(get_local_para_ptr(Message.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*) 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)
                                {
                                    case POWER_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;
                                    

                                    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:
                                	
                                	
                                        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) 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 机制注册的各种其他消息

(待续)

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值