基于 riscv32 的 OS 设计:完结 总结这十三篇博客是学习 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春 的笔记,今日终于完结了。 学完之后,收获很大,如果要是做过 riscv CPU 设计那效果更佳。 如果不考虑性能(需要精巧的数据结构和算法),OS 的核心就是模式转换。soc 提供了各种设备,启动的时候,得初始化这些设备,之后就能利用这些设备了,比如 CLINT、PLIC、UART 等。 ISA 也提 2025-04-01 OS #OS #riscv
基于 riscv32 的 OS 设计:系统调用 前言我们希望,用户程序仅仅运行在 U 模式,而 OS 代码统统运行在高权限模式下。这样,比如 tasks 的行为将会受到限制,比如它不能随意的修改 csr 寄存器,甚至修改 PLIC、CLINT、UART 寄存器以危害整个系统。 因此,某些可能会威胁到 OS 稳定运行的操作应该运行在高权限模式下,比如 S、M 模式。而 tasks 想要执行某些高权限操作,只能通过系统调用的方式来进行。 系统模式: 2025-03-29 OS #OS #riscv
基于 riscv32 的 OS 设计:软件定时器 软件定时器软件定时器和系统实现 _tick 基本没有什么差别。 硬件定时器:芯片本身提供的定时器,一般由外部晶振提供,提供寄存器设置超时时间,并采用外部中断方式通知 CPU,参考 第 12 章介绍。优点是精度高,但定时器个数受硬件芯片的设计限制。 软件定时器:操作系统中基于硬件定时器提供的功能,采用软件方式实现。扩展了硬件定时器的限制,可以提供数目更多(几乎不受限制)的定时器;缺点是精度较低,必须 2025-03-28 OS #OS #riscv
基于 riscv32 的 OS 设计:任务同步和锁 前言在前面,我们已经实现了抢占式任务,但是依然有很多的问题。 如果,两个任务不相关,也就是说没有数据上面的交互,那么是没有问题的。但是一旦涉及到访问共享资源,比如终端,就会出现问题: 1234567891011121314151617Task 0: Running...Task 0timer interruption!tick: 288Task 1: Running...Task 1: Runni 2025-03-26 OS #OS #riscv
基于 riscv32 的 OS 设计:抢占式多任务 前言关于任务如何切换,可以分为三种: 抢占式:任务自己不能决定是否让出,由外部原因引起; 协作式:任务自己放弃 CPU; 兼容协作式:抢占式任务的同时,自己还可以自愿放弃。 关于协作式,前面已经提到了。task0 通过 yield 来放弃当前 CPU。 与定时器配合抢占式可以基于时钟中断来实现,通过不断地产生时钟中断来做到任务切换。 思路大致为,当时钟中断到达的时候,进入到 trap_vect 2025-03-25 OS #OS #riscv
基于 riscv32 的 OS 设计:硬件定时器 CLINTRISC-V 规范规定,CLINT 的寄存器编址采用内存映射(memory map)方式。具体寄存器编址采用 base + offset 的格式,且 base 由各个特定 platform 自己定义。针对QEMU-virt,其 CLINT 的设计参考了 SFIVE,base 为 0x2000000。 相关寄存器mtime系统全局唯一,在 RV32 和 RV64 上都是 64-bit。系统 2025-03-24 OS #OS #riscv
基于 riscv32 的 OS 设计:外部设备中断(uart) RISC-V 中断(Interrupt)的分类一共有三种中断: 本地软件中断; 本地时钟中断; 外部中断; 中断的控制很复杂,具有多个级别的开关,以确保系统能够灵活、高效地处理各种中断: 1. 设备级别: 这是中断控制的最底层。每个外围设备(例如,UART、SPI、GPIO)都有自己的中断使能位。 通过设置这些位,可以控制设备是否能够产生中断请求。 如果设备级别的中断被禁用,即使设备产生了中 2025-03-23 OS #OS #riscv
基于 riscv32 的 OS 设计:Trap 和 Exception trap 和 exception 相关寄存器不管是 trap 还是 exception,大致处理流程都是一致的。 mcause当 trap 发生时,hart 会设置该寄存器通知我们 trap 发生的原因。最高位 Interrupt 为 1 时标识了当前 trap 为 interrupt,否则是 exception。剩余的 Exception Code 用于标识具体的 interrupt 或者 ex 2025-03-21 OS #OS #riscv
基于 riscv32 的 OS 设计:多任务 多任务首先创造两个任务: 12345678910111213141516171819void user_task0(void){ uart_puts("Task 0: Created!\n"); while (1) { uart_puts("Task 0: Running...\n"); task_delay(DELAY); tas 2025-03-20 OS #OS #riscv
基于 riscv32 的 OS 设计:切换上下文 ContextOS 中实际上并没有什么线程、进程,不过是一个个不同的上下文而已。 上下文非常重要,任务 A 和任务 B 的切换,核心就是保存 A 的上下文、恢复 B 的上下文。 在之前的 MIPS yieldOS 中,已经实现过上下文以及上下文的切换了,本质都是差不多的。 1234567891011121314151617181920212223242526272829303132333435/* 2025-03-19 OS #OS #riscv