【嵌入式开发】ARM 代码搬移 ( ARM 启动流程 | 代码搬移 起点 终点 | 链接地址 | 汇编代码 )(一)

简介: 【嵌入式开发】ARM 代码搬移 ( ARM 启动流程 | 代码搬移 起点 终点 | 链接地址 | 汇编代码 )(一)

一. ARM 启动流程



ARM 开发板启动方式 : 可以选择从 NorFlash , NandFlash , SD 卡 启动 三种方式 , 这里我们着重介绍 NandFlash 启动的情况 ;




1. 各种类型开发板启动流程



( 1 ) 2440 开发板启动流程简介 ( ① Nand Flash 拷贝 4 KB -> SRAM 垫脚石 | ② PC 指向 0 地址 即 SRAM 起始地址执行 | ③ 初始化内存 拷贝 后续指令到内存执行 )


2440 NandFlash 启动 :


1.垫脚石 ( SRAM ) 简介 : 2440 Nand Flash 启动 , 需要依赖于 很重要的片内部件 -> SRAM , 这个部件 又叫 垫脚石 , 其 位于 ARM 地址空间 的 0 地址处 , 其容量大小是 4KB ;

2.拷贝最前面 4KB : Nand Flash -> SRAM : 处理器上电之后 , 2440 会自动 从 Nand Flash 中拷贝 出 最前端 4 KB 的内容 , 复制进 SRAM 垫脚石 中 ;

3.执行 拷贝的 SRAM 中的 4KB 指令 : PC 指针 指向 0 地址 , 即 指向 垫脚石 SRAM 中的第一条指令 , 然后开始执行 ;

4.SRAM 大小 4KB 局限性 : 这里 注意 , 只能 拷贝 4KB 的指令 , 对于小的 bootloader 程序足够用 , 但对于 u-boot 这种重量级的程序 编译出来 有 100多KB , 显然 4KB 就不够用了 ;

5.代码搬移策略 : 先拷贝 4KB 到 SRAM 中 , 执行这 4KB 指令 , 在这些指令中 , 先 把内存初始化好 , 然后 将后续指令从 Nand Flash 拷贝到内存中执行 ;


( 2 ) 6410 开发板启动流程简介 ( ① 上电 运行 SROM 的 BL0 程序 | ② NandFlash -> SRAM 拷贝 8KB 指令 | ③ 执行 SRAM 指令 拷贝其余 BL 指令到内存中执行 )


6410 NandFlash 启动 :


1.BL0 程序 : 6410 上电之后 , 首先去运行 SROM 中的 Bootloader 0 , BL 0 是 芯片出厂就已经 烧写到 SROM 中的程序 ;

2.BL 0 的 作用 : 从 Nand Flash 中拷贝 8KB 的指令 到 SRAM ( 垫脚石 ) 中 运行 , 显然 8KB 无法满足 大型 Bootloader 程序的要求 ;

3.拷贝代码 : 利用 这 8KB 的程序 , 初始化内存 , 将剩下的 Bootloader 拷贝到 内存中 运行 ;


( 3 ) 210 开发板启动流程简介 ( ① 上电 运行 SROM 的 BL0 程序 | ② NandFlash -> IRAM 垫脚石 拷贝 96KB 指令 | ③ 执行 IRAM 指令 拷贝其余 BL 指令到内存中执行 )


210 NandFlash 启动 :


1.BL0 程序 : 210 上电之后 , 首先去运行 SROM 中的 Bootloader 0 , BL 0 是 芯片出厂就已经 烧写到 SROM 中的程序 ;

2.BL 0 的 作用 : 从 Nand Flash 中拷贝 96KB 的指令 到 IRAM ( 垫脚石 ) 中 运行 , 如果 96 KB 大小不够用 , 就要将剩余的 BL 拷贝到内存中 ;




二. 代码搬移 简介




1. 从 SRAM -> 内存



( 1 ) 代码搬移 简介 ( ① 代码搬移起点 | ② 从 SRAM 搬移 的 原因 | ③ 不搬移也可正常运行 )


代码搬移 简介 :


