杰发科技AC7840——编译链接过程

链接脚本(.ld)与启动文件(.s)的关系

概述

在嵌入式 ARM 项目中,链接脚本(.ld)和启动汇编文件(.s)通过符号名在链接阶段建立联系。启动文件引用符号,链接脚本定义符号地址。


1. 启动文件定义符号引用

启动文件 startup_ac7840x.s 中引用了链接脚本定义的符号:

asm 复制代码
; 第 46-54 行,定义数据段和 BSS 段的地址引用
.word  _sidata    ; Flash 中 .data 初始值地址
.word  _sdata     ; RAM 中 .data 段起始地址
.word  _edata     ; RAM 中 .data 段结束地址
.word  _sbss      ; .bss 段起始地址
.word  _ebss      ; .bss 段结束地址

; 第 71 行,设置栈指针
ldr   sp, =_estack   ; 栈顶地址

2. 链接脚本定义这些符号

链接脚本 ac7840x_flash.ld 中定义了上述符号的具体地址:

ld 复制代码
_sidata = .;              /* 第 83 行,Flash 中 .data 初始值地址 */
_sdata = .;               /* 第 94 行,RAM 中 .data 段起始 */
_edata = .;               /* 第 99 行,RAM 中 .data 段结束 */
_sbss = .;                /* 第 124 行,.bss 段起始 */
_ebss = .;                /* 第 131 行,.bss 段结束 */
_estack = .;              /* 第 159 行,栈顶地址 */

3. 链接阶段整合

编译和链接的流程:

复制代码
汇编编译:  startup_ac7840x.s  →  startup_ac7840x.o  (符号未解析)
C 编译:    main.c            →  main.o
链接:      gcc *.o -T ac7840x_flash.ld  →  Demo.elf
                ↓
        链接器用 .ld 中定义的地址
        替换 .o 中的符号引用

在链接阶段,链接器读取链接脚本,确定各符号的最终地址,然后替换目标文件(.o)中所有对这些符号的引用。


4. 实际作用

启动文件 Reset_Handler 使用链接脚本定义的符号完成系统初始化:

asm 复制代码
ldr  r3, =_sidata    ; 从 Flash 读取 .data 初始值
ldr  r0, =_sdata     ; .data 在 RAM 中的起始地址
ldr  r3, =_edata     ; .data 在 RAM 中的结束地址
ldr  r2, =_sbss      ; .bss 起始地址
ldr  r3, =_ebss      ; .bss 结束地址

初始化过程:

  1. .data 段初始值从 Flash 拷贝到 RAM
  2. .bss 段清零
  3. 设置栈指针 sp = _estack
  4. 调用 SystemInit 进行时钟初始化
  5. 调用 main 进入应用程序

5. 内存布局示例

复制代码
Flash (0x00000000):
  ┌─────────────────┐
  │  .isr_vector     │  ← 中断向量表
  ├─────────────────┤
  │  .text           │  ← 程序代码
  ├─────────────────┤
  │  .data 初始值    │  ← _sidata 指向此处
  └─────────────────┘

RAM (0x1FFF0000):
  ┌─────────────────┐
  │  .data           │  ← _sdata ~ _edata
  ├─────────────────┤
  │  .bss            │  ← _sbss ~ _ebss
  ├─────────────────┤
  │  .heap           │  ← 堆区
  ├─────────────────┤
  │  .stack          │  ← _estack 指向栈顶
  └─────────────────┘

总结

  • 启动文件(.s):定义处理器复位后执行的初始化代码,引用链接脚本中的符号
  • 链接脚本(.ld):定义各段在内存中的位置,提供符号的具体地址
  • 联系 :两者通过符号名在链接阶段建立联系,完成系统的内存初始化
相关推荐
独小乐2 天前
019.ADC转换和子中断|千篇笔记实现嵌入式全栈/裸机篇
linux·c语言·驱动开发·笔记·嵌入式硬件·mcu·arm
电子科技圈3 天前
SmartDV展示完整的边缘与连接IP解决方案,以高速和低功耗特性赋能移动、物联网和媒体处理设备创新
人工智能·嵌入式硬件·mcu·物联网·智能家居·智能硬件·iot
天月风沙4 天前
Betaflight飞控、树莓派RP2350B主控编译教程
linux·单片机·嵌入式硬件·mcu·无人机·树莓派
电子科技圈5 天前
芯科科技2026 Tech Talks技术讲座启航聚焦无线与边缘 AI,共绘智能物联新蓝图
人工智能·嵌入式硬件·mcu·物联网·智能家居·智能硬件·iot
EVERSPIN6 天前
低功耗MCU对TWS充电仓的驱动控制
单片机·嵌入式硬件·mcu·低功耗mcu
白掰虾7 天前
STM32CubeMX2教程——STM32C5 UART
stm32·单片机·嵌入式硬件·mcu·usart·stm32cubemx2·stm32c542
狂奔蜗牛(bradley)9 天前
使用数组重构责任链实现通信协议解析
网络·mcu·重构
狂奔蜗牛(bradley)9 天前
嵌入式软件中如何用责任链模式重构串口协议栈
网络·单片机·mcu·重构·责任链模式
咸鱼嵌入式10 天前
【AutoSAR】详解CANIF模块
单片机·mcu·车载系统·autosar
EVERSPIN11 天前
高性能32位MCU在热敏打印机上的应用
单片机·嵌入式硬件·mcu·32位mcu