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

(笔记)U-boot 2012.10 armv7启动汇编解析

U-Boot ARM汇编启动代码分析

文件概述

文件路径: arch/arm/cpu/armv7/start.S
目标平台: ARM Cortex-A系列处理器
功能: U-Boot bootloader的启动汇编代码
版本: U-Boot 2012.10

文件结构概览

start.S
├── 头文件包含和宏定义
├── 中断向量表 (_start)
├── 全局符号定义
├── 复位代码 (reset)
├── 代码重定位 (relocate_code)
├── CPU初始化函数
├── 异常处理函数
└── 栈和内存管理

1. 头文件包含部分 (第31-35行)

#include <asm-offsets.h>
#include <config.h>
#include <version.h>
#include <asm/system.h>
#include <linux/linkage.h>

作用:

  • asm-offsets.h: 汇编偏移量定义
  • config.h: 配置选项定义
  • version.h: 版本信息
  • asm/system.h: ARM系统相关定义
  • linux/linkage.h: 函数链接宏定义

2. 中断向量表 (第37-48行)

.globl _start
_start: b	reset                    # 复位向量 - 系统启动入口ldr	pc, _undefined_instruction   # 未定义指令异常ldr	pc, _software_interrupt      # 软件中断(SWI/SVC)ldr	pc, _prefetch_abort         # 指令预取异常ldr	pc, _data_abort            # 数据访问异常ldr	pc, _not_used              # 保留向量ldr	pc, _irq                   # 普通中断请求ldr	pc, _fiq                   # 快速中断请求

重要说明:

  • ARM处理器复位后首先执行_start标签
  • 这是ARM架构标准的8个32位向量表
  • ldr pc, label指令将标签地址加载到程序计数器,实现跳转
  • 向量表必须位于地址0x00000000或0xFFFF0000

3. 向量地址定义 (第49-62行)

根据CONFIG_SPL_BUILD配置选择不同的向量处理方式:

SPL构建模式:

_undefined_instruction: .word _undefined_instruction
_software_interrupt:    .word _software_interrupt
_prefetch_abort:        .word _prefetch_abort
# ... 其他向量指向自身,形成死循环

正常构建模式:

_undefined_instruction: .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:        .word prefetch_abort
# ... 向量指向实际的异常处理函数

4. 系统复位代码 (reset标签, 第125行开始)

4.1 保存启动参数

reset:bl	save_boot_params    # 保存bootloader传递的参数

4.2 CPU模式设置

	mrs	r0, cpsr           # 读取当前程序状态寄存器bic	r0, r0, #0x1f      # 清除模式位[4:0]orr	r0, r0, #0xd3      # 设置SVC32模式,禁用IRQ和FIQmsr	cpsr,r0            # 写回CPSR

模式说明:

  • 0xd3 = 11010011 (binary)
  • Bit[4:0] = 10011 (SVC32模式)
  • Bit[7] = 1 (禁用IRQ)
  • Bit[6] = 1 (禁用FIQ)

4.3 向量基地址设置

	mrc	p15, 0, r0, c1, c0, 0	# 读取系统控制寄存器bic	r0, #CR_V               # 清除V位,使VBAR有效mcr	p15, 0, r0, c1, c0, 0	# 写回控制寄存器ldr	r0, =_start             # 加载向量表基地址mcr	p15, 0, r0, c12, c0, 0	# 设置VBAR寄存器

4.4 低级初始化调用

#ifndef CONFIG_SKIP_LOWLEVEL_INITbl	cpu_init_cp15          # 初始化协处理器CP15bl	cpu_init_crit          # 关键CPU初始化
#endif

5. CPU协处理器初始化 (cpu_init_cp15)

5.1 缓存和TLB无效化

	mov	r0, #0mcr	p15, 0, r0, c8, c7, 0	# 无效化所有TLBmcr	p15, 0, r0, c7, c5, 0	# 无效化指令缓存mcr	p15, 0, r0, c7, c5, 6	# 无效化分支预测器mcr	p15, 0, r0, c7, c10, 4	# 数据同步屏障(DSB)mcr	p15, 0, r0, c7, c5, 4	# 指令同步屏障(ISB)

5.2 系统控制寄存器配置

	mrc	p15, 0, r0, c1, c0, 0   # 读取SCTLR寄存器bic	r0, r0, #0x00002000     # 清除V位(向量表高地址)bic	r0, r0, #0x00000007     # 清除C、A、M位orr	r0, r0, #0x00000002     # 设置A位(对齐检查)orr	r0, r0, #0x00000800     # 设置Z位(分支预测)orr	r0, r0, #0x00001000     # 设置I位(指令缓存)mcr	p15, 0, r0, c1, c0, 0   # 写回SCTLR

控制位说明:

  • M位(bit 0): MMU使能 (此时禁用)
  • A位(bit 1): 对齐检查使能
  • C位(bit 2): 数据缓存使能 (此时禁用)
  • I位(bit 12): 指令缓存使能
  • V位(bit 13): 向量表位置 (0=低地址,1=高地址)
  • Z位(bit 11): 分支预测使能

6. 堆栈设置和板级初始化

call_board_init_f:ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)  # 设置初始堆栈指针bic	sp, sp, #7                      # 8字节对齐ldr	r0,=0x00000000                  # 清零参数bl	board_init_f                     # 调用C语言板级初始化

7. 代码重定位过程 (relocate_code)

7.1 参数保存和堆栈设置

ENTRY(relocate_code)mov	r4, r0	# 保存堆栈指针地址mov	r5, r1	# 保存全局数据指针mov	r6, r2	# 保存目标地址stack_setup:mov	sp, r4  # 设置堆栈指针

