MTK 手机开发小技巧,mtk手机开发小技巧
MTK 手机开发小技巧,mtk手机开发小技巧
声明: 资料根据公司培训及公司同事整理所得
(1) 插上USB线后将某块区域虚拟成一个U盘的代码位置
(2) scatte文件简介和rom、ram超的一般处理
(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文件简介和rom、ram超出的常规处理
Description: defines the memory map for the validation board.简单地说,要生成目标映像文件,armlink必须知道以下两个信息:1. input section与output 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 flash,ram里存放的是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介绍
1、void StartTimer(U16 timerid, U32 delay, FuncPtr funcPtr)
特点:带ID,精准度不高。
2、void gui_start_timer (S32 count, void (*callback) (void))
特点:不带ID,精准度不高。
3、void 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,精准度颇高。用于跑马灯等。
4、gpt timer。用得较少。
(4) Task
Task是有一定封装性的软件模块,当此模块被执行的时候,可以把它理解为一个独立的线程。Task之间的交流可以理解成线程间通信。大家以后可能要独立完成一个task的设计,以应付一些比较高级的应用开发。
1、task的创建:
MTK提供了自定义task的接口,首先要在custom_config.h文件中的custom_task_indx_type和custom_module_type这两个枚举类型中分别加入我们自己的task_index和module id。
其次在custom_config.c中的custom_mod_task_g[]这个数组中定义中增加moudle与task的映射。需要注意这个数组的成员个数不能超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。
2、task的消息循环
前面已经讲到的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.h的MSG_ID_END之前添加我们定义的消息ID,不过打开这个文件发现其实都不这么定义,而是先新增一个头文件,然后把消息ID定义到里面去再include这个头文件。
(5)RATECH53_09A_GPRS.mak文件内容介绍
这个文件是build 选项脚本,大致可人为分为2部分,前面部分的Feature Options是MTK定义的,后面部分的 Platform switch、Custom switch、Sp switch、modis switch、Release Setting Section、Consistent 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.c中mmi_mouse_init、mmi_mouse_event_ind和ofn_get_data等函数。
(7)触屏响应机制
在tp_task_create函数中注册了tp_task_main函数,一般来说这类task entry function的实现都是消息循环,但是这个函数有点特殊,我们发现它在while (1)里等的不是消息,而是TP.event,等到TP.event为1后,再根据TP.state是down还是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.event置1,并通过touch_panel_state的值是0或者1来分别给TP.state赋DOWN和UP。
假如现在的事件是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发了一条消息,消息ID为MSG_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了!
相关文章
- 暂无相关文章
用户点评