基于qemu-riscv从0开始构建嵌入式linux系统
文章平均质量分 86
本项目旨在真正从0开始构建嵌入式linux系统,为了剖析芯片从上电开始执行第一条指令到整个系统运行,相关应用服务启动,基于qemu自己编写(或使用qemu自带的)硬件ip相关模拟代码定制属于自己的硬件板卡。项目代码开源在github且更新要快于博客更新,如果想提前了解相关代码可以前往查看。
Quard_D
嵌入式爱好者,对嵌入式linux、RTOS、裸机均颇有研究,目前最感兴趣的是RISC-V相关。
展开
-
基于qemu-riscv从0开始构建嵌入式linux系统ch0.引言
基于qemu-riscv从0开始构建嵌入式linux系统ch0.引言引言本项目旨在真正从0开始构建嵌入式linux系统,为了剖析芯片从上电开始执行第一条指令到整个系统运行,相关应用服务启动,因此不使用市面上真实的板子,基于qemu定制模拟器开发板,且不使用qemu提供的快速加载elf的文件方式,因而我们需要下载qemu-6.0.0源码,自己编写(或使用qemu自带的)硬件ip相关模拟代码定制属于自己的硬件板卡。本项目同步制作博客专栏,因此项目尽量保证每增加一个feature就提......原创 2021-07-04 22:46:14 · 3191 阅读 · 7 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch1. 搭建qemu环境
基于qemu-riscv从0开始构建嵌入式linux系统ch1. 搭建qemu环境下载qemu源码开启我们的这个教程第一步自然是下载qemu最新的源码,截止目前qemu的最新发布版本为6.0.0,在这里笔者极力建议使用最新版,因为后面我们可能会需要一些新的组件,使用新版会带来更多的方便。qemu官网为:https://www.qemu.org/,6.0.0源码下载地址:https://download.qemu.org/qemu-6.0.0.tar.xz。(如果使用本教程配套github仓库,可以不需要原创 2021-07-04 22:48:02 · 1801 阅读 · 2 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch2. 添加qemu仿真板——Quard-Star板
基于qemu-riscv从0开始构建嵌入式linux系统ch2. 添加qemu仿真板——Quard-Star板增加源文件首先看下图,预览本节教程要添加的源代码,内容不多,主要是增加一个quard_star.c和.h文件用来定义我们的虚拟板卡,然后将其加入qemu编译体系内。源码解析路径qemu-6.0.0/hw/riscv/quard_star.c:(由于对应代码已上传github,我们这里仅对关键代码做以解析)注册板卡到系统内,并定义名称。static const TypeInfo quar原创 2021-07-04 22:49:32 · 2313 阅读 · 8 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch3. 添加中断控制器、串口、pflash支持
基于qemu-riscv从0开始构建嵌入式linux系统ch3. 添加中断控制器、串口、pflash支持添加串口支持真实板卡的初期调试中,串口打印可谓神器,几乎所以的IC都会带有串口这个外设,因此我们也需要添加串口到我们的定义中。首先添加三个串口基地址,之所以添加三个的目的是为了后面我们可能会在多个权限域空间内跑不同的系统因此可能需要不同权限的串口打印输出。{ [QUARD_STAR_UART0] = { 0x10000000, 0x100 }, [QUARD_S原创 2021-07-09 22:07:35 · 2498 阅读 · 4 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch4. 制作测试固件验证串口打印
基于qemu-riscv从0开始构建嵌入式linux系统ch4. 制作测试固件验证串口打印安装交叉编译器为了测试串口的使用,我们首先需要安装目标平台的交叉编译工具链,才能开始编写代码并生成固件仿真运行。交叉编译器我建议先使用bootlin上提供的riscv交叉编译工具链,链接如下:https://toolchains.bootlin.com/。下载如下版本的编译器:将其解压安装在你的任意目录,不过你可以像我一样,把他安装在/opt路径下,这样编译器的前缀为CROSS_PREFIX=/opt/ris原创 2021-07-10 23:26:31 · 1529 阅读 · 4 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch5-1. 什么是多级BootLoader与opensbi(上)
基于qemu-riscv从0开始构建嵌入式linux系统ch5-1. 什么是多级BootLoader与opensbi(上)多级BootLoader随着嵌入式的发展,如今的嵌入式IC也基本上转向了SOC的方式,因而其IC内部不仅仅是一颗cpu核,可能包含各种各样的其他IP,因而相关的上层软件也需要针对性的划分不同的功能域,操作域,安全域等上层应用。为了能支持复杂而碎片化的应用需求,SOC的Boot阶段延伸出了数级的BootLoader,为行文简单,我们把第一级BootLoader称作BL0,下一级则为BL原创 2021-07-11 15:56:02 · 3310 阅读 · 12 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch5-2. 什么是多级BootLoader与opensbi(下)
基于qemu-riscv从0开始构建嵌入式linux系统ch5-2. 什么是多级BootLoader与opensbi(下)opensbi源码结构目前opensbi的源码结构是比较简单清晰的,除了sbi目录内是核心文件,utils主要是用于设备树解析libfdt以及其他的驱动文件,当然这里的驱动都是使用设备树(设备树是从linux内核中广泛使用的一种设备描述文件,可以简化驱动代码的编写并提高驱动代码的复用率移植性,因此逐渐扩展到各个嵌入式平台级代码项目中,本节先不讲解设备树文件本身,下一节将对其进行讲解)原创 2021-07-17 00:18:48 · 1918 阅读 · 1 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch6. 设备树文件与opensbi加载运行
基于qemu-riscv从0开始构建嵌入式linux系统ch6. 设备树文件与opensbi加载运行什么是设备树文件上一篇中我们反复提到了设备树文件,那么究竟设备树文件是什么样的?有什么用?该如何编写使用呢?扁平设备树(Flattened Device Tree)简称FDT,是源于linux内核powerpc架构下对驱动的抽象分装技术,早年间linux内核中充斥者大量的mach-XXX的驱动代码,这对于当时的内核维护团队来说很是不满,而FDT的引入使得驱动的编写架构清晰,受到的大家的追捧,进而引入到所原创 2021-07-17 12:07:08 · 2211 阅读 · 3 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch7. OpenSBI Domain
基于qemu-riscv从0开始构建嵌入式linux系统ch7. OpenSBI DomainOpenSBI Domain介绍在上一节中,我们已经成功运行了OpenSBI,观察输出log可以看到有一组Domain0的信息打印出来,然后会进入到下级boot流程。那么Domain是做什么用的呢?实际上Domain是用来将SOC内部硬件人为的划分不同权限区域,然后分别独立运行,其使用了riscv的权限管理的硬件保护单元,如PMP等。OpenSBI运行在系统的M模式,而不同Domain的上层程序只能工作在S模式原创 2021-07-24 14:01:14 · 1468 阅读 · 1 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch8. U-Boot
基于qemu-riscv从0开始构建嵌入式linux系统ch8. U-BootU-Boot介绍终于我们的项目来到了u-boot,相信很多学习过嵌入式的朋友都听过或熟悉u-boot这个项目,在arm嵌入式开发中uboot常常作为二级loader甚至一级loader,用来引导linux内核。uboot早期是作为BootLoader开发的,主要功能就是loader+boot,如今的u-boot相比早期仅仅是从非易失性加载内核引导内核,还拥有了更多功能,比如通过网络功能,更新升级固件等等,因此我们的项目里也将u原创 2021-07-31 15:28:55 · 1517 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch9. U-Boot platform添加与内存分配重规划
基于qemu-riscv从0开始构建嵌入式linux系统ch9. U-Boot platform添加与内存分配重规划物理内存规划在上一节中,我们已经成运行了uboot,但是默认的配置并不那么适合我们的系统,如果是在真实的ic设计开发时,软件团队往往需要在早期就规划好系统内存的使用方案,包括各级boot且需要考虑固件升级等情况,因此这节我们也针对我们的内存空间做一重新规划调整。如下图所示,最终规划如下,pflash存储所有的低阶固件文件和资源,由位于pflash最前段的lowlevelboot将其他的固原创 2021-08-08 14:13:16 · 937 阅读 · 2 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch10. qemu之virtio与fw_cfg
基于qemu-riscv从0开始构建嵌入式linux系统ch10. qemu之virtio与fw_cfg上一节我们已经基本完成了uboot的移植,下一步自然就是移植linux kernel。在真实的嵌入式开发板上,内核往往会存储在文件系统中,当然也不排除一些直接裸存储于在sd卡或flash介质上,因为我们之前的qemu模拟器中没有添加sd卡或硬盘介质,因此本节我们先回过头来丰富一下qemu的资源。在qemu提供了很多虚拟的外设,但是为了使虚拟机性能更好,我们决定使用转为虚拟化打造的virtio技术来提供文原创 2021-08-08 17:47:48 · 1296 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch11-1. 向着linux Kernel出发!——加载引导
基于qemu-riscv从0开始构建嵌入式linux系统ch11-1. 向着linux Kernel出发!——加载引导kernel编译首先,我们添加linux内核源码到我们的项目中,内核官网:https://www.kernel.org/。这里我们选择5.10.42版本,一般来讲如果没有特殊需求选择一个比较新的longterm版本是比较稳妥可靠的。说起来linux kernel的编译是非常容易的,得益于linux内核良好的工程架构,只需要向编译脚本添加如下命令,即可生成Image文件。这里我们使用了ri原创 2021-08-09 14:59:34 · 1307 阅读 · 7 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch11-2. 向着linux Kernel出发!——完成启动
基于qemu-riscv从0开始构建嵌入式linux系统ch11-2. 向着linux Kernel出发!——完成启动编写测试init进程上一节中,我们的内核已经顺利完成了boot,驱动,文件系统均完成了初始化,然后系统将加载第一个用户态的程序以进行之后的流程,从内核打印可以看到内核试图在文件系统以下路径/sbin、/etc、/bin寻找init程序或者/bin/sh作为第一个进程,既然是用户态进程,不妨我们先不着急移植传统的init进程源码,先自己写一些简单的hello word看看。#includ原创 2021-08-09 16:55:23 · 988 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch12. busybox
基于qemu-riscv从0开始构建嵌入式linux系统ch12. busyboxbusybox工具包busybox号称嵌入式Linux的瑞士军刀,我们上节中测试了init进程,但是在常见的linux系统上有各自的init进程,比较常见的是sysvinit,而在嵌入式领域由于内存存储空间的限制,诞生了一款轻量级的GNU工具包即busybox,其中包含了系统启动的init进程。busybox官网地址:https://busybox.net/ 在这里可以下载最新版busybox-1.33.1。编译bus原创 2021-08-12 22:08:08 · 874 阅读 · 1 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch13. 最小根文件系统完成
基于qemu-riscv从0开始构建嵌入式linux系统ch13. 最小根文件系统完成busybox中init进程解析init进程代码主入口在busybox-1.33.1/init/init.c:1039,我们从上到下粗略分析下流程:创建信号集并且接管一系列系统信号,比如SIGINT、SIGQUIT、SIGPWR、SIGUSR1、SIGTERM、SIGUSR2等等。这些用于接管处理系统关机、重启等事件,因为init进程是不能直接退出的。设置默认的环境变量HOME=/PATH=/sbi原创 2021-08-13 20:33:03 · 502 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch14. 动态链接——elf文件的加载
基于qemu-riscv从0开始构建嵌入式linux系统ch14. 动态链接——elf文件的加载busybox动态链接之前我们配置busybox为静态编译,即是可以看到生成的二进制文件就几M的大小,如果后续我们在系统内添加更多的应用程序均为静态编译,可想而知对磁盘存储消耗很大,在嵌入式设备上是很不划算的,因此我们需要考虑动态链接库,将应用程序和C库分离,这样多个应用程序可以共享一个libc的共享库,不仅仅节省磁盘空间,同时还节约了多个应用程序同时运行时的内存开销。busybox使用动态库编译选项仅需修原创 2021-08-14 11:42:58 · 932 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch15. linux多用户管理
基于qemu-riscv从0开始构建嵌入式linux系统ch15. linux多用户管理inittab修改ch13中我们使用了-/bin/sh作为init进程的RESPAWN|ASKFIRST阶段执行,如此一来,系统在启动时无需输入用户名密码将直接使用root权限启动。而本节将配置多用户管理,因此inittab修改为:::sysinit:/etc/init.d/rcSconsole::respawn:/sbin/getty 38400 consoleconsole::restart:/sbin/i原创 2021-08-14 21:48:24 · 335 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch16. Framebuffer显示设备
基于qemu-riscv从0开始构建嵌入式linux系统ch16. Framebuffer显示设备virtio-gpu-device本节我们给qemu添加一块虚拟的显示设备,方便后面研究一些GUI的应用。由于之前我们向系统添加了8组virtio-mmio设备,并且挂载了virtio-blk-device作为文件系统存储设备,这次我们再添加virtio-gpu-device设备:$SHELL_FOLDER/output/qemu/bin/qemu-system-riscv64 \-M quard-st原创 2021-08-15 15:46:36 · 1348 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch17. bash——交叉编译应用
基于qemu-riscv从0开始构建嵌入式linux系统ch17. bash——交叉编译应用交叉编译嵌入式开发中免不了交叉编译,交叉编译就是使用的开发环境中运行编译器生成另一个平台的可执行程序,常见的pc开发平台就是x86的linux系统,而嵌入式平台一般是arm或者riscv的linux平台,一些低端嵌入式环境是rtos或裸机平台。本节我们就打算将linux系统内的bash工具进行交叉编译,移植到我们的riscv目标系统内,来代替busybox的ash作为shell。传统的GNU项目源码结构bas原创 2021-08-20 18:29:37 · 535 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch18. RTC设备与系统控制设备
基于qemu-riscv从0开始构建嵌入式linux系统ch18. RTC设备与系统控制设备RTC设备我们当前的qemu环境中使用date查看时间发现时间错误,而且即使主动修改时间也不能保存,下次重新启动qemu时间依旧会重置,这会有什么影响呢,目前最大的影响就是使用make工具处理一些工具的源码安装时,时间的错误导致一些错误的依赖检查,影响我们自动化安装脚本。因此我们需要向qemu添加一个虚拟的RTC时钟的组件,使得系统启动后获取到主机的时间,这样每次时间就不会错乱。qemu-6.0.0/hw/r原创 2021-08-21 10:57:54 · 719 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch19. 交叉编译sudo
基于qemu-riscv从0开始构建嵌入式linux系统ch19. 交叉编译sudosudosudo源码可以在sudo网站上下载:https://www.sudo.ws/download.html。sudo可以说在linux系统上用户使用率还是比较高的命令,安装sudo之后我们可以在管理员用户上使用系统,仅在需要提权时使用sudo,而平时不使用,可以防止系统遭到破坏。交叉编译sudo编译sudo,首先在host系统交叉编译./configure --host=riscv CXX=$CROSS_PR原创 2021-08-21 11:16:10 · 286 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch20. 交叉编译screen、tree、cu
基于qemu-riscv从0开始构建嵌入式linux系统ch20. 交叉编译screen、tree、cuscreenscreen源码可以在gnu网站上下载:https://ftp.gnu.org/gnu/screen/。screen是个人非常喜欢的终端管理工具,在没有图形界面的系统中,使用screen可以实现多终端窗口管理以及酷炫的窗口分割等功能,同时也体积较小适合嵌入式环境。screen编译编译screen,首先在host系统交叉编译./configure --host=riscv64-linu原创 2021-08-21 13:36:15 · 630 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch21. 实时操作系统FreeRTOS移植RISCV-S模式
基于qemu-riscv从0开始构建嵌入式linux系统ch21. 实时操作系统FreeRTOS移植RISCV-S模式FreeRTOSFreeRTOS在嵌入式行业内是非常出名了,这么多节过去了,我们不能忘记除了7个core上运行的linux系统外,我们还有个trusted_domain,今天我们就移植一个实时操作系统FreeRTOS到这个域中。注意这里的FreeRTOS运行在S模式上而非完全的裸机环境M模式上,而截止笔者撰写本文官方还没给出S模式的移植port文件,我也没搜索到相关内容,那我们就自己动手原创 2021-08-21 14:31:54 · 1444 阅读 · 4 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch22. 编译器与C/C++标准库
基于qemu-riscv从0开始构建嵌入式linux系统ch22. 编译器与C/C++标准库{TODO:文档施工中,笔者将很快编纂完成}本教程的github仓库:https://github.com/QQxiaoming/quard_star_tutorialgitee仓库:https://gitee.com/QQxiaoming/quard_star_tutorial本节所在tag:ch22...原创 2021-08-21 17:10:21 · 619 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch23. linux FB应用——Qt库移植
基于qemu-riscv从0开始构建嵌入式linux系统ch23. linux FB应用——Qt库移植{TODO:文档施工中,笔者将很快编纂完成}本教程的github仓库:https://github.com/QQxiaoming/quard_star_tutorialgitee仓库:https://gitee.com/QQxiaoming/quard_star_tutorial本节所在tag:ch23...原创 2021-08-21 17:11:41 · 1787 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch24. qemu网卡/linux内核网络配置
基于qemu-riscv从0开始构建嵌入式linux系统ch24. qemu网卡/linux内核网络配置virtio-net-device本节我们给系统添加网络相关的配置,和之前一样virtio-mmio还提供了网络设备的注册,这里我们选择添加qemu支持的最简单的user模式网络,其他博客中有大量介绍使用tap网桥等方式虚拟化的标准网络设备,但是在现在大家多使用笔记本开发,无线网卡往往都不支持虚拟网桥,因此免配置的user模式的虚拟网络是比较简单易用的,注意其存在两个限制即可目标机只支持tcp、u原创 2021-08-21 17:12:26 · 918 阅读 · 0 评论 -
基于qemu-riscv从0开始构建嵌入式linux系统ch25. sshd服务配置
基于qemu-riscv从0开始构建嵌入式linux系统ch25. sshd服务配置openssh很多在网络环境使用的嵌入式开发板后期产品开发稳定后一般都不会在使用串口登录终端,而是使用ssh连接,这就需要系统启动时添加启动sshd服务,在嵌入式linux上使用较多的就是openssh,提供了sshc和sshd的工具。交叉编译方式如下:zlib编译zlib库被很多工具依赖,交叉编译如下,完成后根据需求拷贝输出到目标系统内。export CC=$CROSS_PREFIX-gcc ./configu原创 2021-08-21 17:13:33 · 665 阅读 · 21 评论