RVOS-1.环境搭建与系统引导

0.环境搭建

riscv-operating-system-mooc: 开放课程《循序渐进,学习开发一个 RISC-V 上的操作系统》配套教材代码仓库。 mirror to https://github.com/plctlab/riscv-operating-system-mooc

在 Ubuntu 20.04 以上环境下我们可以直接使用官方提供的 GNU工具链和 QEMU 模拟器,执行如下命令在线安装即可开始试验:

$ sudo apt update
$ sudo apt install build-essential gcc make perl dkms git gcc-riscv64-unknown-elf gdb-multiarch qemu-system-misc

构建和使用说明:

- `make`:编译构建
- `make run`:启动 `qemu` 并运行
- `make debug`:启动调试
- `make code`:反汇编查看二进制代码
- `make clean`:清理

1. 系统引导

1.1 引导程序入口

硬件地址映射:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

系统引导过程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

内核被加载到DRAM的地址 0x8000-0000,引导加载程序被加载到ROM的地址 0x0000-F0000x0000-0000

正常是固化在ROM的程序来引导,找到bootloader程序(BL0阶段)。但这里我们使用模拟器QEMU,在makefile里面指定了内核程序入口:在启动过程中,内核的入口点通常是位于ELF文件中的一个特定位置,这个位置由链接器脚本或者链接选项指定。在Makefile中,链接选项 -Ttext=0x80000000 指定了内核的文本段(代码段)应该被加载到内存地址 0x80000000 处。这意味着当QEMU启动时,它会将内核的代码和数据加载到这个地址,并且从这个地址开始执行。

总而言之:run 目标使用QEMU模拟器运行内核,运行的确实是内核os.elf,并且在ELF文件里面的0x80000000地方开始运行。

但是我们还是分析一下这段汇编

auipc t0, 0x0
addi a2, t0, 40 	#可能是栈
csrr a0, mhartid	#将硬件线程ID写入寄存器 a0。
lw a1, 32(t0)		#参数
lw t0, 24(t0)		#内核的入口地址存放处
jr t0				#jr t0:跳转到寄存器 t0 指向的地址,即内核的入口地址。
start: .word

没看明白,求大佬指点!

1.2 引导程序

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里类似于bootloader的 BL1阶段:

BL1阶段通常负责:

  • 初始化CPU和基本的硬件设备。
  • 设置栈指针。
  • 跳转到下一个阶段的bootloader(如BL2)或直接跳转到操作系统。

start.S:

#include "platform.h"# size of each hart's stack is 1024 bytes# 用于分配一段内存空间 “External Public Uninitialized Block".equ 	STACK_SIZE, 1024.global _start.text
_start:# park harts with id != 0让除了0号核的其他核都进入park状态csrr t0, mhartid 		# read current hart idmv  tp,t0				# save current hart id to tpbnez t0,park 			# if hart id != 0, park# Setup stacks, the stack grows from bottom to top, so we put the# stack pointer to the very end of the stack range.slli	t0, t0, 10		# shift left the hart id by 1024-->(for multiple harts)la	sp, stacks + STACK_SIZE	# set the initial stack pointer# to the end of the first stack spaceadd	sp, sp, t0			# move the current hart stack pointer# to its place in the stack spacej	start_kernel		# hart 0 jump to cpark:wfij park# In the standard RISC-V calling convention, the stack pointer sp# is always 16-byte aligned.
.balign 16
stacks:.skip	STACK_SIZE * MAXNUM_CPU # allocate space for all the harts stacks.end				# End of file

kernel.c

void start_kernel(void)
{while (1) {}; // stop here!
}

platform.h

#ifndef __PLATFORM_H
#define __PLATFORM_H#define MAXNUM_CPU 8#endif // __PLATFORM_H

运行结果:成功进入void start_kernel(void);
在这里插入图片描述疑问:这些文件怎么组织在一起的?

文件之间的联系是通过链接器来建立的。链接器(Linker)是编译过程中的一个工具,它将编译后的目标文件(Object Files,通常是 .o 文件)和库文件链接在一起,生成一个可执行文件(Executable File)或库文件(Library File)

