不可或缺的PrepareImageRegions函数
//=====================================================================
//TITLE:
// 不可或缺的PrepareImageRegions函数
//AUTHOR:
// norains
//DATE:
// Friday 3-December-2010
//Environment:
// MDK 4.1
// .Net Micro Framework 4.1
//=====================================================================如果大家看了《main函数之前究竟发生了什么?》(html">http://www.zzzyk.com/kf/201012/79419.html)这篇文章,应该已经知道在main函数之前,MDK究竟为我们做了什么。但如果转到.NMF,可能大家就犯愁了:.NMF没有main函数!这看起来似乎不是什么大问题,但实际上这问题却很严重。根据文档我们可以知道,MDK只有发现存在main函数的定义的时候,才会自动生成__main函数!如果没有__main函数,很多初始化就无法完成,离散文件中的装载域就无法映射到执行域。
如果你还不明白这无法映射的严重性,那么我们来看个例子。有一个全局的static变量g_iVal,它初始化的代码如下:static int g_iVal = 50;
假如代码的装载域无法映射到运行域的话,那么最直接的结果就是,当你使用g_iVal时,数值不是50,而是一个随机的数值!我想,再也不会有比这更严重的事情了吧?
为什么会有这结果呢?因为我们的代码是放在装载域(可能是flash,也可能是其它),g_iVal的数值自然也处在该域;但程序跑起来之后,g_iVal的地址已经被印射到内存(也就是执行域),但其数值却有没有被拷贝到相应的内存位置!我们用MDK生成的工程进行调试,之所以数值会被拷贝到执行域,是因为有__main函数打理这一切!
那么现在在.NMF的环境下,我们要如何做到这步?莫非要自己声明一个main函数,然后手动调用__main?答案自然是不行,因为.NMF的设置,会让MDK不会自动生成__main函数!那么我们应该怎么做?其实答案很简单,之所以前面会啰嗦那么一大堆,主要是解释为什么会产生这种情况的原因,以及这种情况所带来的结果而已。如果要解决这问题,只需要在你的solution的BootstrapCode函数中调用PrepareImageRegions函数即可。
PrepareImageRegions函数是在tinyhal.CPP中实现的,其完整的代码如下:void __section(SectionForBootstrapOperations) PrepareImageRegions()
{
//
// Copy RAM RO regions into proper location.
//
{
UINT32* src = (UINT32*)&LOAD_RAM_RO_BASE;
UINT32* dst = (UINT32*)&IMAGE_RAM_RO_BASE;
UINT32 len = (UINT32 )&IMAGE_RAM_RO_LENGTH;Prepare_Copy( src, dst, len );
}//
// Copy RAM RW regions into proper location.
//
{
UINT32* src = (UINT32*)&Load$$ER_RAM_RW$$Base;
UINT32* dst = (UINT32*)&Image$$ER_RAM_RW$$Base;
UINT32 len = (UINT32)&Image$$ER_RAM_RW$$Length;Prepare_Copy( src, dst, len );
}//
// Initialize RAM ZI regions.
//
{
UINT32* dst = (UINT32*)&Image$$ER_RAM_RW$$ZI$$Base;
UINT32 len = (UINT32 )&Image$$ER_RAM_RW$$ZI$$Length;Prepare_Zero( dst, len );
}
}
代码条理非常简单,无非就是获取装载域和执行域的地址,然后通过Prepare_Copy进行拷贝而已。而这Prepare_Copy的实现也仅仅是个循环,然后赋值,代码如下:static void __section(SectionForBootstrapOperations) Prepare_Copy( UINT32* src, UINT32* dst, UINT32 len )
{
if(dst != src)
{
while(len)
{
*dst++ = *src++;len -= 4;
}
}
}
唯一让各位迷惑的可能是类似& Image$$ER_RAM_RW$$Base这样的变量是哪里来的,其实源头就在于离散文件,也就是solution下面的scatterfile_tools_XXX.xml文件。比如,& Image$$ER_RAM_RW$$Base变量对应的就是scatterfile_tools_XXX.xml中所定义的ER_RAM_RW。
补充:综合编程 , 其他综合 ,