riscv-5-设备树
1.设备树介绍
参考:
Linux——设备树_linux 设备树-CSDN博客
设备树详解 | TimerのBlog (yanglianoo.github.io)
设备树:是一种描述硬件的数据结构,提供一种语言将硬件配置从Linux内核源码中提取出来,使得目标板和设备变成数据驱动的,它们必须基于传递给内核的数据进行初始化。
设备树文件 使用一种”Device Tree Source”(DTS)的语言编写,文件描述了硬件设备的层次结构,寄存器地址,中断线路,DMA通道和其他的相关属性。
设备树文件 经过DTC编译后会生成一种称为”Device Tree Blob”(DTB)的二进制格式。DTB文件在引导过程中由引导加载程序(Bootloader)提供给内核。内核会解析DTB文件,根据其中的描述信息初始化硬件设备,并加载相应的驱动程序。
名词解释:
DTSdevice tree source ,.dts文件,是一种ASCII 文本格式的文件,一般一个文件对应一个硬件平台
DTC:device tree complier 编译设备树源码的编译工具,一般情况下需要手动安装这个编译工具 ...
riscv-4-opensbi
1.riscv的多级启动引导流程介绍之前的步骤都是板子的一些外设添加以及,上一节写了个简单的固件程序,目前已经实现了板子的cpu,MROM,SRAM,FLASH,DDR,UART和RTC
参考:
RISC-V体系结构的U-Boot引导过程_riscv uboot-CSDN博客
RISC-V启动引导流程 spec - 方东信 - 博客园 (cnblogs.com)
notes/多核启动基本逻辑 at master · wangzhou/notes (github.com)
三种主要的操作模式,riscv 规范定义了三种主要的操作模式
U模式(用户模式),运行用户程序的模式,权限级别最低。不能直接访问I/O或特权指令或内核内存或其他进程。
S模式(管理模式),大多数Linux内核或其他O/S运行的模式。通过I/O remap函数访问最特权的指令和I/O控制。内存管理单元可能打开或关闭。
M模式(机器模式),机器模式:裸机程序/第一阶段引导加载程序和FSBL(First Stage Bootloader ...
git-操作基础
1.git因为 riscv项目在分别在两台电脑上操作完成,特此记录一下使用操作
在另一台电脑上(wsl2 Ubuntu20.04)
配置ssh key
123456789ssh-keygen -t rsa -b 4096 -C "your_email@example.com"#添加到ssh代理eval "$(ssh-agent -s)"ssh-add ~/.ssh/id_rsa#复制密匙 并添加到githubcat ~/.ssh/id_rsa.pub
在wsl2 将项目与 git仓库关联
123git remote add github git@github.com:liangzhouzz/riscv_project.git#然后就是 git add git commit等
合并分支
12345678910111213141516#切换到maingit checkout main#拉取最新更改git pull origin main#合并新分支git merge new-branch-name#如果有冲突 提示处理冲突文件 ...
riscv-3-测试串口打印
1.start.s 位于flash的第一段代码maskrom中 的代码会引导程序到pflash的零地址 即 0x20000000,所以程序从这个地址开始。
读取hard id
如果为0 就跳转_core0 执行打印
_core0 函数 往flash 0x20000000 一个一个写字母
start.c
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 .section .text //定义数据段名为.text .globl _start //定义全局符号_start .type _start,@function //_start为函数_start: //函数入口 csrr a0, mhartid //csr是riscv专有的内核私有寄存器,独立 ...
riscv-2-flash-itr-gpio
1.添加flash
这里加的是pflash意为并行flash。
include/quard_star.h
12345678910111213141516struct QuardStarState { /*< private >*/ MachineState parent; /*< public >*/ RISCVHartArrayState soc[QUARD_STAR_SOCKETS_MAX]; PFlashCFI01 *flash; // FLASH};enum { QUARD_STAR_MROM, QUARD_STAR_SRAM, QUARD_STAR_UART0, QUARD_STAR_FLASH, // FLASH QUARD_STAR_DRAM,};
quard_star.c
定义flash的起始地址和大小 32M
1234567static const MemMapEntry quard_star_memmap[] ...
x86_thread
12.内核线程的创建与切换此处的内核线程作为运行在内核态的一个逻辑执行流,用于私有的栈空间,但是除了私有的栈空间外,不拥有其他资源
所以的内核线程拥有相同的页表,共享所有的全局数据
一般OS 都不会完全采用硬件切换机制,但本简单的内核,只是涉及到内核态,不涉及特权级的转移过程,所以完全可以用硬件实现
任务的切换必然涉及到现场的保护与恢复,所以就必然需要一个数据结构来保存这 些现场信息。这个数据结构中一般也会放置任务相关的一些信息并且以链表之类的方式 组织起来,这个结构被称之为PCB(Process Control Block)或者TCB(Task Control Block)
include/task.h 函数
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354#ifndef INCLUDE_TASK_H_#define INCLUDE_TASK_H_#include "types.h"#include ...
x86-7-heap
11.内核堆管理的实现目前已经实现了页管理,但是在需要分配小内存的时候,比较容易造成内部碎片, — 实现内核的堆管理算法
内部碎片指的是:内存中各种对齐规则的限制,导致分配的内存 大于 进程所需要的内存,因此会造成内部碎片
需要实现的功能:
分配内存
在内存释放的时候对连续的内存进行合并
在空闲内存过多的时候,将物理页释放给物理内存管理模块
关于堆的实现,选择最简单的侵入式链表管理方法
Linux: C语言实现范型数据结构 - 嵌入(侵入)式链表浅谈 - 知乎 (zhihu.com)
侵入式链表(Intrusive Linked List)是一种链表实现方式,其中链表节点的链接信息嵌入在节点数据结构本身中。
减少了内存的开销
include/heap.c
1234567891011121314151617181920212223242526272829303132#ifndef INCLUDE_HEAP_H_#define INCLUDE_HEAR_H_#include "types.h"// 堆起始地址,它是内核页表没有使用的空闲区域。#de ...
x86-6-虚拟内存管理的实现
10.虚拟内存管理的实现1.段页式内存管理
虚拟地址到物理地址通过由页目录和页表组成的二级页表映射,页目录的地址放置在CR3寄存器里。
段页式内存管理:
该过程需要三次访问内存,为提高执行速度,可以增加一个快表,访问数据时利用段号和页号检索它,若可以命中,直接取出物理帧号;否则,进行上述三次内存访问过程获得数据。
将进程按照逻辑模块分段,然后再将各段分页
段页式管理外部采用段的优点,即用户可根据逻辑功能进行分段,内部采用页的优点,进行系统的固定分页,取消了段的长度不等造成的开销,由固定大小的页代替,提高内存利用率
段页式内存管理的优点:段式使得内存分配更灵活,页式使得内存碎片减少,段页式内存管理可以方便地重用内存页,提高内存利用效率。
灵活的内存分配:
段页式内存管理允许将内存分成逻辑段,每个段可以独立地增长和缩减。这种灵活性使得程序可以按需分配内存,从而提高内存利用率。
内存保护:
每个段都有独立的段描述符,描述符中包含了段的基址、大小和访问权限。这种机制可以防止进程之间的内存越界访问,提高系统的稳定性和安全性。
简化的地址空间:
段页式内存管理将逻辑地址转换为 ...
x86-5-物理内存管理的实现
9.物理内存管理的实现9.1分页式的内存管理
线性地址是连续的,但是其实际指向的 物理地址就不见得是连续的了
虚拟 内存实质上就是把物理内存中暂时用不到的内容暂时换出到外存里,空出内存放置现阶段 需要的数据。至于替换的策略当然有相应的算法了,比如最先换入原则,最少使用原则等 等方法可以使用
分级页表:以32位的地址来说,分为3段来寻址,分别是地址的低12位,中间10位和高10位。
高 10位表示当前地址项在页目录中的偏移,最终偏移处指向对应的页表,
中间10位是当前地 址在该页表中的偏移,我们按照这个偏移就能查出来最终指向的物理页了,
最低的12位表 示当前地址在该物理页中的偏移
本章主要解决一下三个问题:
如何获取可用物理内存的大小和地址?
采用什么样的数据结构来描述物理内存?
申请和释放物理内存的算法如何实现?
问题一:如何获取可用物理内存的大小和地址?在GRUB中已经获取物理内存的分布,并且将它们放置下面的成员里
include/multiboot.h
1234567891011121314151617181920212223242526272 ...
x86-4-中断描述符
7.添加中断描述符表中断执行的流程:
当某个中断发生时,典型的处理方式就是CPU会 打断当前的任务,保留当前的执行现场
再转移到该中断事先安排好的中断处理函数去执行。
在中断处理函数执行结束之后再恢复中断之前的执行现场,去执行之前的任务。
中断描述符表(IDT,interrupt descriptor table) 与gdt 类似的 也有一个中断描述符表寄存器 记录这个表的起始地址
include/idt.h 定义
123456789101112131415161718192021222324252627#ifndef INCLUDE_IDT_H_#define INCLUDE_IDT_H_#include "types.h"// initvoid init_idt();// 中断typedefstruct idt_entry_t { uint16_t base_lo; // 中断处理函数地址的 15 - 0 位 uint16_t sel; // 目标代码段描述符选择子 uint8_t al ...