You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32链接脚本:无需指定长度将结构体存至固定内存地址

在STM32链接脚本中固定地址放置结构体(无需指定长度)的实现方法

核心思路

不需要新增MEMORY段,直接利用链接器的段定位功能,结合代码中的section属性标记结构体,让链接器自动计算结构体长度,同时优化段的衔接逻辑以减少不必要的空间浪费。

步骤1:代码中标记目标结构体

在C代码里,给需要固定地址的结构体添加section属性,确保链接器能识别到对应的段,同时避免被编译器优化掉:

// 定义你的结构体
typedef struct {
    uint32_t magic_code;
    uint16_t firmware_version;
    uint16_t checksum;
    // 其他结构体成员
} SWSystemHeader;

// 标记到指定section,并强制保留
__attribute__((section(".SWHEADER_SECTION"), used))
SWSystemHeader g_sw_header = {
    .magic_code = 0xABCD1234,
    .firmware_version = 0x0201,
    // 初始化其他成员
};

步骤2:修改链接脚本

调整链接脚本的SECTIONS部分,实现以下逻辑:

  1. 中断向量表.isr_vector正常放在FLASH起始地址
  2. 普通代码段.text紧跟向量表,且不超过结构体的固定起始地址
  3. 将.SWHEADER_SECTION强制定位到指定地址,链接器自动根据结构体大小分配空间
  4. 后续代码段从结构体结束地址开始继续排列,避免空间浪费

示例链接脚本代码:

MEMORY
{
    FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K  // 保留原有FLASH定义
    RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}

SECTIONS
{
    // 中断向量表,默认放在FLASH起始位置
    .isr_vector :
    {
        . = ALIGN(4);
        KEEP(*(.isr_vector))  // 确保向量表不被优化丢弃
    } >FLASH

    // 普通代码/只读数据段,紧跟向量表,上限为结构体固定地址
    .text :
    {
        . = ALIGN(4);
        *(.text*)           // 所有代码段
        *(.rodata*)         // 只读数据
        *(.rodata.str1.1)
        // 限制该段不超过结构体固定起始地址,防止重叠
        . = MIN(., 0x8000300);
    } >FLASH

    // 固定地址放置结构体段,无需手动指定长度
    .SWHEADER_SECTION 0x8000300 :
    {
        KEEP(*(.SWHEADER_SECTION))  // 强制保留该段内容
    } >FLASH

    // 后续代码段,从结构体结束地址开始继续排列
    .text_post :
    {
        . = ALIGN(4);
        *(.text*)           // 未在前一段分配的剩余代码
        *(.rodata*)         // 剩余只读数据
    } >FLASH

    // 数据段和BSS段保持原有逻辑
    .data :
    {
        . = ALIGN(4);
        __data_start__ = .;
        *(.data*)
        __data_end__ = .;
    } >RAM AT>FLASH

    .bss :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss*)
        *(COMMON)
        __bss_end__ = .;
    } >RAM

    // 栈和堆的定义保持原有设置
    _estack = ORIGIN(RAM) + LENGTH(RAM);
    _Min_Stack_Size = 0x400;
    _Min_Heap_Size = 0x200;
}

关键说明

  1. 无需指定结构体长度:链接器会自动根据.SWHEADER_SECTION中的实际内容(即你的结构体大小)分配空间,不需要手动填写长度参数。
  2. 减少空间浪费:通过限制.text段的上限,让普通代码尽量填满结构体固定地址前的空间;后续代码从结构体结束地址开始,避免中间出现大块未使用区域(如果普通代码未填满固定地址前的空间,这是固定地址要求导致的必然结果)。
  3. 防止段重叠:如果普通代码段长度超过了固定地址(0x8000300),链接器会直接抛出重叠错误,提前发现问题。

针对你当前方案的优化说明

你原来的写法重复定义了.text段,且用ALIGN(0x8000300)强制跳转地址,导致中间出现未使用空间。上面的方案通过拆分代码段、限制段范围的方式,最大程度利用了固定地址前后的空间,同时满足结构体固定地址的需求。

内容的提问来源于stack exchange,提问作者Peti634

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:10:32