RISC-V体系结构的U-Boot引导过程 第一阶段

RISC-V体系结构的U-Boot引导过程 第一阶段

flyfish

.globl _start
_start:

.globl使符号对链接器可见相当于C语言中的Extern,声明此变量,并且告诉链接器此变量是全局变量,外部可以访问.u-boot.lds里的ENTRY(_start)也是这里的_start。
即指定入口为_start,_start就是整个start.S的开始的地方,是整个uboot的代码的开始
_start:表示其是一个标号Label,类似于C语言goto后面的标号

在这里插入图片描述

#if CONFIG_IS_ENABLED(RISCV_MMODE)
	csrr	a0, CSR_MHARTID
#endif

RISCV_MMODE 就是 machine mode
RISCV_SMODE就是supervisor mode
依据

choice
	prompt "Run Mode"
	default RISCV_MMODE

config RISCV_MMODE
	bool "Machine"
	help
	  Choose this option to build U-Boot for RISC-V M-Mode.

config RISCV_SMODE
	bool "Supervisor"
	help
	  Choose this option to build U-Boot for RISC-V S-Mode.
#define CSR_MHARTID		0xf14

执行该语句csrr a0, CSR_MHARTID之后a0寄存器存储了hartid
依据下表
在这里插入图片描述

la	t0, trap_entry

la t0, trap_entry
LA是Load Address,语法是LA rd, symbol
la指令的格式,将内存地址symbol加载到rd寄存器中
trap_entry 可以看mtrap.S
这里是将trap_entry加载到临时寄存器t0中

#include <common.h>
#include <asm/encoding.h>

#ifdef CONFIG_32BIT
#define LREG		lw
#define SREG		sw
#define REGBYTES	4
#else
#define LREG		ld
#define SREG		sd
#define REGBYTES	8
#endif

	.text

	/* trap entry */
	.align 2
	.global trap_entry
trap_entry:
	addi sp, sp, -32 * REGBYTES
	SREG x1,   1 * REGBYTES(sp)
	SREG x2,   2 * REGBYTES(sp)
	SREG x3,   3 * REGBYTES(sp)
	SREG x4,   4 * REGBYTES(sp)
	SREG x5,   5 * REGBYTES(sp)
	SREG x6,   6 * REGBYTES(sp)
	SREG x7,   7 * REGBYTES(sp)
	SREG x8,   8 * REGBYTES(sp)
	SREG x9,   9 * REGBYTES(sp)
	SREG x10, 10 * REGBYTES(sp)
	SREG x11, 11 * REGBYTES(sp)
	SREG x12, 12 * REGBYTES(sp)
	SREG x13, 13 * REGBYTES(sp)
	SREG x14, 14 * REGBYTES(sp)
	SREG x15, 15 * REGBYTES(sp)
	SREG x16, 16 * REGBYTES(sp)
	SREG x17, 17 * REGBYTES(sp)
	SREG x18, 18 * REGBYTES(sp)
	SREG x19, 19 * REGBYTES(sp)
	SREG x20, 20 * REGBYTES(sp)
	SREG x21, 21 * REGBYTES(sp)
	SREG x22, 22 * REGBYTES(sp)
	SREG x23, 23 * REGBYTES(sp)
	SREG x24, 24 * REGBYTES(sp)
	SREG x25, 25 * REGBYTES(sp)
	SREG x26, 26 * REGBYTES(sp)
	SREG x27, 27 * REGBYTES(sp)
	SREG x28, 28 * REGBYTES(sp)
	SREG x29, 29 * REGBYTES(sp)
	SREG x30, 30 * REGBYTES(sp)
	SREG x31, 31 * REGBYTES(sp)
	csrr a0, MODE_PREFIX(cause)
	csrr a1, MODE_PREFIX(epc)
	csrr a2, MODE_PREFIX(tval)
	mv a3, sp
	jal handle_trap
	csrw MODE_PREFIX(epc), a0

	LREG x1,   1 * REGBYTES(sp)
	LREG x3,   3 * REGBYTES(sp)
	LREG x4,   4 * REGBYTES(sp)
	LREG x5,   5 * REGBYTES(sp)
	LREG x6,   6 * REGBYTES(sp)
	LREG x7,   7 * REGBYTES(sp)
	LREG x8,   8 * REGBYTES(sp)
	LREG x9,   9 * REGBYTES(sp)
	LREG x10, 10 * REGBYTES(sp)
	LREG x11, 11 * REGBYTES(sp)
	LREG x12, 12 * REGBYTES(sp)
	LREG x13, 13 * REGBYTES(sp)
	LREG x14, 14 * REGBYTES(sp)
	LREG x15, 15 * REGBYTES(sp)
	LREG x16, 16 * REGBYTES(sp)
	LREG x17, 17 * REGBYTES(sp)
	LREG x18, 18 * REGBYTES(sp)
	LREG x19, 19 * REGBYTES(sp)
	LREG x20, 20 * REGBYTES(sp)
	LREG x21, 21 * REGBYTES(sp)
	LREG x22, 22 * REGBYTES(sp)
	LREG x23, 23 * REGBYTES(sp)
	LREG x24, 24 * REGBYTES(sp)
	LREG x25, 25 * REGBYTES(sp)
	LREG x26, 26 * REGBYTES(sp)
	LREG x27, 27 * REGBYTES(sp)
	LREG x28, 28 * REGBYTES(sp)
	LREG x29, 29 * REGBYTES(sp)
	LREG x30, 30 * REGBYTES(sp)
	LREG x31, 31 * REGBYTES(sp)
	LREG x2,   2 * REGBYTES(sp)
	addi sp, sp, 32 * REGBYTES
	MODE_PREFIX(ret)