在此项目中,链接过程是通过 Makefile 控制的。Makefile 中定义了如何编译和链接项目:

  1. OBJS_ASM 和 OBJS_C:这些变量定义了汇编和 C 语言的目标文件(Object Files)。

  2. ELF 和 BINELF 是链接后的可执行文件,BIN 是可执行文件的二进制格式。

  3. LDFLAGS:链接器标志,用于指定链接器的行为。在您的 Makefile 中,LDFLAGS 可以是 -T ${OUTPUT_PATH}/os.ld.generated(使用链接脚本)或 -Ttext=0x80000000(指定文本段的起始地址)。

  4. 链接命令

    ${ELF}: ${OBJS}ifeq (${USE_LINKER_SCRIPT}, true)${CC} -E -P -x c ${DEFS} ${CFLAGS} os.ld > ${OUTPUT_PATH}/os.ld.generatedendif${CC} ${CFLAGS} ${LDFLAGS} -o ${ELF} $^${OBJCOPY} -O binary ${ELF} ${BIN}
    

    这段代码首先检查是否使用链接脚本,如果是,则生成链接脚本文件。然后使用 CC(交叉编译器)和 LDFLAGS 链接目标文件,生成 ELF 文件。最后,使用 OBJCOPY 将 ELF 文件转换为二进制格式。

  5. 默认目标

    .DEFAULT_GOAL := all
    all: ${OUTPUT_PATH} ${ELF}
    

    默认目标是 all,它依赖于 OUTPUT_PATHELF 文件。

通过这些步骤,Makefile 确保了所有源文件被正确编译和链接,生成最终的可执行文件。链接器根据链接脚本(如果使用)或链接器标志来确定如何将各个目标文件和库文件组合在一起。

参考—汪老师讲的太好了!!!!:

1.3 RISC-V寄存器_RISC-V体系结构编程与实践(第2版)

