uboot:源码分析-启动第一阶段-start.S解析

start.S引入

进入start.S文件中,发现57行中就是_start标号的定义处

在这里插入图片描述

SourceInsight中添加行号

在这里插入图片描述
在SI中,如果我们知道我们要找的文件的名字,但是我们又不知道他在哪个目录下,我们要怎样找到并打开这个文件?方法是在SI中先打开右边的工程项目管理栏目,然后点击最左边那个(这个是以文件为单位来浏览的),然后在上面输入栏中输入要找的文件的名字。我们在输入的时候,SI在不断帮我们进行匹配,即使你不记得文件的全名只是大概记得名字,也能帮助你找到你要找的文件。

在这里插入图片描述

start.S解析

不简单的头文件包含

#include <config.h>
#include <version.h>
#if defined(CONFIG_ENABLE_MMU)
#include <asm/proc/domain.h>
#endif
#include <regs.h>#ifndef CONFIG_ENABLE_MMU
#ifndef CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE    CFG_UBOOT_BASE
#endif
#endif

(1)#include <config.h>。config.h是在include目录下的,这个文件不是源码中本身存在的文件,而是配置过程中自动生成的文件。mkconfig文件的134-141行创建(默认情况)/追加(make -a时追加)include/config.h文件,这里仅仅添加了一个头文件。这个文件的内容其实是包含了一个头文件:#include<configs/x210_sd.h>".

在这里插入图片描述
(2)经过分析后,发现start.S中包含的第一个头文件就是:include/configs/x210_sd.h,这个文件是整个uboot移植时的配置文件。
include/configs/x210_sd.h文件和start.S文件关联了起来。因此之后在分析start.S文件时,主要要考虑的就是x210_sd.h文件。
(3)#include <version.h>。include/version.h中包含了include/version_autogenerated.h,这个头文件就是配置过程中自动生成的。version_autogenerated.h里面就一行内容:#define U_BOOT_VERSION “U-Boot 1.3.4”。这里面定义的宏U_BOOT_VERSION的值是一个字符串,字符串中的版本号信息来自于Makefile中的配置值。这个宏在程序中会被调用,在uboot启动过程中会串口打印出uboot的版本号,那个版本号信息就是从这来的。
主Makefile的29行VERSION_FILE = $(obj)include/version_autogenerated.h:版本信息将被写入到构建输出目录的include子目录下名为version_autogenerated.h的文件中。编译过后的目录当中才会有这个文件,内容是编译过后的版本号

在这里插入图片描述

(4)#include <asm/proc/domain.h>。asm目录不是uboot中的原生目录,uboot中本来是没有这个目录的。asm目录是配置时创建的一个符号链接,实际指向的是就是asm-arm,在mkconfig文件的第33行到第118行都是创建符号链接
在这里插入图片描述
(5)经过分析后发现,实际文件是:include/asm-arm/proc-armv/domain.h

在这里插入图片描述
在这里插入图片描述
(6)从这里可以看出之前配置时创建的符号链接的作用,如果没有这些符号链接则编译时根本通不过,因为找不到头文件。(所以uboot不能在windows的共享文件夹下配置编译,因为windows中没有符号链接)

这样的设计主要是为了可移植性。因为如果直接包含,则start.S文件和CPU架构(和硬件)有关了,可移植性就差了。譬如我要把uboot移植到mips架构下,则start.S源代码中所有的头文件包含全部要修改。我们用了符号链接之后,则start.S中源代码不用改,只需要在具体的硬件移植时配置不同,创建的符号链接指向的不同,则可以具有可移植性。

启动代码的16字节头部

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED).word 0x2000.word 0x0.word 0x0.word 0x0
#endif

