(STM32F10x,IAR EW)通过RS232自升级bootloader,从FLASH复制后如何在RAM中执行程序

时间:2013-12-31 03:05:41

标签: upgrade ram stm32 bootloader flash-memory

我在STM32F103RBT6工作,我想升级我的bootloader程序,我把它放在0x08000000~0x08003fff,我使用所有其他闪存的应用程序代码。通过RS232,我想升级bootloader。所以我想将代码复制到RAM - >在RAM中执行原始引导加载程序 - >下载新的bootloader。 我做的是:

startAddr == 0x20000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 

JumpAddress = *(__IO UINT32*)(startAddr + 4 ); 
Jump_To_Application =  (pFunction)JumpAddress;   
__set_MSP(*(__IO UINT32*) startAddr);
Jump_To_Application();  

它不起作用。

问题是:

  1. 我可以将代码复制到0x20000000~。我应该将RAM分为两部分,但如何?

  2. 如何设置我的Vector表位置,我可以在哪里设置它?我该如何处理“VECT_TAB_OFFSET”。

  3. 如果你能给我一些解决方案或任何命令,我将非常感激。 非常感谢。

1 个答案:

答案 0 :(得分:2)

在传统设置(flash + RAM)中编译代码时,代码进入内存的一部分而RAM进入另一部分,因此不存在踩踏其他脚趾的风险。现在,当您将代码复制到RAM时,可能是它尝试访问RAM中的某些变量,最终被您编写的代码覆盖,这会产生问题。

正如您所说,您要做的是将RAM分为两部分。它的一部分应保留给您要复制的代码,另一部分保留给全局变量和堆栈。这是通过链接器脚本(仅用于链接器脚本的Google)完成的,尽管某些IDE可能会在某处公开首选项。例如,参见此Coocox forum thread中Coocox中的数字,如果是偶然的,那就是您正在使用的内容。在这种特殊情况下你要做的是将IRAM1的起点改为以后的位置,比如0x20000400,当然也要相应地调整RAM区域的大小 - 示例中为0x00000C00。对于gcc链接器脚本,你应该在脚本的某个地方有这样的东西:

MEMORY
{
    rom (rx)  : ORIGIN = 0x08000000, LENGTH = 0x00040000
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000
}

只需对以ram开头的行进行类似更改。

当然,这些只是示例值。你需要弄清楚你的代码有多大,并确保至少那个大小的RAM部分是其他所有内容的禁区。

此外,您需要使用某种PIC(位置无关代码)选项编译代码,因此重定位代码没有问题。这非常重要。

您还需要重新定位向量表,正如您所指出的那样。这是通过Cortex-M3内核的系统控制模块,特别是地址0xE000ED08的向量表偏移寄存器完成的,如果您使用标准,也可以通过结构字段SCB-> VTOR访问它。外围图书馆。还有标准外设库中的NVIC_SetVectorTable()功能。唯一的限制是向量表必须位于512的倍数的地址中,即位8-0必须为0。

通过这样做,MCU内核将在您设置的位置查找中断表。第二个问题是确保向量表上的地址指向RAM中的位置而不是闪存中的原始位置。您可以通过执行一些指针算法来修复条目,即在闪存中获取其原始地址中的函数的指针,减去链接器脚本中找到的起始闪存地址(通常为0x08000000),然后添加复制代码将启动的地址(比如0x20000000,如果你为我的代码放置RAM的初始区域,就像我上面所做的那样)。我无法想到一种更简单的方法,而不是这一点特别复杂。

或者您可以绕过整个问题,并且不要在引导加载程序中使用任何中断。当我编写一个引导加载程序时,这是我做出的一个设计决策,理由是中断使代码更难以预测,更难分析。引导加载程序是一个非常关键的代码(遇到错误,你可能会破坏你的硬件需要一个可能很昂贵的修复),同时,引导加载程序通常没有任何硬实时要求或事情。排序,因此您可以在满足设计要求的同时完全避免中断。我会敦促你考虑这种可能性。

相关问题