mokongking

keil分散加载表与ide的ld文件

在 Keil MDK 使用的 分散加载文件 (.sct) 中,没有 (NOLOAD) 这个关键字。它的等价替代者是 UNINIT

在你提供的 .sct 修改建议中,我使用的 RW_SHARED 0x38000000 UNINIT 0x00002000 里的 UNINIT,其作用与 GCC 链接脚本(.ld)中的 (NOLOAD) 完全一致。

1. 为什么在 Keil 中要用 UNINIT

在 C 语言程序启动时,执行单元(C Lib)会进行“清场”:

  • RW 段:从 Flash 拷贝初始值到 RAM。

  • ZI 段:把 RAM 区域全部清零。

如果你不加 UNINIT 当 M7 启动并初始化好了电机参数(MotorObject),随后 M4 启动。M4 的启动代码发现自己也有一个 RW_SHARED 段,于是它会按照惯例把这块内存再次清零。结果就是 M7 刚写好的数据瞬间被 M4 抹掉了。

加上 UNINIT 后: 链接器(Armlink)会标记这块内存为“不初始化”。这样 M4 启动时,它的 __main 函数会跳过这块地址,保持内存里原有的数据(即 M7 写好的数据)不动。


2. 检查你的 .sct 文件位置

请确保你的 .sct 文件里是这样写的:

Code snippet
 
; M7 的 sct 文件
RW_SHARED 0x38000000 UNINIT 0x00002000 { 
    *(SHARED_DATA_SECTION)
}

; M4 的 sct 文件(同样要加 UNINIT)
RW_SHARED 0x38000000 UNINIT 0x00002000 {
    *(SHARED_DATA_SECTION)
}

3. 特别注意:手动初始化

由于使用了 UNINIT,这块内存里的数据在冷上电(刚插电)时是随机的垃圾值

因为 M4 不负责初始化,M7 也不自动清零,你必须在 M7 的代码中手动调用你的初始化函数:

C
 
// 在 M7 的 main.c 中
void main(void) {
    // 1. 先进行硬件初始化
    // 2. 手动对共享结构体进行一次性赋值
    Task_Motor_Init(); 
    
    // 3. 此时才唤醒 M4 核心
    HAL_RCCEx_EnableBootCore(RCC_BOOT_C2); 
}

4. 补充:C 代码里的“双保险”

如果你想在代码层面也强调这一点(虽然 .sct 已经决定了结果),在 Keil 下你还可以给变量增加这个特殊的属性:

C
 
// 在 M7 中定义时,显式指定不初始化
MotorStruct MotorObject[MaxMotorNum] __attribute__((section("SHARED_DATA_SECTION"), zero_init));

注意:在 Keil 中,如果你想让变量绝对不被清零,除了 sct 里的 UNINIT,有时还需要配合编译器指令,但最稳妥、最直观的方法就是通过刚才改好的 .sct 文件。

总结

  • GCC (.ld) 使用 (NOLOAD)

  • Keil (.sct) 使用 UNINIT

ld例子

MEMORY { /* 必须和 M7 的地址完全一致! */ SHARED_RAM (xrw) : ORIGIN = 0x38000000, LENGTH = 64K } SECTIONS { /* M4 这边也映射到同一个物理位置 */ .shared_section (NOLOAD) : { . = ALIGN(32); KEEP(*(.shared_data)) . = ALIGN(32); } > SHARED_RAM }

MEMORY { /* 假设我们使用 SRAM4 作为共享区 */ SHARED_RAM (xrw) : ORIGIN = 0x38000000, LENGTH = 64K ... } SECTIONS { /* 将名为 .shared_data 的输入段放入 SHARED_RAM 区域 */ .shared_section (NOLOAD) : { . = ALIGN(32); KEEP(*(.shared_data)) /* 匹配代码中的 section(".shared_data") */ . = ALIGN(32); } > SHARED_RAM }

posted on 2026-05-07 15:54  虎啸岳林  阅读(66)  评论(0)    收藏  举报

导航