老大让我研究一下MTK平台上是否能够实现动态加载的功能,没什么时间限制,尽量搞一下看看是否能实现,利用闲暇时间网上搜索了相关资料并写了部分代码,在MT6250平台上初步测试ok.两个区域之间函数调用ok.
首先研究一下arm编译器中RO,RW,ZI的说明(参考http://blog.csdn.net/jamestaosh/article/details/4348385文章),还有MTK平台scatterfile(参考http://blog.sina.com.cn/s/blog_49bfa8830100hwif.html文章)做好准备。
然后确定思路,需要先在flash原来的基础上分配一段固定地址的空间出来(称为小cp,原来代码为大cp)存放代码和数据,修改scatterfile,11B平台后是.cfg文件,都是编译过程中生成的文件,需要修改scatGenLib.pl文件,参考原有的分区代码分配一段小cp的空间,注意以下几点:
1. 必须在ram区域中分配,如果存放到rom中,运行时读取小cp内存会直接重启
2. 必须是绝对固定地址,原来ram区域各个部分是相对累加的,需要计算清楚再分配,可以在ram最后分配,同时将大cp可用ram的最后地址(CACHED_DUMMY_END)提前.
编写测试代码放到小cp里,例如:
#pragma arm section code = "DYNAMIC_LOAD_ER", rwdata = "DYNAMIC_LOAD_ER", rodata = "DYNAMIC_LOAD_ER", zidata = "DYNAMIC_LOAD_ER"
int g_dynamic_load = 0;
const int g_dynamic_array[]= {0,1,2,3,4,5,6,7,8};
void mmi_dynamic_load_test(void)
{
int dynamic_load_char = g_dynamic_load;
unsigned short str_id = STR_GLOBAL_1 +dynamic_load_char;
dbg_print("mmi_dynamic_load_test, str_id=%d \r\n", str_id);
mmi_display_popup(get_string(STR_GLOBAL_DONE), 0);
}
#pragma arm section code
然后编译完成后,查看生成文件夹中是否有新的bin文件,还有lis文件中观察所定义的section“DYNAMIC_LOAD_ER”是否有对应的ro rw信息,如果有并且对应size正确则说明小cp区域分配成功。
接下来测试大cp和小cp之间函数和数据的通信,首先需要把新的bin文件(存放小cp的代码和数据)拷贝到内存中才可以运行,因为flash tools下载问题无法把新的bin文件下载到flash中,所以采取文件系统管理的方法,在大cp中把bin文件拷贝到文件系统中,开机后读取该bin文件并拷贝到对应的起始地址(之前分配的空间中)即可运行并相互调用
1. arm编译生成的bin文件只包含code,ro data,rw data,而不包含初始化为0的rw和未初始化的变量,该区域由bootloader全部初始化为0,而小cp部分没有纳入这个机制,所以需要单独处理,在大cp读取该bin文件之前需要memset全部小cp区域。
2. memset(&Image$$DYNAMIC_LOAD_ER$$Base, 0, (200*1024));
Image$$DYNAMIC_LOAD_ER$$Base为arm编译器根据scatterfile自动生成的全局变量,200*1024为所分配的区域大小
以上所实现的只是伪动态加载,就是大cp和小cp必须同时编译才可以相互调用,因为编译器连接时的函数地址都是绝对地址,如果大cp修改代码后函数的绝对地址会变化,那么小cp调用的还是原来的函数地址,会产生错误,所以还需要修改代码,函数调用必须采用相对地址的方法,否则大小cp就无法独立出来