gcc - 这两个链接描述文件部分有什么区别?
问题描述
我有一个涉及 .firmware_header 部分的 STM32 项目,该部分限制了我的应用程序映像的末尾。我正在尝试重新定位 .data 部分,以便它出现在 .firmware_header 部分之前,但由于某种原因,我在这样做时遇到了很多困难。
以下工作,但破坏了我用来签署图像的脚本,因为它不知道它需要在校验和计算中包含 .data 部分(LMA 在 RAM 中)。
_sidata = .;
.data_x : AT(_sidata) /* LMA address is _sidata (in FLASH) */
{
. = ALIGN(4);
_sdata = .; /* data section VMA address */
*(.data*)
. = ALIGN(4);
_edata = .;
} > SRAM
.firmware_header (_sidata + SIZEOF(.data_x)):
{
. = ALIGN(4);
KEEP(*(.firmware_header))
. = ALIGN(4);
} > FLASH
这不起作用。即使所有地址(sidata、sdata、edata)都正确并且映像启动,但初始化数据存在问题,并且映像通常在开始运行后由于明显的原因硬失败。为什么会启动失败?要加载到内存中的数据的位置与前面的链接描述文件片段中的相同,存储数据在闪存中的位置也相同。
.data_flash :
{
. = ALIGN(4);
_sidata = .;
*(.data*)
. = ALIGN(4);
} > FLASH
.firmware_header :
{
. = ALIGN(4);
KEEP(*(.firmware_header))
. = ALIGN(4);
} > FLASH
.data_ram (NOLOAD) :
{
. = ALIGN(4);
_sdata = .;
. = . + SIZEOF(.data_flash);
_edata = .;
. = ALIGN(4);
} > SRAM
这就是我在 reset_handler() 中将数据从闪存加载到内存中的方式:
void **pSource, **pDest;
for (pSource = &_sidata, pDest = &_sdata; pDest != &_edata; pSource++, pDest++)
*pDest = *pSource;
我在这里想念什么?这些在功能上不应该完全相同吗?
解决方案
第一个脚本将所有.data
段的字节放入闪存中的相应部分,但将它们的所有地址解析为 RAM 中的运行时位置;这就是您的程序所需要的。要初始化变量,您需要将内容从闪存复制到 RAM,您所做的。
第二个脚本在闪存中解析.data
加载时位置(如果我可以这么说的话)的所有段地址;这是行不通的,因为您的程序在运行时无法写入这些位置。该NOLOAD
部分只是增加 RAM 中的位置指针,而不解析初始化变量的地址。
请查看交叉引用中的一些初始化变量(到一个不等于零的值)。使用您的第一个脚本,它将正确位于 RAM 中的某个地址,使用您的第二个脚本,它将错误地位于闪存中的某个地址。
推荐阅读
- python - Slack Bot [Python/Flask]:等待来自指定用户的直接消息并保存响应
- c# - Json.Net 属性忽略所有属性
- javascript - 不能使用状态变量作为函数参数?反应
- javascript - 无法访问 Mapbox GL JS 中的地理定位控件以更改/添加属性
- android - Android 使用 OnTouch 检测 longClick 位置
- javascript - React JS + Fetch API 发布
- java - How to check variable is initialized or not in Java?
- python - 无法在 setup.py 中导入从 git 安装的依赖项
- java - 触发 TTL 删除 Cassandra
- r - R - 如果在另一个数据框中找到 ID,则合并和替换列