csrw	MODE_PREFIX(tvec), t0

根据定义

#if CONFIG_IS_ENABLED(RISCV_SMODE)
#define MODE_PREFIX(__suffix)	s##__suffix
#else
#define MODE_PREFIX(__suffix)	m##__suffix
#endif

MODE_PREFIX(tvec)就是mtvec或者stvec
mtvec(Machine Trap Vector)
中断(interrupt)和异常(exception)在RISCV里被统称为trap
在这里插入图片描述

csrw	MODE_PREFIX(ie), zero

机器模式中断使能控制寄存器(MIE)
机器模式中断使能控制寄存器(MIE)用于控制不同中断类型的使能和屏蔽。该寄存器的位长是 64 位,
寄存器的读写权限是机器模式可读写,即非机器模式访问都会导致非法指令异常。
MSIE-机器模式软件中断使能位:
• 当 MSIE 为 0 时,机器模式软件中断无效。
• 当 MSIE 为 1 时,机器模式软件中断有效

屏蔽所有中断。对于U-Boot,全局禁用中断(处于m/sstatus),但我们需要读取m/sip以确定是否获得IPI

MODE_PREFIX(ie) 就是mie或者sie
m/sstatus 表示mstatus和sstatus
mstatus表示Machine Status,M模式下的处理器状态寄存器
m/sip 表示 mip和sip
mip表示Machine Interrupt Pending, M模式下的中断待定寄存器
表示哪些中断处于待定(Pending,)状态
IPI,全称是Inter-Processor Interrupt,是在SoC内多个core之间触发的中断
在这里插入图片描述

li	t0, CONFIG_NR_CPUS
bge	tp, t0, hart_out_of_bounds_loop

缩写

Branch if equal (BEQ) 
Branch if not equal (BNE) 
Branch if less than (BLT)
Branch if less than unsigned (BLTU) 
Branch if greater than equal (BGE) 

语法

bge reg1, reg2, label   # if reg1 >= reg2, branch to label
beq reg1, reg2, label   # if reg1 == reg2, branch to label
bne reg1, reg2, label   # if reg1 != reg2, branch to label

