我已经为Kinetis K24 Cortex M4编写了一个引导程序。引导加载器在运行时通过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
发布于 2018-01-25 03:25:27
处理.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的清零,但是在第一次尝试时,它导致我的程序崩溃。我无法想象要花很多功夫才能让它工作。
https://stackoverflow.com/questions/48425861
复制相似问题