MTK 手机开发小技巧

声明: 资料根据公司培训及公司同事整理所得

 

 

(1)   插上USB线后将某块区域虚拟成一个U盘的代码位置

(2)   scatte文件简介和romram超的一般处理

(3)   四类timer介绍

(4)   Task

(5)   RATECH53_09A_GPRS.mak文件(文件名因项目而异)内容介绍

(6)   光电鼠的实现思路

(7)   触屏响应机制。

等。

下半场主要讲解wap profile相关内容。

 

(1)插上USB线后将某块区域虚拟成一个U盘的代码位置

在函数usb_task_init()调用的custom_usb_ms_init()

USB_Ms_Register_DiskDriver(&USB_SIMPLUS_drv);

USB_Ms_Register_DiskDriver(&USB_MSDC_drv);

USB_Ms_Register_DiskDriver(&USB_RAM_drv);

USB_Ms_Register_DiskDriver(&USB_NOR_drv);

USB_Ms_Register_DiskDriver(&USB_NAND_drv);

 

(2) scat文件简介和romram超出的常规处理

Description: defines the memory map for the validation board.简单地说,要生成目标映像文件,armlink必须知道以下两个信息:1. input sectionoutput section之间的对应关系。2.region在加载时空间和运行时空间的地址。

目前,有两种方法可以将这些信息提供给armlink

1.arm 命令行选项

2.scatter文件:对于复杂的映像文件,可以使用scatter文件,通过命令行-scatter

filename 命令指定对应的scatter文件,armlink会解析指定的scatter文件来获得信息。

具体请参考资料文档Scatter文件简介v1.0.pdf,这里仅列举海焦讲解完后提的2个问题

1、ROM里面存放什么?超了怎么办?

Code+RW(已初始化的全局变量)+RO (只读数据如图片等)

超了一般会压缩那些较大的图片,也就是减小RO占用的空间。

2、RAM里面存放什么?超了怎么办?

如果是nor flashram里存放的是RW(初始化的全局变量)/ ZI(未初始化的全局变量),带const的全局变量属于RO,并不占用RAM 空间。对于nand flash,由于nand flash 不支持XIP,所以RAM 里面要分一部分来存放CODE,其余情况同nor flash+RAM 配置。

ram超了要看超多少,一般是关用ram多的功能。

但是超得不多,比如几十K,那么我们就去处理几个大buffer。一般我们只处理 med_ext_mem[MED_EXT_MEM_SIZE] wap_mem, 对于那个app_mem,很少处理。

(3)四类timer介绍

1void StartTimer(U16 timerid, U32 delay, FuncPtr funcPtr)

       特点:带ID,精准度不高。

2void gui_start_timer (S32 count, void (*callback) (void))

       特点:不带ID,精准度不高。

3void kal_set_timer(kal_timerid timer_id, kal_timer_func_ptr handler_func_ptr, void* handler_param_ptr, kal_uint32 delay, kal_uint32 reschedule_time);

       特点:参数较多,最后两个参数单位不是ms,而是ticks,精准度颇高。用于跑马灯等。

4gpt timer。用得较少。

 

(4) Task

Task是有一定封装性的软件模块,当此模块被执行的时候,可以把它理解为一个独立的线程。Task之间的交流可以理解成线程间通信。大家以后可能要独立完成一个task的设计,以应付一些比较高级的应用开发。

1task的创建:

MTK提供了自定义task的接口,首先要在custom_config.h文件中的custom_task_indx_typecustom_module_type这两个枚举类型中分别加入我们自己的task_indexmodule id

其次在custom_config.c中的custom_mod_task_g[]这个数组中定义中增加moudletask的映射。需要注意这个数组的成员个数不能超MAX_CUSTOM_MODS,即MTK只支持16个自定义task

       然后需要在task配置表custom_comp_config_tbl[]中增加task的配置信息。这个结构体的成员组成如下:

typedef struct {

   kal_char             *comp_name_ptr; //task名称

   kal_char             *comp_qname_ptr;//外部队列名称

   kal_uint32           comp_priority;//task优先级

   kal_uint16           comp_stack_size;//task堆栈大小

   kal_uint8            comp_ext_qsize;//外部队列大小

   kal_uint8            comp_int_qsize;//内部队列大小

   kal_create_func_ptr    comp_create_func;//创建task的入口函数

   kal_bool             comp_internal_ram_stack;

} comptask_info_struct;

       接下来是比较关键的task创建函数的实现。这个函数的返回值是kal_bool,参数是comptask_handle_struct**,显然这是一个out型的结构体二级指针,需要我们在函数内部对这个结构体指针赋值。而我们可以看到这个结构体的成员组成如下:

