当前位置: 首页 > news >正文

【stm32】【edgetx】解析链接脚本文件(ld)

链接器脚本 (*.ld)

.ld文件是GNU Linker Script(链接脚本),用于GNU工具链(如GCC)中的链接器ld。它主要用来定义目标程序的内存布局,包括代码段、数据段、堆栈、堆等的大小和位置。

链接器脚本的两阶段处理机制

  • 符号可以在定义前使用

  • 内存区域函数在内存区域定义后才会被计算

  • 最终值在链接时确定

stm32f40x部分

layout.ld

它是整个内存布局的核心配置文件,定义了STM32F4的所有内存区域和关键参数。

/* Highest address of the user mode stack */
STACK_ADDRESS = ORIGIN(CCM) + LENGTH(CCM); /* end of CCM */
/* Required amount of stack for interrupt stack (Main stack) */
MAIN_STACK_SIZE = 1024;

计算0x10000000 + 64K = 0x10010000
作用: 栈顶指针指向CCM内存的末尾, 为主栈(中断栈)分配1KB空间

/* Maximum bootloader code size */
BOOTLOADER_SIZE = 0x8000;

计算0x8000 = 32KB
作用: 为bootloader保留32KB Flash空间

/* Minimum Heap Size (indicative) */
MIN_HEAP_SIZE = 0;
// 默认MIN_HEAP_SIZE = 0 的原因:
// - 嵌入式系统通常避免动态内存分配
// - 防止内存碎片和不确定性
// - 鼓励静态内存分配,提高可靠性

堆大小设置为0,意味着默认不启用动态内存分配

/* Highest heap address */
HEAP_ADDRESS = ORIGIN(RAM) + LENGTH(RAM);

计算0x20000000 + 128K = 0x20020000
作用: 堆的结束地址指向主RAM末尾

MEMORY
{FLASH (rx) :ORIGIN = 0x08000000,LENGTH = DEFINED(__flash_size) ? __flash_size : 512KRAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128KCCM (xrw)       : ORIGIN = 0x10000000, LENGTH = 64K
}
# 编译时定义__flash_size覆盖默认值
gcc -D__flash_size=256K -T layout.ld ...

MEMORY定义

FLASH (rx): 
- 起始地址: 0x08000000  
- 大小: 512KB (可通过__flash_size覆盖)
- 属性: r(读)+x(执行)
- 灵活性: 支持不同Flash大小的芯片
RAM (xrw):
- 起始地址: 0x20000000
- 大小: 128KB  
- 属性: x(执行)+r(读)+w(写)
- 用途: 通用变量、堆空间
CCM (xrw):
- 起始地址: 0x10000000
- 大小: 64KB
- 属性: x(执行)+r(读)+w(写)  
- 特点: 零等待状态,与CPU核心直连
REGION_ALIAS("REGION_BOOTLOADER",   FLASH);
REGION_ALIAS("REGION_ISR_VECT",     FLASH);
REGION_ALIAS("REGION_TEXT",         FLASH);
REGION_ALIAS("REGION_TEXT_STORAGE", FLASH);

Flash区域分配:

  • 所有Flash相关段都映射到同一物理Flash

  • 通过不同别名实现逻辑分区

REGION_ALIAS("REGION_DATA", CCM);
REGION_ALIAS("REGION_BSS", CCM);
REGION_ALIAS("REGION_RAM", RAM);

RAM区域策略:

  • .data.bss段放在高速CCM

  • 通用.ram段放在主RAM中

  • 体现性能优化的设计思想

extra_sections.ld

这是extra_sections.ld文件,它专门处理堆和栈的内存分配

PROVIDE(_heap_start = _eram);
  • _eram 是.ram段的结束地址(在common_sections.ld中定义)

  • _heap_start = .ram段之后的位置

  • 这样堆就紧接在.ram段后面开始

INCLUDE section_ccm.ld
PROVIDE(_ccm_heap_start = _eccm);
PROVIDE(_ccm_heap_end = _main_stack_start);

作用: 包含CCM专用段的定义,建立CCM内存布局,定义CCM堆的边界

堆分配段解析

/* Reserve heap space in RAM */
._user_heap(NOLOAD) :
{. = ALIGN(4);                      /* 4字节对齐 */. = . + MIN_HEAP_SIZE;             /* 预留堆空间大小 */. = ALIGN(4);                      /* 再次对齐 */
} > REGION_RAM
  • (NOLOAD): 不加载初始值,运行时动态使用

  • MIN_HEAP_SIZE = 0默认不分配堆空间

  • 位置: REGION_RAM (主RAM)

