1

我正在研究 STM32L152RCT6 上的项目,我必须建立一种机制来从新的门控文件(HEX 文件)中自我更新代码。为此,我已经实现了诸如引导加载程序之类的机制,它在其中检查新固件是否必须交叉验证,如果发现有效,则必须存储在“应用程序位置”上。

我正在采取以下步骤。

  1. 引导加载程序地址 = 0x08000000
  2. 应用地址 = 0x08008000
  3. 在指定位置的某个地方,它必须通过引导加载程序检查新文件。
  4. 如果发现有效,则必须在位置复制所有十六进制(根据指南)。
  5. 比通过在该位置跳转来运行应用程序代码。

现在问题来自第 5 步,我已经完成的所有上述步骤,甚至数据的存储都已正确完成(在 STM32 实用程序中验证),但是当我跳转到应用程序代码时它不会工作。

有我必须交叉检查或我遗漏的东西吗?

4

4 回答 4

0

您是否根据新的 falsh 位置更改了应用程序?

例如,必须通过正确设置向量表

SCB->VTOR = ...
于 2018-07-23T08:33:28.160 回答
0

当您的引导加载程序启动应用程序时,它必须将所有内容配置回重置状态,因为应用程序可能会依赖默认重置值。尤其是您需要:

  1. 将所有硬件寄存器的值返回到其复位值
  2. 关闭所有外围时钟(不要忘记 SysTick)
  3. 禁用所有启用的中断
  4. 将所有时钟域恢复为其复位值。
  5. 设置向量表地址
  6. 从 APP 向量表的开头加载堆栈指针。
  7. 调用APP入口点。(vertor table start + 4)

您的应用程序必须使用自定义链接器脚本进行编译和链接,其中 FLASH 起点为 0x8008000

例如:

FLASH (rx) : ORIGIN = 0x8000000 + 32K, LENGTH = 512K - 32K

于 2018-07-23T11:14:48.420 回答
0

与其他在复位时直接跳转到地址 0 的 ARM 控制器不同,Cortex-M 系列从向量表中获取起始地址。如果程序直接加载(没有引导加载程序),向量表位于二进制文件的开头(加载或映射到地址 0)。偏移量 0 处的第一个条目是堆栈指针的初始值,地址 4 处的第二个条目称为复位向量,它包含要执行的第一条指令的地址。

使用引导加载程序加载的程序通常会0x08008000保留这种安排,并在您的情况下将向量表放在二进制文件的开头。然后重置向量将在0x08008004。但这是你的应用程序,你应该检查你把向量表放在哪里。提示:查看.map链接器生成的文件以确定。如果它确实在0x08008000,那么您可以将控制权转移到应用程序重置向量,这样:

void (*app)(void);                   // declare a pointer to a function
app = *(void (**)(void))0x08008004;  // see below
app();                               // invoke the function through the pointer

第二行中的复杂转换将物理地址转换为指向函数指针的指针,获取指向它的值,该值现在是指向函数的指针,并将其分配给app

然后,您应该管理到应用程序向量表的切换。您可以在引导加载程序或应用程序中执行此操作,或者在它们之间划分步骤。

  • 禁用所有中断并停止 SysTick。注意SysTick 不是一个中断,不要调用NVIC_DisableIRQ()它。我会在引导加载程序中执行此步骤,因此它负责禁用已启用的任何内容。
  • 将新的向量表地址分配给SCB->VTOR。请注意,样板SystemInit()函数system_stm32l1xx.c 无条件地变SCB->VTOR回 flash 的开头,即0x08000000,您应该编辑它以使用正确的偏移量。

您也可以从向量表中加载堆栈指针值,但要正确执行此操作很棘手,而且并非真正必要,应用程序可以继续使用在引导加载程序中设置的堆栈。只需检查它以确保它是合理的。

于 2018-07-23T13:21:49.043 回答
-1
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

其中FLASH_BASE的值必须等于您的 IROM 在 KEIL 中的值的地址

例子:

#define FLASH_BASE      0x08004000

Keil配置

于 2019-06-23T04:13:54.213 回答