tp寄存器里是hart id,t0寄存器里是Maximum number of CPUs
如果 tp >=t0 跳转 到 hart_out_of_bounds_loop

bge blt rs1,rs2,imm 如果rs1 >= rs2(有符号方式),跳转

此处跳转到hart_out_of_bounds_loop

li是 Load Immediate
加载立即数
CONFIG_NR_CPUS是预定义的,表示Maximum number of CPUs

CONFIG_NR_CPUS=32

或者

#define CONFIG_NR_CPUS		1

SMP, Symmetric Multi-Processor

#if CONFIG_IS_ENABLED(RISCV_MMODE)
	li	t0, MIE_MSIE
#else
	li	t0, SIE_SSIE
#endif
	csrs	MODE_PREFIX(ie), t0
#endif

根据条件编译 加载立即数 MIE_MSIE 还是SIE_SSIE到t0
SIE (Interrupt Enable)
SIP (Interrupt Pending)

#define MIE_MSIE		(_AC(0x1, UL) << IRQ_M_SOFT)
#define SIE_SSIE		(_AC(0x1, UL) << IRQ_S_SOFT)
#define IRQ_S_SOFT		1
#define IRQ_M_SOFT		3

_AC的意思

用于处理常量的宏

#ifdef __ASSEMBLY__
#define _AC(X,Y)	X
#define _AT(T,X)	X
#else
#define __AC(X,Y)	(X##Y)
#define _AC(X,Y)	__AC(X,Y)
#define _AT(T,X)	((T)(X))
#endif

在C语言里

#define CONNECT(x,y) x##y

表示连接

int n = CONNECT(12,34);

n的值是1234
RISC-V 程序计数器 (PC)程序计数寄存器(Program Counter Register)
RISC-V 引入了一个特殊的通用寄存器 X0 。

RISC-V 通用寄存器 X0 的的特性就是:读出来的值永远为 0 ,写入的值将会被丢弃
RISC-V 将 PC 单独拿出来作为一个特殊的寄存器来对待.

RISC-V 很多伪指令的实现都是通过 X0 通用寄存器与常用的普通指令相结合而实现的
每当完成取指令操作后,PC = PC + 1 这里的 +1 是增加【一条指令的长度 ÷ 寻址粒度】

初始堆栈指针地址

/*
 * Set stackpointer in internal/ex RAM to call board_init_f
 */
call_board_init_f:
	li	t0, -16
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	li	t1, CONFIG_SPL_STACK
#else
	li	t1, SYS_INIT_SP_ADDR
#endif
	and	sp, t1, t0		/* force 16 byte alignment */

加法指令

and	and rd,rs1,rs2

将rs1寄存器的值 和 rs2寄存器的值相加,将结果写入到rd寄存器中

and sp, t1, t0
sp栈指针寄存的初始化

对于我们的初始堆栈指针地址,最常见的情况是,我们定义了一个静态初始RAM地址位置(CFG_SYS_INIT_RAM_ADDR)和大小(CFG_SYS_INIT_RAM_SIZE),并从中减去生成的全局数据(GENERATED_GBL_DATA_SIZE)大小。