栈分配段解析

/* Reserve stack space in CCM */
.stack(NOLOAD) :
{. = ALIGN(4);                      /* 4字节对齐 */. = . + MAIN_STACK_SIZE;           /* 预留栈空间大小 */. = ALIGN(4);                      /* 再次对齐 */
} > CCM
  • (NOLOAD): 栈不需要初始值

  • MAIN_STACK_SIZE = 1024: 分配1KB栈空间

  • 位置: CCM (核心耦合内存)

section_ccm.ld

用于定义CCM(Core Coupled Memory)内存段的布局。 CCM (Core Coupled Memory) 是一块非常特殊且有用的片上 SRAM。

.ccm (NOLOAD) 的含义

  • .ccm: 段名称,程序员可以在代码中指定变量放在这个段。

  • (NOLOAD): 关键属性,表示:这个段不需要在启动时从Flash。

.ccm (NOLOAD) :          /* 定义名为 .ccm 的段,NOLOAD表示不加载到Flash */
{. = ALIGN(4);          /* 当前位置对齐到4字节边界 */_sccm = .;             /* 定义符号 _sccm = CCM段起始地址 */*(.ccm)                /* 将所有目标文件中的 .ccm 段收集到这里 */. = ALIGN(4);          /* 再次对齐到4字节边界 */_eccm = .;             /* 定义符号 _eccm = CCM段结束地址 */
} > CCM                  /* 将此段放置在CCM内存区域 */

definition.ld

INCLUDE layout.ld                      /* 包含内存布局定义文件 */
/* Entry Point */
ENTRY(Reset_Handler)                   /* 定义程序入口点为Reset_Handler */

包含layout.ld实现配置分离

作用: 引入内存区域、大小常量等基础配置。

  • 告诉链接器和调试器程序从哪里开始执行

  • Reset_Handler是启动文件中定义的函数,负责系统初始化

  • 程序复位后,CPU首先跳转到这个地址

/* Stack address */
_estack = STACK_ADDRESS;               /* 栈顶地址 = CCM内存末尾 */
/* Main stack end */
_main_stack_start = _estack - MAIN_STACK_SIZE;  /* 栈底地址 */
/* Highest heap address */
_heap_end = HEAP_ADDRESS;              /* 堆结束地址 = RAM末尾 */

这里有堆和栈内存结尾定义。

栈:向低地址扩展
堆:向高地址扩展

栈内存布局:

CCM内存 (64KB):
0x10000000 +-----------------+ ← _sdata/_sbss| .data + .bss段  | (全局变量)+-----------------+ ← _edata/_ebss|    .ccm段       | (高性能变量)+-----------------+ ← _eccm = _ccm_heap_start|   CCM堆空间     | (可用作高速堆)+-----------------+ ← _ccm_heap_end = _main_stack_start|   主栈(1KB)     | (向下增长)+-----------------+ ← _estack (0x10010000)

 将栈放在 CCM 可以显著提高函数调用、中断响应的速度(因为栈访问非常频繁)

堆内存布局:

主RAM (128KB):
0x20000000 +-----------------+ ← _sram|    .ram段       | (用户定义的RAM变量)+-----------------+ ← _eram = _heap_start|   未使用区域     | 可作为堆 (但默认未启用)+-----------------+ ← _heap_end (0x20020000)

common_sections.ld

ARM异常处理段

/* C/C++ Exception handling (not used) */
.ARM.extab (READONLY) :
{*(.ARM.extab* .gnu.linkonce.armextab.*)
} > REGION_TEXT AT> REGION_TEXT_STORAGE.ARM (READONLY) :
{PROVIDE(__exidx_start = .);*(.ARM.exidx* .gnu.linkonce.armexidx.*)PROVIDE(__exidx_end = .);
} > REGION_TEXT AT> REGION_TEXT_STORAGE

引导代码段

/* Bootstrap code to load ISR vector and code sections */
.bootstrap (READONLY) :
{*(.bootstrap)
} > REGION_TEXT_STORAGE

已初始化数据段 (.data)

/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{. = ALIGN(4);_sdata = .;        /* create a global symbol at data start */*(.data .data*)    /* .data sections */. = ALIGN(4);_edata = .;        /* define a global symbol at data end */
} > REGION_DATA AT> REGION_TEXT_STORAGE

未初始化数据段 (.bss)

