当前位置:编程学习 > 网站相关 >>

不可或缺的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。

 

补充:综合编程 , 其他综合 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,