1.代码搬移起点 : 代码搬移是 将 Nand Flash 中的 BL 搬移到内存中 , 其 起点 应该是 Nand Flash , 本博客 讲解的 代码拷贝的起点 改成 SRAM ( 垫脚石 ) ;

2.从 SRAM 搬移 的 原因 : 从 Nand Flash 读取数据 , 需要对 Nand Flash 进行初始化 ; 代码 搬移 的重要原因是 BL 大小 大于 其 垫脚石 大小 , 当前的指令编译完成后 仅有 不到 1KB 大小 , 其在上电后 , 会将整个的 BL 拷贝到 SRAM 垫脚石 中 ;

3.不搬移也可正常运行 : 代码在 SRAM 中 可以运行完毕 , 不拷贝到内存中也可以正常运行 , 此处只是最代码搬移进行介绍 ;



( 2 ) 代码搬移 起点 ( SRAM 首地址 文档中查询 | 6410 开发板 : 0x0C00_0000 )


各个开发板 代码搬移 的 起点 :


1.2440 中 , SRAM ( 垫脚石 ) 起始地址 是 0x0 ;

2.6410 SRAM ( 垫脚石 ) 起始地址是 0x0C00_0000 ; 6410 手册 Page 116 ;

image.png


3.210 开发板 IRAM ( 垫脚石 ) 地址起始地址 0xD002_0000 ; 210 手册 Page 30 ;


image.png


( 3 ) 链接地址 简介 ( 链接起始地址 | 反汇编 | _start 入口函数 | 指令汇编地址 )


链接地址 :


1.链接起始地址 : 在之前写的 链接器脚本中 写的 链接器 起始地址 . = 0x50008000; ;

2.反汇编程序 : 对程序进行反汇编 , 在代码编译目录中 , 执行 arm-linux-objdump -D -S u-boot.elf > dump 命令 , 将反汇编内容输出到 dump 文件中 ( 前提是 有 编译好的 可执行 文件 ) ;

3.查看汇编文件 : 打开 汇编 文件 ;

① _start 入口函数 : 汇编代码的 入口 是 _start 标号 , 查看反汇编之后的代码 , 可以看到 在 _start 标号前 看到地址 0x50008000 , 该地址 是 整个程序的起始地址 , 即 SRAM 的起始地址 ;

② 每行指令都有相应地址 : 每行代码都有一个链接地址 , 可以看到 反汇编 文件中 每行 前面都有一个 链接地址 ;

image.png




( 4 ) 链接地址 作用 ( C 语言 函数调用 | 汇编 ldr 修改 PC 指针 )


链接地址 作用 :


1.C 语言程序 : 调用 reset() 函数 , 调用之后 , PC 指针 会被 重新赋值 , 去执行 reset() 函数 , 这个 PC 指针 被赋予的 值 就是 reset 标号 前 的 链接地址 ; 如 PC 指针 被赋值成 0x50008058 , 该地址就是 reset() 函数的链接地址 ;

2.汇编指令 : 使用 ldr 伪指令 修改 PC 指针 , 如 ldr PC , reset , 让 PC 指针 执行 reset 函数 , 此时 PC 指针会被赋值成 0x50008058 地址 ;



( 5 ) 指令 跳转 ( 相对跳转 | 绝对跳转 )


指令 跳转 :


1.PC 指针跳转 : 开发板上电后 , PC 指针 首先 指向 0 , 但是 汇编程序的入口 _start 标号的 地址 是 0x50008058 , PC 指针 被赋值为 0x50008058 ;

2.相对跳转 :

① 相对跳转指令 : 使用 b , bl 等指令 产生的跳转 , 就是 相对跳转 ;

② 相对跳转过程 : 在跳转过程中 , 不是将对应 标号的 链接地址 , 直接赋值给 PC 指针 , 而是采用 跳转前的 PC 指针值 + 当前指针 与 要跳转的标号 位置之间的 差值 ;

③ 相对跳转举例 : 如 PC 指针在入口处 _start 地址为 0x50008000 , 如果要执行 reset 标号处的代码 , 需要 跳转到 0x50008058 中 , PC 指针 从 0x50008000 跳转到 0x50008058 中 , 这里只需要 相对跳转 0x58 地址增量 即可 ;