/* Uninitialized data section */
.bss (NOLOAD) : AT (ADDR(.bss))
{. = ALIGN(4);_sbss = .;         /* define a global symbol at bss start */*(.bss .bss*)      /* .bss sections */*(COMMON)          /* COMMON symbols */. = ALIGN(4);_ebss = .;         /* define a global symbol at bss end */
} > REGION_BSS

通用RAM段

/* collect all uninitialized .ram sections */
.ram (NOLOAD) : AT (ADDR(.ram))
{. = ALIGN(4);_sram = .;*(.ram). = ALIGN(4);_eram = .;
} > REGION_RAM

重启缓冲区

/* Seems to be the safest place for all targets (see AN2606) */
.reboot_buffer (ORIGIN(REGION_DATA) + LENGTH(REGION_DATA) - 4) (NOLOAD) : AT (ADDR(.reboot_buffer))
{KEEP(*(.reboot*))
} > REGION_DATA

库段丢弃

/* Remove information from the standard libraries */
/DISCARD/ :
{libc.a ( * )libm.a ( * )libgcc.a ( * )
}

ARM属性段

.ARM.attributes 0 : { *(.ARM.attributes) }
Flash存储布局 (LMA):
+-----------------+
|    .text        | 程序代码
+-----------------+
|    .data初始值  | ← _sidata
+-----------------+
|    .ARM.extab   | 异常处理
+-----------------+CCM运行布局 (VMA):
+-----------------+ ← _sdata/_sbss
|    .data        | 已初始化变量 (运行时)
|    .bss         | 未初始化变量
+-----------------+ ← _edata/_ebss主RAM运行布局:
+-----------------+ ← _sram
|    .ram段       | 用户定义的RAM变量
+-----------------+ ← _eram

common_text.ld

专门定义代码段和C++运行时结构的布局

/* .text sections (code) */
*(.text .text* .gnu.linkonce.t.*)        /* 收集所有代码段:主代码、编译器生成的代码、链接优化代码 */
*(.rodata .rodata* .gnu.linkonce.r.*)    /* 收集所有只读数据段:常量字符串、全局常量、编译时常量 */*(.glue_7)  /* glue arm to thumb code */ /* ARM调用Thumb代码的粘合代码段(veneers) */
*(.glue_7t) /* glue thumb to arm code */ /* Thumb调用ARM代码的粘合代码段(veneers) */*(.eh_frame)                             /* 异常处理帧信息,用于栈展开和调试 */
*(.data.__global_locale)                 /* C++全局区域设置数据(locale相关) *//* Init hooks table */
. = ALIGN(4);                            /* 对齐到4字节边界 */
__init_hook_array_start = .;             /* 定义初始化钩子数组起始符号 */
KEEP (*(.init_hook))                     /* 强制保留所有.init_hook段(自定义初始化钩子) */
__init_hook_array_end = .;               /* 定义初始化钩子数组结束符号 *//*C++ Runtime: initializers for static variables.C Runtime: designated constructors
*/
. = ALIGN(4);                            /* 对齐到4字节边界 */
KEEP(*(.init))                           /* 强制保留.init段(C运行时初始化代码) */
. = ALIGN(4);                            /* 对齐到4字节边界 */
__preinit_array_start = .;               /* 定义预初始化数组起始符号 */
KEEP (*(.preinit_array))                 /* 强制保留.preinit_array段(C++预初始化函数指针数组) */
__preinit_array_end = .;                 /* 定义预初始化数组结束符号 */. = ALIGN(4);                            /* 对齐到4字节边界 */
__init_array_start = .;                  /* 定义初始化数组起始符号 */
KEEP (*(SORT(.init_array.*)))            /* 强制保留并排序所有.init_array.*段(优先级排序的C++构造函数) */
KEEP (*(.init_array))                    /* 强制保留.init_array段(C++全局构造函数指针数组) */
__init_array_end = .;                    /* 定义初始化数组结束符号 *//*C++ runtime: destructors for static variables.C runtime: designated finializers
*/
. = ALIGN(4);                            /* 对齐到4字节边界 */
KEEP(*(.fini))                           /* 强制保留.fini段(C运行时终结代码) */. = ALIGN(4);                            /* 对齐到4字节边界 */
__fini_array_start = .;                  /* 定义终结数组起始符号 */
KEEP (*(.fini_array))                    /* 强制保留.fini_array段(C++全局析构函数指针数组) */
KEEP (*(SORT(.fini_array.*)))            /* 强制保留并排序所有.fini_array.*段(优先级排序的C++析构函数) */
__fini_array_end = .;                    /* 定义终结数组结束符号 *//*C++ runtime: static constructors
*/
. = ALIGN(4);                            /* 对齐到4字节边界 */
KEEP (*crtbegin.o(.ctors))               /* 强制保留crtbegin.o中的构造函数表起始部分 */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))/* 强制保留除crtend.o外所有.ctors段(C++静态构造函数) */
KEEP (*(SORT(.ctors.*)))                 /* 强制保留并排序所有.ctors.*段(优先级排序的静态构造函数) */
KEEP (*crtend.o(.ctors))                 /* 强制保留crtend.o中的构造函数表结束部分 */
Flash中的.text段布局:
+----------------------+
| .text (程序代码)     |
| .rodata (只读数据)   |
| .glue_7 (ARM/Thumb)  |
+----------------------+
| __init_hook_array    | ← 自定义初始化钩子
+----------------------+
| .init                | ← C运行时初始化
+----------------------+
| __preinit_array      | ← C++预初始化
+----------------------+
| __init_array         | ← C++全局构造函数
+----------------------+
| .ctors               | ← C++静态构造函数
+----------------------+
| __fini_array         | ← C++全局析构函数
+----------------------+
| .fini                | ← C运行时终结
+----------------------+