typedef struct {

   kal_task_func_ptr    comp_entry_func;//主函数,它的实现是一个消息循环

   task_init_func_ptr   comp_init_func;//配置函数

   task_cfg_func_ptr    comp_cfg_func;//初始化函数

   task_reset_func_ptr  comp_reset_func;//重置函数

   task_end_func_ptr    comp_end_func;//task结束时调用的函数

} comptask_handler_struct;

       所以在task创建函数里我们只要定义一个comptask_handler_struct类型的结构体,里面填充好上述几个函数指针,然后将其地址赋给函数传进来的参数即可。最后返回

KAL_TRUE

 

 

2task的消息循环

 

前面已经讲到的comp_entry_func主函数,它的实现是一个消息循环,简单讲,我们不断从外部消息列表中获取消息,使用的函数为

 

kal_status receive_msg_ext_q( kal_msgqid task_ext_qid, ilm_struct *ilm_ptr);然后我们去实现消息的分发处理。据说开发过程中有时候还有task内部的消息需要处理,使用的是另外一个函数receive_msg_int_q从内部消息队列获取消息,这部分需要再去体会。手上的53平台source这个函数的应用极少。此外,我们可以在stack_msgs.hMSG_ID_END之前添加我们定义的消息ID,不过打开这个文件发现其实都不这么定义,而是先新增一个头文件,然后把消息ID定义到里面去再include这个头文件。

 

 

(5)RATECH53_09A_GPRS.mak文件内容介绍

       这个文件是build 选项脚本,大致可人为分为2部分,前面部分的Feature OptionsMTK定义的,后面部分的 Platform switchCustom switchSp switchmodis switchRelease Setting SectionConsistent Feature Options等是我们公司和第三方定义软件服务商定义的,其中大多选项可以望文生义并且附有英文注释,其中PHB_SIM_ENTRY(SIM卡支持电话本条数)

PHB_PHONE_ENTRY(手机支持电话本条数)PHB_LN_ENTRY(最近电话条数,已拨,已接,未接)MAIN_LCD_SIZE(主屏幕分辨率)等选项会经常改到。由于内容过多,不一一罗列。

 

 

(6)光电鼠的实现思路

难点有2

1、如何让描画光电鼠的那一层始终处于最上面

详见gdi_layer_blt_ext函数中的宏__RGT_MMI_MOUSE__所包部分。

 

mouse_layer = mmi_get_mouse_layer_hdlr();

for(i=0;i<GDI_LAYER_HW_LAYER_COUNT&&*blt_layer[i]!=mouse_layer;i++)

{

    if( last_find_index >= 0 && *blt_layer[i] > GDI_NULL_HANDLE )

    {

        last_find_index = -1;

    }

else if(last_find_index <0 && blt_layer[i]!= NULL && (*blt_layer[i] == GDI_ERROR_HANDLE||*blt_layer[i] == GDI_NULL_HANDLE))

{

    last_find_index = i;

    //break;

}

}

 if( i == GDI_LAYER_HW_LAYER_COUNT && last_find_index >= 0 )

    {

        *blt_layer[last_find_index] = mouse_layer;

    }

2、如何将按键事件模拟转换成触屏事件

详见mouse.cmmi_mouse_initmmi_mouse_event_indofn_get_data等函数。

 

(7)触屏响应机制

tp_task_create函数中注册了tp_task_main函数,一般来说这类task entry function的实现都是消息循环,但是这个函数有点特殊,我们发现它在while (1)里等的不是消息,而是TP.event,等到TP.event1后,再根据TP.statedown还是up来继续执行handle。那么,这个TP.event是什么时候被置1的?TP.state又是何时被赋值的呢?

 

tp_task_main函数调用了touch_panel_init(),通过   EINT_Registration

(TP.eint_chan,KAL_TRUE,touch_panel_state,touch_panel_

HISR, KAL_TRUE)注册了触屏中断处理函数touch_panel_HISR

 

在中断处理函数中通过kal_set_eg_events(TP.event,1,KAL_OR)将前面提到的TP.event1,并通过touch_panel_state的值是0或者1来分别给TP.stateDOWNUP

 

假如现在的事件是DOWN,那么就会调用touch_panel_down_hdr()函数,接着会调用tp_data_pop()函数再调用touhc_push_data_to_buffer()函数,在这个函数里我们发现会执行TP.touch_panel_event_cb(TP.cb_para, _state)这个回调函数,也就是在mmi_pen_init()里就注册好了的mmi_pen_touch_panel_sendilm()函数,那么,这个回调函数到底做了什么工作呢?

 

它通过msg_send_ext_queue()函数向MMI发了一条消息,消息IDMSG_ID_TP_EVENT_IND

搜索消息ID发现同样是在mmi_pen_init()这个函数里注册了收到这条消息的处理函数:

 

SetProtocolEventHandler(mmi_pen_touch_panel_event_ind, MSG_ID_TP_EVENT_IND);

进到mmi_pen_touch_panel_event_ind()里一看,mmi_pen_poll_hdlr()就是大家所熟悉的mmi收到底层消息后的进行处理的handler了!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值