7.2 重定位检查

	adr	r0, _start              # 获取当前运行地址cmp	r0, r6                  # 与目标地址比较moveq	r9, #0              # 如果相同,无需重定位beq	clear_bss               # 跳转到BSS清零

7.3 代码复制循环

copy_loop:ldmia	r0!, {r9-r10}       # 批量加载8字节数据stmia	r1!, {r9-r10}       # 批量存储到目标地址cmp	r0, r2                  # 检查是否完成blo	copy_loop               # 继续循环

7.4 动态重定位修复

fixloop:ldr	r0, [r2]                # 读取重定位地址add	r0, r0, r9              # 添加重定位偏移ldr	r1, [r2, #4]            # 读取重定位信息and	r7, r1, #0xff           # 获取重定位类型cmp	r7, #23                 # 相对重定位?beq	fixrelcmp	r7, #2                  # 绝对重定位?beq	fixabs

8. 异常处理框架

8.1 寄存器保存宏

.macro	bad_save_user_regssub	sp, sp, #S_FRAME_SIZE   # 在堆栈上开辟异常帧stmia	sp, {r0 - r12}      # 保存通用寄存器# ... 保存CPSR、PC、LR等状态寄存器
.endm

8.2 异常处理函数

undefined_instruction:get_bad_stack           # 获取异常处理堆栈bad_save_user_regs      # 保存用户寄存器bl	do_undefined_instruction  # 调用C处理函数prefetch_abort:get_bad_stackbad_save_user_regsbl	do_prefetch_abort   # 处理指令预取异常

9. 关键内存布局

9.1 符号定义

.globl _TEXT_BASE
_TEXT_BASE:.word	CONFIG_SYS_TEXT_BASE    # 代码段基地址.globl _bss_start_ofs
_bss_start_ofs:.word __bss_start - _start      # BSS段起始偏移.globl _bss_end_ofs
_bss_end_ofs:.word __bss_end__ - _start      # BSS段结束偏移

9.2 堆栈空间

.globl IRQ_STACK_START
IRQ_STACK_START:.word	0x0badc0de              # IRQ堆栈起始地址.globl FIQ_STACK_START
FIQ_STACK_START:.word 0x0badc0de               # FIQ堆栈起始地址

10. 启动流程总结

系统复位
跳转到_start
设置CPU为SVC32模式
配置向量基地址
初始化CP15协处理器
调用cpu_init_crit
设置堆栈指针
调用board_init_f
代码重定位到RAM
修复动态链接
清零BSS段
跳转到board_init_r
启动完成

11. 重要配置宏

宏定义作用
CONFIG_SPL_BUILDSPL(Secondary Program Loader)构建模式
CONFIG_SYS_TEXT_BASE代码段基地址
CONFIG_SYS_INIT_SP_ADDR初始堆栈指针地址
CONFIG_SKIP_LOWLEVEL_INIT跳过低级初始化
CONFIG_SYS_ICACHE_OFF禁用指令缓存
CONFIG_USE_IRQ启用中断支持

12. 调试要点

  1. 向量表位置: 确保向量表正确对齐和定位
  2. 堆栈设置: 检查堆栈指针是否指向有效内存
  3. 重定位过程: 验证代码是否正确复制到RAM
  4. 缓存一致性: 确保指令和数据缓存同步
  5. MMU状态: 初期MMU应该关闭

13. 常见问题

Q1: 系统启动后卡在向量表?

A: 检查向量表地址是否正确设置,VBAR寄存器配置是否有误。

Q2: 重定位后程序崩溃?

A: 检查重定位地址计算、动态链接修复是否正确。

Q3: 异常处理不工作?

A: 确认异常向量表、堆栈设置、处理函数地址是否正确。

http://www.dtcms.com/a/297708.html

相关文章:

  • C++STL系列之unordered_set和unordered_map
  • gig-gitignore工具实战开发(四):使用ai辅助生成gitignore
  • 开讲啦|MBSE公开课:第二集 MBSE远景设想
  • cocos creator 3.8.6 websocke的一直报错WebSocket is not a constructor
  • Logstash 多表增量同步 MySQL 到 Elasticsearch:支持逻辑删除与热加载,Docker 快速部署实战
  • vue项目创建流程
  • XML的简略知识点
  • PyCharm高效开发全攻略
  • RHCA - CL260 | Day01:Ceph 架构及环境介绍
  • leetcode102:二叉树的层序遍历(队列实现)
  • 栈----1.有效的括号
  • iOS WebView 调试实战,文件上传与权限弹窗异常的排查路径
  • 三维模型驱动下的光伏组件智能排列方案
  • 【深入底层】C++开发简历4+4技能描述6
  • 百特搭AI低代码平台助力企业国际化业务敏捷拓展
  • 《一种采用分布式多模态传感模块的身体尺度机器人皮肤的设计、评估与应用》论文解读
  • 【日志】unity俄罗斯方块——边界限制检测
  • 如何在离线电脑win11上安装VS2022
  • PI 思维升级 PI设计的典范转移:从阻抗思维到谐振控制
  • 在 Ansys CFX Pre 中配置 RGP 表的分步指南
  • C++中的反向迭代器
  • java面试题(中级题汇总)
  • k8s 中的 deployment,statefulset,daemonset 控制器的区别
  • 特征值与特征向量
  • 腾讯云CodeBuddy+微信小程序:5分钟开发番茄小闹钟
  • 电科金仓新一代数据库一体机:国产化方案替换优质选择
  • 本地内网IP映射到公网访问如何实现?内网端口映射外网工具有哪些?
  • python学习DAY22打卡
  • 深入解析Hadoop高频面试题:HDFS读/写流程的RPC调用链
  • yolov8通道级剪枝讲解(超详细思考版)