bootloader.ld

专门用于引导加载器的内存布局配置。

/*Generic bootloader linker script for STM32
*/INCLUDE definitions.ld                    /* 包含基础定义:内存区域、栈地址、堆地址等 *//* Define output sections */
SECTIONS
{/* ISR vector to be loaded */.isr_vector :{_sisr_vector = .;                    /* 定义向量表起始地址符号 */KEEP(*(.isr_vector))                 /* 强制保留中断向量表,防止链接器优化掉 */. = ALIGN(4);                        /* 对齐到4字节边界 */_eisr_vector = .;                    /* 定义向量表结束地址符号 */} > REGION_ISR_VECT AT> REGION_TEXT_STORAGE  /* VMA在ISR向量区域,LMA在代码存储区域 */_isr_load = LOADADDR(.isr_vector);     /* 获取向量表在Flash中的加载地址(LMA) */g_pfnVectors = _isr_load;              /* 创建全局符号指向向量表,供C代码使用 *//* The program code and other data goes into FLASH */.text :{FILL(0xFFFF)                         /* 未初始化区域填充0xFFFF(Flash擦除状态) */CREATE_OBJECT_SYMBOLS                 /* 为每个输入对象文件创建符号,用于调试 */_stext = .;                          /* 定义代码段起始地址符号 */KEEP(*(.version))                    /* 强制保留版本信息段 */KEEP(*(.bootversiondata))            /* 强制保留引导加载器版本数据段 */INCLUDE common_text.ld               /* 包含通用代码段定义:程序代码、只读数据、C++运行时等 */. = ALIGN(4);                        /* 对齐到4字节边界 */_etext = .;        /* define a global symbols at end of code */  /* 定义代码段结束地址符号 */} > REGION_TEXT AT> REGION_TEXT_STORAGE  /* VMA在代码区域,LMA在代码存储区域 */_text_load = LOADADDR(.text);          /* 获取代码段在Flash中的加载地址(LMA) */INCLUDE common_sections.ld             /* 包含通用数据段定义:.data, .bss, .ram等 */
}

firmware.ld