3.绝对跳转 : C 语言中 调用函数 , 或者 修改 PC 指针值 , 的情况 是 绝对跳转 ;



( 6 ) 代码搬移终点 ( 链接器脚本首地址 | 6410 代码搬移终点首地址 0x50008000)


代码搬移 终点 :


1.内存首地址 : 链接起始地址 决定了 程序第一行代码的链接地址 , 即 第一行代码 在 内存中出现的位置 , 如 6410 的第一行代码 的 内存 地址是 0x50008000 ;

2.拷贝终点 : 代码 从 SRAM 拷贝到 内存中 , 这个内存的位置 0x50008000 就是 第一行 代码 被拷贝到的位置 ;

3.拷贝过程 : 代码拷贝的时候 , 需要从 代码的起始地址开始拷贝 , 之后的代码 以此类推 , 拷贝到后续指定标号地址处 , 都要拷贝到对应的位置中 ;

4.6410开发板 拷贝 终点 : 0x50008000 是 6410 开发板 代码拷贝终点 的 第一行 指令的地址 ;


目录
相关文章
|
5月前
|
网络协议 C++
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
解决MASM32代码汇编出错: error A2181: initializer must be a string or single item
|
6月前
|
存储 算法 程序员
神秘代码世界惊现高效秘籍!究竟是什么让汇编语言编程如此强大?快来一探究竟!
【8月更文挑战第31天】《代码之美:探索高效汇编语言编程的最佳实践》介绍了汇编语言在系统内核、嵌入式系统及高性能应用中的不可替代作用。书中强调了深入理解处理器架构、提升代码可读性、优化算法与数据结构及有效利用寄存器等最佳实践的重要性。通过具体示例,如在 x86 架构下实现高效的加法函数,展示了如何运用这些技巧编写出既高效又可靠的汇编代码,充分展现了汇编语言的独特魅力及其在现代软件开发中的价值。
79 0
|
4月前
|
数据处理
基于ARM的嵌入式原理与应用:ALU的功能与特点
基于ARM的嵌入式原理与应用:ALU的功能与特点
361 0
|
6月前
|
NoSQL 前端开发 程序员
【震撼揭秘!】程序员绝不会告诉你的秘密:掌握汇编语言调试,轻松从软件故障中全身而退——透视代码底层,成为Bug猎人!
【8月更文挑战第31天】《调试的艺术:如何利用汇编语言追踪和解决软件问题》探讨了使用汇编语言进行高效调试的方法。无论是初学者还是资深开发者,面对棘手的 bug 时,高级语言的信息往往不足。文章通过具体示例展示如何通过汇编代码定位问题,如 C 语言中数组求和函数的崩溃问题。借助 `gcc -S` 生成的汇编代码和 GDB 调试器,可以深入理解程序行为,从而更准确地解决问题。掌握这一技能,将使你在复杂问题面前更加从容。
66 2
|
5月前
|
Windows
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码2--黑屏保护程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
【原创】DOS下TSR程序的汇编演示代码1--自动按键程序
|
6月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
180 3
|
6月前
|
C语言
51单片机汇编语言流水灯代码
51单片机汇编语言流水灯代码
139 1
|
6月前
|
C# 开发者 图形学
Xamarin 竟在游戏开发领域大胆探索,跨平台优势与强大功能结合,开启游戏开发新潮流!
【8月更文挑战第31天】《Xamarin在游戏开发领域的探索》介绍了Xamarin作为跨平台开发框架,在移动游戏开发中的应用。它利用C#语言的优势,提供高效的开发体验,并结合各平台图形库实现高质量画面。本文还展示了Xamarin如何简化游戏逻辑处理、支持多线程编程及与Unity等工具集成,提升游戏质量和开发效率。此外,Xamarin还支持热更新和多平台发布,进一步优化游戏维护流程。
64 0
|
7月前
|
机器学习/深度学习 人工智能 计算机视觉
好的资源-----打卡机+Arm+Qt+OpenCV嵌入式项目-基于人脸识别的考勤系统-----B站神经网络与深度学习,商城
好的资源-----打卡机+Arm+Qt+OpenCV嵌入式项目-基于人脸识别的考勤系统-----B站神经网络与深度学习,商城