在应用程序编程问题

In Application Programming issue

我正在 STM32L152RCT6 项目上工作,我必须在其中构建一种机制,以从新门控文件(HEX 文件)自我更新代码。 为此,我已经实现了像引导加载程序这样的机制,它检查新固件是否存在它必须交叉验证,如果发现有效它必须存储在 "Application location" 上。

我正在执行以下步骤。

  1. 引导加载程序地址 = 0x08000000
  2. 申请地址=0x08008000
  3. 它必须在指定位置的某处通过引导加载程序检查新文件。
  4. 如果发现有效,则必须复制所有 HEX 到位(按照指南)。
  5. 比运行应用代码跳转到那个位置。

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

我是否需要交叉检查或遗漏了什么?

你有没有根据新的闪光灯位置更改应用程序?

例如,矢量 Table 必须通过

正确设置
SCB->VTOR = ...

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

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

您的应用必须使用 FLASH 起始点为 0x8008000 的自定义链接描述文件进行编译和链接

例如:

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

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

使用引导加载程序加载的程序通常 会保留这种排列方式,并将矢量table 放在二进制文件的开头,在您的例子中是0x08008000。那么重置向量将位于 0x08008004。但这是你的应用程序,你应该检查你把你的矢量放在哪里 table。提示:看看链接器生成的.map文件就可以确定了。如果它确实在 0x08008000,那么您可以将控制转移到应用程序重置向量,因此:

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

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

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

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

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

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

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

示例:

#define FLASH_BASE      0x08004000

Keil configuration