/*Generic firmware linker script for STM32
*/INCLUDE definitions.ld                    /* 包含基础定义:内存区域、栈地址、堆地址等常量 *//* Define output sections */
SECTIONS
{.bootloader :{FILL(0xFFFF)                         /* 未初始化区域填充0xFFFF(Flash擦除状态) */KEEP(*(.bootloader))                 /* 强制保留.bootloader段内容 */. = BOOTLOADER_SIZE;                 /* 当前位置前进到BOOTLOADER_SIZE(32KB)处 */} > REGION_BOOTLOADER                  /* 放置在引导加载器区域(Flash开头) *//* Used only with H7 */.firmware_header (READONLY) :          /* 固件头段(仅H7系列使用,F4可能忽略) */{KEEP(*(.fwdescription))              /* 强制保留固件描述信息段 */} > REGION_TEXT AT> REGION_TEXT_STORAGE  /* VMA在代码区域,LMA在代码存储区域 *//* ISR vector to be loaded */.isr_vector :                          /* 中断向量表段 */{. = ALIGN(4);                        /* 对齐到4字节边界 */_sisr_vector = .;                    /* 定义向量表起始地址符号 */KEEP(*(.isr_vector))                 /* 强制保留中断向量表,防止链接器优化掉 */. = ALIGN(4);                        /* 对齐到4字节边界 */_eisr_vector = .;                    /* 定义向量表结束地址符号 */} > REGION_ISR_VECT AT> REGION_TEXT_STORAGE  /* VMA在ISR向量区域,LMA在代码存储区域 */_isr_load = LOADADDR(.isr_vector);     /* 获取向量表在Flash中的加载地址(LMA) *//* Main code section */.text (READONLY) :                     /* 主代码段(只读属性) */{FILL(0xFFFF)                         /* 未初始化区域填充0xFFFF */CREATE_OBJECT_SYMBOLS                 /* 为每个输入对象文件创建符号,用于调试 */_stext = .;                          /* 定义代码段起始地址符号 */KEEP(*(.fwversiondata))              /* 强制保留固件版本数据段 */INCLUDE common_text.ld               /* 包含通用代码段定义:程序代码、只读数据、C++运行时等 */. = ALIGN(4);                        /* 对齐到4字节边界 */_etext = .;                          /* 定义代码段结束地址符号 */} > REGION_TEXT AT> REGION_TEXT_STORAGE  /* VMA在代码区域,LMA在代码存储区域 */_text_load = LOADADDR(.text);          /* 获取代码段在Flash中的加载地址(LMA) */INCLUDE common_sections.ld             /* 包含通用数据段定义:.data, .bss, .ram, 堆栈等 */.text_end_section : {} > REGION_TEXT AT > REGION_TEXT_STORAGE  /* 文本结束标记段(空段,用于计算长度) */_firmware_length = LOADADDR(.text_end_section) - LOADADDR(.firmware_header);  /* 计算固件总长度:从固件头到代码结束 */_firmware_version = _text_load;        /* 固件版本信息指向代码段开始位置 */
}

Flash物理布局

0x08000000 +-----------------+ ← REGION_BOOTLOADER|   Bootloader    | 32KB (保留区域)
0x08008000 +-----------------+ ← REGION_ISR_VECT|  Firmware Header| (H7专用,F4可能为空)+-----------------+ ← _sisr_vector|  中断向量表     | ← _isr_load (加载地址)+-----------------+ ← _eisr_vector|                 ||   主程序代码    | ← _stext, _text_load|   (.text等)     |+-----------------+ ← _etext|  数据初始值     | (.data段初始值)+-----------------+|  固件版本数据   | ← _firmware_version+-----------------+
http://www.dtcms.com/a/434828.html

相关文章:

  • 商务网站构建与维护网站建设所有权
  • C语言速成秘籍——跳转语句(goto)
  • WPF实现串口热插拔 (提供百度网盘源代码)
  • 企业网站关键词排名南京比较好的网络策划公司
  • FFmpeg 核心 API 系列:avcodec_find_decoder / avcodec_alloc_context3 / avcodec_open2
  • 文件上传简单的绕过总结
  • Visual Studio Code中launch.json深度解析:C++调试的艺术
  • 天长市建设局网站惠来做网站
  • 51单片机红外遥控
  • Java 集合 “List + Set”面试清单(含超通俗生活案例与深度理解)
  • 云南网站建设哪个好软文广告平台
  • 《嵌入式 – GD32开发实战指南(RISC-V版本)》第8章 PWM输出实现
  • HNU 编译系统 第一次作业
  • 网站怎么做交易平台图片生成网页链接在线
  • 渗透测试中的信息收集:文档元数据
  • minikube 的 kubernetes 入门教程-kubeSphere
  • 深圳 手机网站建设彩妆做推广的网站
  • 网站跳转是什么意思郑州建站网站的公司
  • 老题新解|再求 f(x,n)
  • 【Android cmd命令的执行流程】
  • c++26新功能—constexpr在稳定排序中的应用
  • AI生成悬疑故事
  • 泰山派rk3566烧录
  • Phpstudy博客网站apache2日志分析python代码
  • asp网站程序优点做App和网站 聚马
  • 免费软件下载网站入口正能量微信开发公众平台
  • 【系统重装】Windows无法安装到这个磁盘提示选中的磁盘具有MBR分区表解决方法(亲测有效)
  • MySQL 查询与更新语句执行过程深度解析:从原理到实践​
  • Bella Beauty – Aesthetic Medical Clinic WordPress Theme: A Practical
  • 洗车店会员管理系统数据分析