Upgrade (STM32F10x,IAR EW)通过RS232自升级引导加载程序,从闪存复制后如何在RAM中执行程序

Upgrade (STM32F10x,IAR EW)通过RS232自升级引导加载程序,从闪存复制后如何在RAM中执行程序,upgrade,ram,stm32,bootloader,flash-memory,Upgrade,Ram,Stm32,Bootloader,Flash Memory,我在STM32F103RBT6工作,我想升级我放在0x08000000~0x08003fff中的引导加载程序,我使用所有其他闪存作为应用程序代码。通过RS232,我想升级引导加载程序。因此,我考虑将代码复制到RAM-->在RAM中执行原始引导加载程序-->下载新的引导加载程序。 我所做的是: startAddr == 0x20000000 NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); JumpAddress = *(__IO UINT32*)(sta

我在STM32F103RBT6工作,我想升级我放在0x08000000~0x08003fff中的引导加载程序,我使用所有其他闪存作为应用程序代码。通过RS232,我想升级引导加载程序。因此,我考虑将代码复制到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();  
它不起作用

问题是:

  • 我可以把代码复制到0x20000000~。我应该把公羊分成两部分吗?但是怎么分呢

  • 如何设置向量表位置,以及在何处设置?如何处理“向量选项卡偏移”

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

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

    你要做的是,正如你所说的,将RAM分成两部分。其中一部分应该保留给要复制的代码,另一部分保留给全局变量和堆栈。这是通过一个链接器脚本来完成的(只是googleforlinker脚本),尽管一些ide可能会在某个地方公开一个首选项。例如,如果您碰巧使用的是Coocox,请参见本文中的图。在这种特殊情况下,您要做的是将IRAM1的起始位置更改为更晚的位置,比如0x20000400,当然还要相应地调整RAM区域的大小——在本例中为0x00000000。对于gcc链接器脚本,在脚本中的某个地方应该有类似的内容:

    MEMORY
    {
        rom (rx)  : ORIGIN = 0x08000000, LENGTH = 0x00040000
        ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000
    }
    
    只需对以
    ram
    开头的行进行类似的更改

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

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

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

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

    或者,您可以绕过整个问题,在引导加载程序中不使用中断。当我编写引导加载程序时,这是我做出的一个设计决策,其基本原理是中断会使代码更难预测和分析。引导加载程序是一段非常关键的代码(碰到一个bug,你可能会把你的硬件限制在一个潜在的昂贵的修复中),同时,引导加载程序通常没有任何硬实时的要求或类似的东西,所以你可以避免在满足设计要求时完全避免中断。我敦促你考虑这个可能性。