MTK 内存 任务管理和定时器消息机制

来源:互联网 发布:2016社交媒体数据分析 编辑:程序博客网 时间:2024/06/05 01:03

声明:资料来源于一个好友


1 内存管理。

 

平台不提供动态分配内存的方式;应用程序需要使用动态分配内存时,可以采用以下几种方式:

与系统其他模块共享内存,典型的是使用MED模块的内存;

定义一个静态数组,交给系统adm托管,然后调用kal_adm_alloc、kal_adm_free等内存操作函数实现动态内存分配;

定义一个静态数组,应用自己实现基于此数组的分配和管理,也就是实现自己的内存管理模块。

 

   在MTK的资料中,介绍了它的内存管理机制,有3种:ADM、Control buffer、System Memory。后两个是系统使用的,与上层应用无关。但是我对kal_system_alloc也做了初步分析。

 

   sys_mem_ptr,其估计应该指向的是 System_Mem_Pool,       debug_mem_ptr,其估计应该指向的是 debug_Mem_Pool。       经过初步分析,kal_system_alloc就是从System_Mem_Pool做简单的加法操作,sys_mem_left_size就是 System_Mem_Pool还剩下多少。kal_system_alloc从sys_mem_ptr开始来计算要取的内存。ctrl_buf是通过 kal_system_alloc的内存,然后再通过NU_Create_Partition_Pool创建POOL。系统的一些task stack.等也都是通过kal_system_alloc来分配的。

 

   也就是说,Control buffer、System Memory用的都是System_Mem_Pool的空间。而System_Mem_Pool可以查到,是在custom_configmem函数中配置。

 

ADM就完全没有使用操作系统提供的内存管理算法,是平台自创了一套。开发者,可以自己开辟一个POOL,自己在这个池用ADM提供的内存管理API完成内存的动态管理。具体的分配算法,就没有再细看,跟一些通用的内存分配算法应该一致。但是在以前调试一个问题的时候,应该是可以断定,ADM在每一个alloc node前后都加了GAP调试区,来判断是否被overwrite。

 

   至于系统中,到底是用了多少块内存用于ADM,各块内存又是让哪些应用在共享,开发者可能更清楚。在系统中是否建立了对内存动态分配的监控机制,比如查询内存泄漏、动态内存使用效率等等。

 

3

少于2K 使用get_ctrl_buffer。

大于2K 使用adm

get_ctrl_buffer是在系统定义的一块区域申请空间。 这段空间被分为好多块均等大小。好像有以下几种方式:

2个 1K*2

4个 0.5K*4

6个 0.25K*8

....

申请的话,按首适应算法。这就是你所说的小块内存管理。

adm主要是你自己定义的一块全局数组比如400K.

你可以使用它的adm相关函数去动态申请释放这400K大小的区域,维护也靠你自己。

 

 

2.任务管理

 

 


任务管理。系统任务采用静态创建方式,静态配置任务优先级、栈大小、任务全局唯一ID等;不提供动态创建Task的方式;任务内部以及任务之间的通信通过内部事件队列和外部事件队列完成

Application_Initialize中的mainp函数,负责任务的创建。我们在代码中见不到任务创建的函数,只需要维护任务初始化参数数据结构。对于系统的那些task信息,都保存在sys_comp_config_tbl变量中,我们看不到。但是MTK提供给客户的custom_comp_config_tbl,客户是可以修改的,在这里用户可以定义自己的task。

关于任务,需要关心数据结构comptask_handler_struct。关于comptask_handler_struct成员的执行顺序,应该是:comp_init_func 在系统还未 schedule 即在Application_Initialize中完成,然后task schedule后执行comp_entry_func。comp_cfg_func、comp_reset_func、comp_end_func我认为无太多意义。

 

 

3.定时器消息机制

 


MTK定时器消息机制分析

1.   数据结构

     (1). stack_timer_struct

          定时器类型的信息结构( 其主要作用似乎是用以装载待发送的定时器消息数据 )

     (2). TIMERTABLE

          定时器队列节点结构( 其由主要元素mmi_frm_timer_type结构及链表指针两个元素组成 )

     (3). event_scheduler

          队列信息结构

     (4). mmi_frm_timer_type

          定时器信息结构

2.   L4定时器初始化

     (1). 步骤

          ...-> 创建MMI Task -> 设置MMI Task初始化函数 -> 在该函数中调用 L4InitTimer

     (2). 作用

          初始化定时器队列并设置基本定时器1,2

3.   发送定时器消息

     (1). 步骤

          StartTimer -> L4StartTimer

     (2). 两种类型的定时器

          MTK中有两种类型的定时器

          a. NO_ALIGNMENT

              非队列式的,即要求立即执行的定时器,时间到了就自动被reset.

          b. ALIGNMENT

              队列式的, 即可以通过队列操作,有一定的延时容忍的定时器 .                         

              其基本执行流程: 执行定时器 --> 超时? --> 保存timer id,event id -- timer stop || no event ?----> END ;

 

                         


          c. 除了触摸屏和手写,其他情况下的定时器一般都是队列式的.                                                                                     

                                                                                                         

     (3). L4StartTimer的作用

          判断将要发送的定时器ID,根据是否是队列类型传递给不同的队列结构(event_sheduler1/event_sheduler2) ;

     (4). TimerExpiry

              这是作为参数传递给L4StartTimer的回调函数,由于MTK做了一定的封装,因此其内部具体回调触发过程

          无法得知,但根据猜测,应该是在定时时间一到,以中断的方式发出消息(MSG_ID_TIMER_EXPIRY),并将其写到

          MMI的循环队列.

              该函数可能是在L4CallBackTimer中调用的,L4CallBackTimer的作用如下:

              a. 重置当前定时器信息结构(mmi_frm_timer_type) ;

              b. 执行定时器到点后的执行函数(TimerExpiry) ;

              c. 讲Timer消息写到MMI循环队列中 .

4.   与StartTimer对应的StopTimer

     (1). 具体实现通过调用L4StopTimer操作.

     (2). 作用: 找出指定要停止的定时器ID在队列中的位置,然后使用evshed_cancel_event将指定定时器节点从队列

                中删除.

              

5.   定时器消息的处理

     (1). 步骤

          ...-> 创建MMI Task -> 设置MMI Task入口函数 -> 调用 EvshedMMITimerHandler

     (2). evshed_timer_handler( ) -> 处理具体的定时器事件

   

6.   小结

     简单分析MTK定时器消息事件,由于只是简单的分析,谬误定然甚多,忘包涵包涵并不吝指正

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiangyu912/archive/2010/07/29/5773095.aspx