#ifdef CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR
#define SYS_INIT_SP_ADDR	CONFIG_CUSTOM_SYS_INIT_SP_ADDR
#else
#ifdef CONFIG_MIPS
#define SYS_INIT_SP_ADDR	(CFG_SYS_SDRAM_BASE + CFG_SYS_INIT_SP_OFFSET)
#else
#define SYS_INIT_SP_ADDR	\
	(CFG_SYS_INIT_RAM_ADDR + CFG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#endif
#endif

CONFIG_SPL_BUILD和CONFIG_SPL_STACK配置的情况下
不同的板子配置也是不同的

#define CONFIG_SPL_TEXT_BASE		0x60		/* sram start+header */
#define CONFIG_SPL_MAX_SIZE		0x5fa0		/* 24KB on sun4i/sun7i */
#define LOW_LEVEL_SRAM_STACK		0x00008000	/* End of sram */
#define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

儿童遗留监测成为「加分项」,多种技术路线「争夺战」一触即发

儿童遗留密闭车内&#xff0c;温度可以在短短15分钟内达到临界水平&#xff0c;从而可能导致中暑和死亡&#xff0c;尤其是当汽车在太阳底下暴晒。 按照Euro NCAP给出的指引&#xff0c;与车祸相比&#xff0c;儿童因车辆中暑而死亡的情况较少&#xff0c;但却是完全可以避免的…

基于改进MRAS算法的永磁同步电机参数辨识

基于改进MRAS算法的永磁同步电机参数辨识 摘 要永磁同步点电机参数辨识算法介绍永磁同步电机数学模型改进MRAS参数辨识算法递推最小二乘法辨识原理递推最小二乘法结合MRAS算法原理仿真结果分析总结 摘 要 在永磁同步电机运行时&#xff0c;电机的电气参数会受到温度以及磁链饱…

【使用指导】wifi蓝牙二合一模块LCS2028与服务器的数据收发功能测试指导

在物联网智能家居、智能照明、智能楼宇、智慧工厂、智能制造等领域的数据透传、智能控制应用中&#xff0c;支持UART串口通信的低功耗WiFi蓝牙二合一模块应用极为广泛。模块性能测试环节中会测试模块与服务器的数据收发功能&#xff0c;确保功能性能够满足项目应用需求。本篇就…

在Mybatis执行插入数据时,如何将Date类型字段设置为“yyyy-MM-dd”的格式

1、问题描述 使用mybatis新增插入一条数据到MySQL数据库时&#xff0c; 其中实体类对象的一个属性”hiredate“的类型是日期类型Date&#xff0c; 此属性在数据库中对应的字段“hiredate”类型也是日期Date类型&#xff0c; 但是在数据库中要求“hiredate”字段的字段值为“yy…

Kendo UI R2 2023 crack

Kendo UI R2 2023 crack 新组件&#xff1a;角度PDFViewer 直接在Angular应用程序中查看PDF文件&#xff0c;无需第三方软件或附加组件。 凭借直观的分页机制、强大的搜索功能和灵活的缩放选项&#xff0c;用户可以轻松导航和浏览PDF内容。 角度16支架 Angular 16引入了一系列改…

视频网页前端禁止截屏代码实现js

有言在先 原理是采用商业级DRM实现&#xff0c;DRM 许可证费用目前没有免费服务商&#xff0c;腾讯云价格是0.0056元/次。 另外此功能不兼容安卓&#xff0c;安卓系统无法正常播放视频&#xff01; 先展示效果 可以看到截屏时刻出现黑屏&#xff0c;录屏也能保证全黑状态。…

搭建Freekan私人影视电影网站,cpolar内网穿透发布上线

文章目录 1.前言2.本地网页搭建2.1 环境使用2.2 支持组件和环境设置2.3 支持组件选和环境设置2.4 网页安装2.5 测试和使用2.6 问题解决 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 转发自CSDNprobezy的文章&#xff1a;使用Cpolarfreekan源码…

驱动开发:内核RIP劫持实现DLL注入

本章将探索内核级DLL模块注入实现原理&#xff0c;DLL模块注入在应用层中通常会使用CreateRemoteThread直接开启远程线程执行即可&#xff0c;驱动级别的注入有多种实现原理&#xff0c;而其中最简单的一种实现方式则是通过劫持EIP的方式实现&#xff0c;其实现原理可总结为&am…

Spring Security --- 自定义登录逻辑

目录 UserDetailsService详解 返回值 方法参数 异常 PasswordEncoder密码解析器详解 接口介绍 内置解析器介绍 BCryptPasswordEncoder简介 代码演示 自定义登录逻辑 编写配置类 自定义逻辑 UserDetailsService详解 当什么也没有配置的时候&#xff0c;账号和密码是…

基于51单片机设计的呼吸灯

一、项目介绍 呼吸灯是一种常见的LED灯光效果,它可以模拟人类呼吸的变化,使灯光看起来更加柔和和自然。51单片机是一种广泛使用的微控制器,具有体积小、功耗低、成本低等优点,非常适合用于控制LED呼吸灯。本项目的呼吸灯将使用PWM(脉冲宽度调制)技术控制LED亮度,从而实…

ES6学习笔记

作用域 1.4垃圾回收机制 内存的生命周期 JS环境中分配的内存&#xff0c;一般有如下生命周期 内存分配:当我们声明变量、函数、对象的时候&#xff0c;系统会自动为他们分配内存1.2.内存使用:即读写内存&#xff0c;也就是使用变量、函数等内存回收: 使用完毕&#xff0c;由…

BRC20赛道的刚需基础设施,BrccSwap如何延续新的造富神话?

引言 BRC20代币和去中心化交易所的背景 BRC20代币赛道的刚需SWAP BrccSwap如何延续新的造富神话 结语 引言 随着加密货币市场的不断发展&#xff0c;BRC20代币和去中心化交易所成为了越来越受欢迎的概念。BRC20代币是建立在比特币区块链上的代币&#xff0c;具有高级别的…

Dalamud 插件开发白皮书 P1 - Getting started

文章目录 从哪里开始 How do I get started?Dalamud 插件例子Dalamud 底层探究XIVLauncher 启动器 在哪里寻找帮助 Where do I ask for help?如何热重载插件 How do I hot-reload my plugin?如何调试插件&#xff0c;甚至游戏&#xff1f;如何在编码过程中使用 How do I use…

浅谈微前端

本文呢是我梳理的一个扫盲文&#xff0c;由于最近团队准备使用微前端对项目进行改造&#xff0c;所以我呢就先浅了解一下&#xff1a; 微前端到底是什么&#xff1f; 为什么要使用微前端&#xff1f; 都有哪些微前端方案&#xff1f; 微前端有什么不好的地方吗&#xff1f; 通过…

手动渲染农场和自助云渲染农场的区别

手动渲染农场和自助云渲染农场是两种常见的渲染方式&#xff0c;它们各有优缺点。手动渲染农场指的是在本地使用自己的硬件设备进行渲染&#xff0c;而自助云渲染农场则是利用云服务商提供的计算资源进行渲染。对于需要渲染大规模项目的设计师或工作室来说&#xff0c;选择一种…

C++11学习笔记(3)——通用工具(上)(包含重要特性智能指针Smart pointer)

1.Pair 在C11中&#xff0c;std::pair是一个模板类&#xff0c;用于将两个值组合成一个单元。它可以将两个不同的类型的值配对在一起&#xff0c;并且提供了对这对值的访问和操作。 std::pair的定义 template<class T1, class T2> struct pair{T1 first;T2 second; };…

【JAVA开发环境配置】 卸载JDK很简单, 一分钟帮你搞定!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

Context Prior for Scene Segmentation--CVPR, 2020

Context Prior for Scene Segmentation–CVPR, 2020 文章目录 Context Prior for Scene Segmentation--CVPR, 2020一、背景介绍二、方法介绍1.A的生成2.Affinity Loss3.如何从 X X X获取P4.Y操作 一、背景介绍 问题&#xff1a;现阶段&#xff0c;不少语义分割方法所限于卷积结…

Android12之如何查看hidl服务(一百五十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

软件项目管理需要具备哪些能力?

作为一名软件项目管理者&#xff0c;在处理许多事情时需要不断提高个人在数据分析处理、项目业务流程管理等各个领域的能力。当然作为过来人&#xff0c;我也很清楚很多软件项目管理新人也较为疑惑如何提高自己的能力和专业水平&#xff0c;以便提高工作效率。那我也想与大家唠…