【[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春】 https://www.bilibili.com/video/BV1Q5411w7z5/?p=19&share_source=copy_web&vd_source=d63943fdb26087d14a536adf35c52d6b

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UNet 改进(5):结合SE模块提升图像分割性能

U-Net是医学图像分割领域最成功的架构之一,其对称的编码器-解码器结构和跳跃连接使其能够有效捕捉多尺度特征。本文将解析一个改进版的U-Net实现,该版本通过引入Squeeze-and-Excitation(SE)模块进一步提升了模型性能。 一、架构概览 这个改进的U-Net保持…

机器人拧螺丝紧固装配(Robot screw fastening assembly)

机器人拧螺丝紧固装配技术正以其高精度、高效率和高灵活性,重塑着传统制造业的生产范式。这项融合了机械臂定位、扭矩控制、视觉引导与数据分析的自动化解决方案,不仅将工人从重复性高强度劳动中解放出来,更通过实时数据反馈与精准执行&#…

图像处理中的 Gaussina Blur 和 SIFT 算法

Gaussina Blur 高斯模糊 高斯模糊的数学定义 高斯模糊是通过 高斯核(Gaussian Kernel) 对图像进行卷积操作实现的. 二维高斯函数定义为 G ( x , y , σ ) 1 2 π σ 2 e − x 2 y 2 2 σ 2 G(x, y, \sigma) \frac{1}{2\pi \sigma^2} e^{-\frac{x^2 y^2}{2\sigma^2}} G(x…

在Unity中实现《幽灵行者》风格的跑酷动作

基础设置 角色控制器选择: 使用Character Controller组件或Rigidbody Capsule Collider 推荐使用Character Controller以获得更精确的运动控制 输入系统: 使用Unity的新输入系统(Input System Package)处理玩家输入 滑铲实现 public class Slide…

青蛙吃虫--dp

1.dp数组有关元素--路长和次数 2.递推公式 3.遍历顺序--最终影响的是路长&#xff0c;在外面 其次次数遍历&#xff0c;即这次路长所有情况都更新 最后&#xff0c;遍历次数自然就要遍历跳长 4.max时时更新 dp版本 #include<bits/stdc.h> using namespace std; #def…

Tiktok 关键字 视频及评论信息爬虫(2) [2025.04.07]

&#x1f64b;‍♀️Tiktok APP的基于关键字检索的视频及评论信息爬虫共分为两期&#xff0c;希望对大家有所帮助。 第一期&#xff1a;基于关键字检索的视频信息爬取 第二期见下文。 1.Node.js环境配置 首先配置 JavaScript 运行环境&#xff08;如 Node.js&#xff09;&…

Matlab绘图—‘‘错误使用 plot输入参数的数目不足‘‘

原因1&#xff1a; ❤️ 文件列名不是合法变量名 在excel中数据列名称为Sample:float,将:删除就解决了

Kotlin问题汇总

Kotlin问题汇总 真机安装调试 查看真机的Android版本&#xff0c;将build.gradle文件中的minSdk改为手机的Android版本&#xff0c;点Sync Now更新设置 apk安装失败 在gradle.properties全局配置中设置android.injected.testOnlyfalse Unresolved reference: 在activity_…

基于VMware的Cent OS Stream 8安装与配置及远程连接软件的介绍

1.VMware Workstation 简介&#xff1a; VMware Workstation&#xff08;中文名“威睿工作站”&#xff09;是一款功能强大的桌面虚拟计算机软件&#xff0c;提供用户可在单一的桌面上同时运行不同的操作系统&#xff0c;和进行开发、测试 、部署新的应用程序的最佳解决方案。…

Go语言从零构建SQL数据库(4)-解析器

SQL解析器&#xff1a;数据库的"翻译官"图解与代码详解 图解SQL解析过程 SQL解析器就像是人类语言与计算机之间的翻译官&#xff0c;将我们书写的SQL语句转换成数据库能够理解和执行的结构。 #mermaid-svg-f9gAqHutDLL4McGy {font-family:"trebuchet ms"…

十道海量数据处理面试题与十个方法总结

一、十道海量数据处理面试题 ♟️1、海量日志数据&#xff0c;提取出某日访问百度次数最多的那个IP。(分治思想 哈希表) 首先&#xff0c;从日志中提取出所有访问百度的IP地址&#xff0c;将它们逐个写入一个大文件中&#xff0c;便于后续处理。 考虑到IP地址是32位的&#…

SolidWorks2025三维计算机辅助设计(3D CAD)软件超详细图文安装教程(2025最新版保姆级教程)

目录 前言 一、SolidWorks下载 二、SolidWorks安装 三、启动SolidWorks 前言 SolidWorks 是一款由法国达索系统&#xff08;Dassault Systmes&#xff09;公司开发的三维计算机辅助设计&#xff08;3D CAD&#xff09;软件&#xff0c;广泛用于机械设计、工程仿真和产品开…

IntelliJ IDEA 2020~2024 创建SpringBoot项目编辑报错: 程序包org.springframework.boot不存在

目录 前奏解决结尾 前奏 哈&#xff01;今天在处理我的SpringBoot项目时&#xff0c;突然遇到了一些让人摸不着头脑的错误提示&#xff1a; java: 程序包org.junit不存在 java: 程序包org.junit.runner不存在 java: 程序包org.springframework.boot.test.context不存在 java:…

CPU 压力测试命令大全

CPU 压力测试命令大全 以下是 Linux/Unix 系统下常用的 CPU 压力测试命令和工具&#xff0c;可用于测试 CPU 性能、稳定性和散热能力。 1. 基本压力测试命令 1.1 使用 yes 命令 yes > /dev/null & # 启动一个无限循环进程 yes > /dev/null & # 启动第二个进…

#SVA语法滴水穿石# (003)关于 sequence 和 property 的区别和联系

在 SystemVerilog Assertions (SVA) 中,sequence 和 property 是两个核心概念,它们既有区别又紧密相关。对于初学者,可能不需要过多理解;但是要想写出复杂精美的断言,深刻理解两者十分重要。今天,我们汇总和学习一下该知识点。 1. 区别 特性sequenceproperty定义描述一系…

WordPress浮动广告插件+飘动效果客服插件

源码介绍 WordPress浮动广告插件飘动效果客服插件 将源码上传到wordpress的插件根目录下&#xff0c;解压&#xff0c;然后后台启用即可 截图 源码免费获取 WordPress浮动广告插件飘动效果客服插件

虚幻基础:蓝图基础知识

文章目录 组件蓝图创建时&#xff0c;优先创建组件&#xff0c;如c一样。 UI控件控件不会自动创建&#xff0c;而是在蓝图创建函数中手动创建。 函数内使用S序列接退出&#xff0c;并不会等所有执行完再退出&#xff0c;而是一个执行完后直接退出 组件 蓝图创建时&#xff0c;…

《AI大模型应知应会100篇》加餐篇:LlamaIndex 与 LangChain 的无缝集成

加餐篇&#xff1a;LlamaIndex 与 LangChain 的无缝集成 问题背景&#xff1a;在实际应用中&#xff0c;开发者常常需要结合多个框架的优势。例如&#xff0c;使用 LangChain 管理复杂的业务逻辑链&#xff0c;同时利用 LlamaIndex 的高效索引和检索能力构建知识库。本文在基于…

深度学习项目--分组卷积与ResNext网络实验探究(pytorch复现)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 ResNext是分组卷积的开始之作&#xff0c;这里本文将学习ResNext网络&#xff1b;本文复现了ResNext50神经网络&#xff0c;并用其进行了猴痘病分类实验…

从代码学习深度学习 - RNN PyTorch版

文章目录 前言一、数据预处理二、辅助训练工具函数三、绘图工具函数四、模型定义五、模型训练与预测六、实例化模型并训练训练结果可视化总结前言 循环神经网络(RNN)是深度学习中处理序列数据的重要模型,尤其在自然语言处理和时间序列分析中有着广泛应用。本篇博客将通过一…