1.#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
:这是一个预处理条件指令。它检查CONFIG_EVT1是否已定义(即是否在代码的某处通过#define CONFIG_EVT1进行了定义),并且检查CONFIG_FUSED是否未定义(即没有通过#define CONFIG_FUSED进行定义)。只有当这两个条件同时满足时,紧随其后的代码块才会被编译。
2…word 0x2000
、.word 0x0、.word 0x0、.word 0x0:这四行代码是汇编语言指令,用于在生成的机器代码中插入字面量值。.word指令通常用于在内存中分配一个或多个字(word)的空间,并将指定的值存储在那里。在这个例子中,它分配了四个连续的32位(或相应大小的)空间,并分别初始化为0x2000、0x0、0x0、0x0。
3.#endif
:这标志着预处理条件指令的结束。

在SD卡启动/Nand启动等整个镜像开头需要16字节的校验头。(mkv210image.c中就是为了计算这个校验头)。

uboot这里start.S中在开头位置放了16字节的填充占位,这个占位的16字节只是保证正式的image的头部确实有16字节,但是这16字节的内容是不对的,还是需要后面去计算校验和然后重新填充的。

/home/aa/work0630/pro/uboottest/uboot/sd_fusing/C110-EVT1-mkbl1.c 内容就是mkv210image.c的内容

在这里插入图片描述
在这里插入图片描述

异常向量表的构建

    b    resetldr    pc, _undefined_instructionldr    pc, _software_interruptldr    pc, _prefetch_abortldr    pc, _data_abortldr    pc, _not_usedldr    pc, _irqldr    pc, _fiq

ldr pc, _label指令的意思是“将标签_label所代表的地址加载到程序计数器(PC)中。

1._undefined_instruction
:未定义指令异常。当执行了一条未定义的指令时,会跳转到这个地址。
2._software_interrupt
:软件中断。这是由软件触发的中断,通常用于操作系统或应用程序之间的通信。
3._prefetch_abort
:预取中止异常。当ARM处理器试图预取一条指令,但由于某种原因(如内存访问权限问题)无法完成时,会发生这种异常。
4._data_abort
:数据中止异常。当处理器试图访问数据(而不是指令)时,由于某种原因(如内存访问权限问题)无法完成,会发生这种异常。
5._not_used
:未使用的异常向量。在ARMv6及更早的版本中,这个位置是保留的,没有被使用。
6._irq
:IRQ(中断请求)异常。这是由外部设备或内部定时器触发的硬件中断。
7._fiq
:FIQ(快速中断请求)异常。这是另一种硬件中断,但优先级高于IRQ,通常用于需要快速响应的情况。

(1)异常向量表是硬件决定的,软件只是参照硬件的设计来实现它。
(2)异常向量表中每种异常都应该被处理,否则真遇到了这种异常就跑飞了。但是我们在uboot中并未非常细致的处理各种异常。
(3)复位异常处的代码是:b reset,因此在CPU复位后真正去执行的有效代码是reset处的代码,因此reset符号处才是真正的有意义的代码开始的地方。

有点意思的deadbeef

    .balignl 16,0xdeadbeef

.balignl 16,0xdeadbeef 这条指令是ARM汇编语言中的一条伪指令,用于在代码中插入对齐填充,以确保后续的代码或数据位于一个特定的地址对齐。
具体来说:

  • .balignl 是指示进行长字(long word,即4字节或32位)对齐的伪指令。
  • 16 表示对齐的边界,即对齐到16字节(128位)的边界上。
  • 0xdeadbeef 是一个填充值,用于在对齐过程中填充到内存中,以确保对齐。这个值通常是一个魔数(magic number),用于调试或标记对齐位置。

(1).balignl 16,0xdeadbeef. 这一句指令是让当前地址对齐排布,如果当前地址不对齐则自动向后走地址直到对齐,并且向后走的那些内存要用0xdeadbeef来填充。
(2)0xdeadbeef这是一个十六进制的数字,这个数字很有意思,组成这个数字的十六进制数全是abcdef之中的字母,而且这8个字母刚好组成了英文的dead beef这两个单词,字面意思是坏牛肉。
(3)为什么要对齐访问?有时候是效率的要求,有时候是硬件的特殊要求。

TEXT_BASE等

_TEXT_BASE:.word    TEXT_BASE
  • _TEXT_BASE:
    是一个标签,它通常用于表示一个代码段或者数据段的起始地址。在链接(linking)过程中,这个标签会被替换成一个具体的内存地址。
  • .word
    是一条伪指令,用于在当前位置插入一个32位的字(word)。这个字的内容就是紧跟在 .word 后面的表达式或立即数的值。
  • TEXT_BASE
    是一个符号(symbol),它代表了一个具体的数值或者地址。这个符号在链接过程中会被解析成一个具体的地址值。

(1)第100行这个TEXT_BASE就是上个课程中分析Makefile时讲到的那个配置阶段的TEXT_BASE,其实就是我们链接时指定的uboot的链接地址。(值就是c3e00000)
TEXT_BASE变量。最终来源是Makefile中配置对应的命令中,在make xxx_config时得到的
关联知识点:指定程序的链接地址有2种方法
(2)源代码中和配置Makefile中很多变量是可以互相运送的。简单来说有些符号的值可以从Makefile中传递到源代码中。

_TEXT_PHY_BASE:.word    CFG_PHY_UBOOT_BASE
#define CFG_PHY_UBOOT_BASE    MEMORY_BASE_ADDRESS + 0x3e00000
#define MEMORY_BASE_ADDRESS    0x30000000

(1)CFG_PHY_UBOOT_BASE 33e00000 uboot在DDR中的物理地址
虚拟地址是C3e00000

设置CPU为SVC模式

在这里插入图片描述

msr    cpsr_c, #0xd3        @ I & F disable, Mode: 0x13 - SVC
  • msr 是 Move to Special Register 的缩写,表示将数据移动到特殊寄存器。
  • cpsr_c 表示当前程序状态寄存器的控制域。CPSR 是一个32位的寄存器,包含了当前处理器的状态和模式信息。其中,c域(控制域)包含了中断(I)和快中断(F)的使能位。
  • #0xd3 是一个立即数,表示要写入c域的值。在ARM架构中,寄存器的值通常以十六进制表示。
  • @ I & F disable, Mode: 0x13 - SVC 是一条注释,解释了这条指令的作用:禁用中断(I)和快中断(F),并将处理器模式设置为0x13,即SVC(Supervisor)模式。
    具体来说,#0xd3 这个值包含了处理器模式和中断使能位的信息。在ARM架构中,CPSR的M[4:0]位用于表示处理器模式,而I位和F位用于控制中断和快中断的使能。
  • M[4:0] = 0x13 表示处理器处于SVC模式。
  • I = 1 表示禁用中断。
  • F = 1 表示禁用快中断(在某些ARM版本中,F位可能用于其他目的,但在这里我们假设它用于控制快中断)。

(1)msr cpsr_c, #0xd3 将CPU设置为禁止FIQ IRQ,ARM状态,SVC模式。
(2)其实ARM CPU在复位时默认就会进入SVC模式,但是这里还是使用软件将其置为SVC模式。整个uboot工作时CPU一直处于SVC模式。

设置L2、L1cache和MMU

(1)bl disable_l2cache // 禁止L2 cache
(2)bl set_l2cache_auxctrl_cycle // l2 cache相关初始化
(3)bl enable_l2cache // 使能l2 cache
(4)刷新L1 cache的icache和dcache。
(5)关闭MMU
总结:上面这5步都是和CPU的cache和mmu有关的,不用去细看,大概知道即可。

识别并暂存启动介质选择

        ldr    r0, =PRO_ID_BASEldr    r1, [r0,#OMR_OFFSET]bic    r2, r1, #0xffffffc1

(1)从哪里启动是由SoC的OM5:OM0这6个引脚的高低电平决定的。
(2)实际上在210内部有一个寄存器(地址是0xE0000004),这个寄存器中的值是硬件根据OM引脚的设置而自动设置值的。这个值反映的就是OM引脚的接法(电平高低),也就是真正的启动介质是谁。
(3)我们代码中可以通过读取这个寄存器的值然后判断其值来确定当前选中的启动介质是Nand还是SD还是其他的。
(4)start.S的225-227行执行完后,在r2寄存器中存储了一个数字,这个数字等于某个特定值时就表示SD启动,等于另一个特定值时表示从Nand启动····
(5)260行中给r3中赋值#BOOT_MMCSD(0x03),这个在SD启动时实际会被执行,因此执行完这一段代码后r3中存储了0x03,以后备用。

    /* SD/MMC BOOT */cmp     r2, #0xcmoveq   r3, #BOOT_MMCSD    

设置栈(SRAM中的栈)并调用lowlevel_init

    /** Go setup Memory and board specific bits prior to relocation.*/ldr    sp, =0xd0036000 /* end of sram dedicated to u-boot */sub    sp, sp, #12    /* set stack */mov    fp, #0

(1)284-286行第一次设置栈。这次设置栈是在SRAM中设置的,因为当前整个代码还在SRAM中运行,此时DDR还未被初始化还不能用。栈地址0xd0036000是自己指定的,指定的原则就是这块空间只给栈用,不会被别人占用。
(2)在调用函数前初始化栈,主要原因是在被调用的函数内还有再次调用函数,而BL只会将返回地址存储到LR中,但是我们只有一个LR,所以在第二层调用函数前要先将LR入栈,否则函数返回时第一层的返回地址就丢了。

学习记录,侵权联系删除。
来源:朱老师物联网大课堂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146160.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

教你快速制作一本3D翻页电子杂志

​在制作3D翻页电子杂志之前&#xff0c;我们需要了解一些基本概念。3D翻页电子杂志主要通过翻页效果来展示内容&#xff0c;读者可以通过手指滑动或点击鼠标来进行翻页。此外&#xff0c;它还支持图片、文字、视频等多种媒体形式的展示&#xff0c;为读者带来全方位的阅读体验…

KTH5774 —— 3D 摇杆/操纵杆霍尔位置传感器芯片

KTH5774 是一款摇杆、操纵杆专用的 3D 霍尔磁感 应芯片&#xff0c;主要面向对线性度和可靠性要求严格的应用 场景。 KTH5774 基于 3D 霍尔技术&#xff0c;内部分别集成了 X 轴、 Y 轴和 Z 轴三个独立的霍尔元件&#xff0c;能够通过测量和 处理磁通密度矢量的三个空间分量…

决策树算法中篇

手动计算实现决策树分类 数据整合 X[真实用户] y X 计算未划分信息熵 s X[真实用户] p s.value_counts()/s.size (p * np.log2(1/p)).sum() 按照日志密度进行划分 x X[日志密度].unique() x.sort() # 如何划分呢&#xff0c;分成两部分 for i in range(len(x) - 1):sp…

Checkstyle 使用总结

1. 使用 GitHub 地址&#xff1a;checkstyle/checkstyle: Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard. 官网文档地址&#xff1a;checkstyle – Checkstyle 10.17.0 1.1 IDEA 插件 在 IDEA 搜索插件 CheckS…

DOS(Disk Operating System,磁盘操作系统)常用指令

目录 背景: 早期探索: DOS之父&#xff1a; 发展历程&#xff1a; 常用指令&#xff1a; 进入命令&#xff1a; 操作1.进入和回退&#xff1a; 操作2.增、删&#xff1a; 操作3.其它&#xff1a; 总结: 背景: 早期探索: DOS(Disk Operating System,磁盘操作系统)在…

基于云的补丁管理

什么是云补丁 云补丁或基于云的补丁管理是指扫描和检测缺失补丁、测试补丁并将它们部署到所需系统的过程&#xff0c;所有这些都通过基于云的控制台或软件完成。虽然补丁管理工作流程通常保持不变&#xff0c;但基于云的补丁管理的主要区别在于&#xff0c;整个过程仅通过基于…

数据跨境流通发展现状浅析

文章目录 前言一、数据跨境流通的场景二、数据跨境流通国内发展现状三、数据跨境流通国外发展现状1、国外的数据跨境政策类型&#xff1a;&#xff08;1&#xff09;美国以数据自由流动为核心&#xff08;2&#xff09;欧盟将人权保护作为首要考虑&#xff08;3&#xff09;俄罗…

2.1 SQL语言及如何创建数据表

一、什么是SQL语言 SQL语言全称叫做结构化查询语言&#xff0c;它是一种计算机语言&#xff0c;但是跟其他编程语言来比较还是有很大区别的。比如说HTML&#xff0c;CSS&#xff0c;Java script&#xff0c;这三种计算机语言是用在网页设计上面的。那么swift语言是用来开发IOS…

反转字符串中的单词--力扣151

反转字符串中的单词 题目思路代码 题目 思路 题目的难点在于首先要清除多余的空格&#xff0c;并且单词之间要留一个空格&#xff0c;首单词前和末尾单词后不能有多余空格。我们使用双指针去除所有的空格&#xff0c;然后在处理完一个单词后手动加一个单词。具体思路是当快指针…

k8s快速搭建+prometheus部署及使用(纯干货!!!)

目录 环境准备 1.所有主机安装docker 2.部署harbor 3.部署k8s 集群初始化 安装网络插件&#xff08;此时选择的是flannel网络插件 后面也有calico网络插件的安装方法&#xff09; 节点扩容 4.calico网络插件的部署&#xff08;如果安装了flannel插件需要先删除&#xf…

web前端-HTML常用标签-综合案例

如图&#xff1a; 代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document&…

LlamaIndex 中的 NodeParser

LlamaIndex 中 Document 会被转成 Node,Node 中的文字会进行 Embedding,最终保留向量数据做后续的搜索处理。这里的关键步骤是 Document 转为 Node 的策略,LlamaIndex 内置了多个 Document Reader 和 Node Parser,每个 NodeParser 都有自己的策略,需在初始化时进行设置。 …

基于springboot+vue超市管理系统

基于springbootvue超市管理系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本无人超市管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助使用者在…

STM32如何修改外部晶振频率和主频

对于STM32F10x系列的单片机&#xff0c;除了STM32F10x_CL单片机&#xff0c;其它的单片机一般外部晶振HSE的时钟频率都默认是8MHz。如果我们使用的外部晶振为12Mhz&#xff0c;那么可以把上图绿色标记改为:12000000 72MHz的主频8MHz的外部晶振HSE*倍频系数9。当然如果像上面把外…

四款好用的电脑录屏工具推荐!!

在科技日益发展的今天&#xff0c;屏幕录制已成为我们工作、学习和娱乐中不可或缺的一部分&#xff1b;无论是制作教程、记录游戏过程还是分享精彩瞬间&#xff0c;一个好的录屏工具都是不可或缺的&#xff1b;今天&#xff0c;我就为大家推荐四款实用又好用的电脑录屏工具&…

矿用立式负压自动排渣放水器感恩遇见

做良心产品一直是我们的初心好产品加上好服务&#xff0c;让您满意是我们一直的追求只凭低价去换取销量的话&#xff0c;就会想方设法降低成苯质量难有保障 矿用立式负压自动排渣放水器感恩遇见 概述 负压自动排渣放水器的型号为YCFP&#xff0c;YC指品牌永成&#xff0c;FP指…

mac os x 找不到钥匙串访问

昨天手贱更新了最新的mac系统&#xff0c;结果在实用工具中找不到钥匙串访问APP了。。。 最新mac系统为 15.0 (24A335) 真是醉了。。。 那就得想办法把他给呼出来&#xff0c;在开发者中心下载了一个.cer文件&#xff0c;然后双击打开&#xff0c;此时钥匙串打开了&#xff…

CSP-CCF★201912-2回收站选址★

一、问题描述 二、解答 代码&#xff1a; #include<iostream> #include<map> using namespace std; struct rubbish{int x;int y; }rub[1000]; int n; void input(){cin>>n;for(int i0;i<n;i){cin>>rub[i].x>>rub[i].y;} } bool has(int p,…

化繁为简:中介者模式如何管理复杂对象交互

化繁为简&#xff1a;中介者模式如何管理复杂对象交互 中介者模式 是一种行为型设计模式&#xff0c;定义了一个中介者对象&#xff0c;来封装一组对象之间的交互。中介者模式通过将对象之间的交互行为从多个对象中抽离出来&#xff0c;集中封装在一个中介者对象中&#xff0c;…

FedOV

3 FEDOV: ONE-SHOT FEDERATED OPEN-SET VOTING FRAMEWORK 3.1 PROBLEM STATEMENT 假设有个客户端及其本地数据集。我们的目标是在服务器的帮助下&#xff0c;在不交换原始数据的情况下&#xff0c;训练一个优秀的机器学习模型 。此外&#xff0c;每个客户端只允许与服务器进行…