MTK平台是非常优秀的一个平台,曾经的山寨机之父,下面我将介绍下在MTK平台下如何去创建自己的任务。
一、基础知识
在学习如何创建任务之前,我们需要了解一些基本概念,以及一些和任务相关的数据结构,了解了这些之后,我们就能更好的理解如何去创建任务了。MTK中关于任务的概念有两个,一个是TASK,另外一个则是MODULE,这两个有什么区别呢,task是操作系统层面的概念,MTK使用的是nucleus plus实时操作系统,其任务即TASK可以理解为一个线程,而一个TASK下面可以有很多的MODULE,MODULE是软件平台设计者因为某种需要而设计的。TASK是一个执行单元,MODULE主要是用于传递消息,在MTK中,消息传递是以MODULE为单位src_mod -> des_mod,而不是以TASK为单位。MTK并不支持动态的创建任务,所以任务的创建是静态的,需要事先定义好。而且任务的创建函数对程序开发人员来说是不可见的,MTK提供了几张数据表,让开发人员来装填,装填好这几张表之后,系统就会自动创建我们想要创建的任务了。cunstomer_config.h文件中的枚举类型数据结构custom_task_indx_type、custom_module_type,前面一个枚举类型是用来定义任务索引的,后面的一个枚举类型是用来定义MOD索引的,开发人员新定义的任务时,需要在这个地方添加新的索引。另外一个文件就是customer_config.c文件中的custom_task_index_type类型的变量,custom_mod_task_g变量的装填,这一步的作用主要就是将一个MOD和一个任务关联起来,即将MOD挂载到TASK上面。
MTK创建TASK的基本结构体:
typedef struct
{
kal_char *comp_name_ptr; ----- 任务的名称
kal_char *comp_qname_ptr; ----- 任务所属队列的名称
kal_uint32 comp_priority; ----- 任务的优先级,0~255
kal_uint16 comp_stack_size; ----- 任务堆栈的大小
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;comp_internal_ram_stack相对速度要快,但是数量有限,一般自己创建的任务不要去使用,容易引起问题。
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结束是要调用,用来释放资源,可选。
二、任务的创建过程
有了上面的基础知识,再创建MTK的任务时,理解起来就容易多了,创建任务主要分为以下的几个
步骤:
第一步:增加一个task index到custom_config.h中的枚举类型custom_task_indx_type中。
第二步:增加一个mode index到custom_config.h中的枚举类型custom_module_type中。
第三步:把mod和task进行关联,因为一个task可以对应多个mod,所以需要将mod挂载到
task上,挂载的方法是在custom_config.c中的
custom_mod_task_g[ MAX_CUSTOM_MODS ]数组中添加刚刚在第一步中所增加
的那个task index,这样就能够通过mode index索引到相应的task index,也就建
立了二者的对应关系。
第四步:添加task基本信息到custom_config.c中的custom_comp_config_tbl中。
第五步:上面的各种数据信息装填完毕之后,接下来就开始编写自己的任务的实现的函数。
三、任务创建的举例说明
如果我们想创建一个任务名称为FD_TEST4 ,优先级为219,堆栈大小为4096 byte的任务,采用
如下的方法来创建这个任务:
第一步:添加TASK INDEX
typedef enum
{
INDX_CUSTOM1 = RPS_CUSTOM_TASKS_BEGIN,
INDX_CUSTOM2,
#ifdef __FLAVOR_VENDOR_SDK__
INDX_VS,
#endif// LXL
INDX_FD_TEST4, ----- 此处添加TASK INDEX
RPS_CUSTOM_TASKS_END
} custom_task_indx_type;第二步:添加MOD INDEX
typedef enum
{
MOD_CUSTOM1 = MOD_CUSTOM_BEGIN,
MOD_CUSTOM2,
#ifdef __FLAVOR_VENDOR_SDK__
MOD_VS,
#endifMOD_FD_TEST4, ----- 在此处添加MODE INDEX
MOD_CUSTOM_END
} custom_module_type;第三步:将MOD挂载到TASK上
custom_task_indx_type custom_mod_task_g[ MAX_CUSTOM_MODS ] =
{
INDX_CUSTOM1, /* MOD_CUSTOM1 */
INDX_CUSTOM2, /* MOD_CUSTOM2 */
#ifdef __FLAVOR_VENDOR_SDK__
INDX_VS,
#endifINDX_FD_TEST4,
INDX_NIL /* Please end with INDX_NIL element */
};
第四步:装填创建人物的数据结构
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
},// 此处添加TASK任务的数据结构信息
{"FD_TEST4", "FD_TEST4_Q", 219, 1024, 30, 0, fd_test4_create, KAL_FALSE}
};
第五步:编写任务的创建函数fd_test4_create
kal_bool fd_test4_create(comptask_handler_struct **handle)
{
static const comptask_handler_struct custom_handler_info =
{
fd_test4_fun, /* task entry function */
NULL, /* task initialization function */
NULL, /* task configuration function */
NULL, /* task reset handler */
NULL, /* task termination handler */
};
*handle = (comptask_handler_struct *)&custom_handler_info;
return KAL_TRUE;
}注意此函数的返回值,入口函数是固定的,因为这个函数是在任务创建时由系统自动
调用的,而我们想要实现的功能,则在函数fd_test4_fun中实现。
四、结束
上面就是MTK任务的创建过程,我也是刚开始接触这个平台,还有很多不懂的地方,如果有说的
不对的地方,希望大家能够指出来,一起进步。