3

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

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”。

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

4

1 回答 1

2

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

正如您所说,您想要做的是将 RAM 分成两部分。它的一部分应该为您要复制的代码保留,另一部分用于全局变量和堆栈。这是通过链接器脚本完成的(对于链接器脚本只有 Google),尽管某些 IDE 可能会在某处公开偏好。例如,请参阅 Coocox 的这个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),然后添加复制代码将开始的地址(如果您像我上面所做的那样为代码留出 RAM 的初始区域,则说 0x20000000)。我想不出一种更简单的方法来做到这一点,并不是说这个方法特别复杂。

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

于 2014-04-19T01:56:03.400 回答