使用IAR EWARM手动将.data部分从flash复制到ram

时间:2018-01-24 15:17:20

标签: c embedded iar

我为Kinetis K24 Cortex M4编写了一个bootloader。引导加载程序在运行时通过USB将其他功能加载到RAM中。这个ramcode作为自己的EWARM项目存在,生成二进制文件。此二进制文件的入口点必须始终为0x20000000,并且向量表必须始终位于0x20007000才能与我的.NET工具很好地配合使用。 IAR启动代码处理.bss和.data副本的清除,但它也做了一些我不想要的事情。我无法弄清楚如何强制IAR入口点到特定地址,所以我创建了自己的入口点,如此

#pragma section=".bss"

#pragma location=".init"
__interwork int __low_level_init(void)
{
    char * from = __section_begin(".bss");
    char * to = __section_end(".bss");

    __DI(); // Disable interrupts

    memset(from, 0x00 , (to - from));

    memcpy(__vector_table, (unsigned char *)ROM_VECTOR_LOCATION, VECTOR_TABLE_SIZE);

    SCB_VTOR = (unsigned int) & __vector_table;

    main();

    SCB_VTOR = (uint32_t)ROM_VECTOR_LOCATION;
}

当我调试代码时,我可以看到初始化为非零值的全局变量采用随机值。我相信这是因为我没有将.data部分从LMA复制到VMA。

我的问题是如何将此.data部分的副本从LMA复制到VMA?

如果我能弄清楚如何分解它,我也会决定使用IAR启动代码但是入口点不能成为复位向量。入口点必须为0x20000000,向量表必须为0x20007000

1 个答案:

答案 0 :(得分:1)

处理.data部分副本的IAR函数称为__iar_data_init3()。我曾考虑直接调用它,但不敢相信它就这么简单。 IAR建议这是正确的解决方案。我还使用关键字__root来阻止编译器删除我的“未使用”函数。这允许我重命名它像startup()更合适。调用它__low_level_init()只是一个阻止编译器删除它的黑客攻击。 __low_level_init()没有被调用作为启动序列的一部分,而是我在引导加载程序中加载程序计数器的入口点。这是我的最终解决方案

#pragma section=".bss"
#pragma location=".init"
__root void startup()
{
    char * from = __section_begin(".bss");
    char * to = __section_end(".bss");

    memset(from, 0x00 , (to - from));

    __iar_data_init3();

    memcpy(__vector_table, (unsigned char *)ROM_VECTOR_LOCATION, VECTOR_TABLE_SIZE);

    __DI(); // Disable interrupts

    SCB_VTOR = (unsigned int) & __vector_table;

    main();

    SCB_VTOR = (uint32_t)ROM_VECTOR_LOCATION;

}

还没有一个名为__iar_zero_init3()的函数来处理.bss的归零,但是在第一次尝试时它导致我的程序崩溃。我无法想象要让它发挥作用需要花费很多工作。