制作一个RISC-V的操作系统十一-外部设备中断

news2024/11/16 16:38:43

文章目录

  • 中断分类
  • mie mip
  • 中断处理流程
  • 外部中断
  • 中断源
  • PLIC
  • Priority
  • Pending
  • Enable
  • Threshold
  • Claim/Complete
  • PLIC工作流程
  • 设置uart寄存器IER
  • 设置uart寄存器LSR
  • asm volatile("mv %0, tp" : "=r" (x) );
  • 头文件不能定义函数,不然每次导入都会定义一次
  • static line
  • 代码
    • 初始化plic
    • 中断处理
  • 代码
  • 待解决

中断分类

本地中断:软中断(0-3)和定时器中断(4-7)
全局中断:外部中断(8-10)

三类中断对应到CPU有三个引脚
在这里插入图片描述

mie mip

mstatus中的那个中断寄存器是全局,mie这个中断寄存器是二级的,相当于做个细化

mie:开启哪个模式下某个类型的中断
mip:标准当前哪个模式下的某个类型的中断是否在发生
在这里插入图片描述

中断处理流程

与异常处理流程类似,区别是设置mepc保存的是当前pc下一条指令的地址。因为中断认为是执行完当前指令后再去指向中断,所以中断处理完后应该回到之前指令的下一条指令

外部中断

外设产生中断给CPU,CPU响应,处理中断
对于每个CPU只有一个对应外部中断的引脚,但外设很多个
在这里插入图片描述
通过PLIC中断控制器管理,即产生外设产生中断源后,PLIC处理然后给某个CPU处理
在这里插入图片描述

中断源

0没有固定对应的中断源,预留
在这里插入图片描述

PLIC

PLIC也是一个外设,CPU访问其PLIC也是通过将PLIC映射到内存上进而实现访问内存即访问到PLIC寄存器的方式
在这里插入图片描述

Priority

每个中断源根据其中断源ID来对应到其Priority寄存器,每个寄存器内的值从0到7,0代表该中断源的优先级最低
在这里插入图片描述

Pending

PLIC可读可写,标注某个中断源是否发生,每个PLIC有两个是因为64位才能表示够所有的中断源
在这里插入图片描述

Enable

对应hart的,也是两个,也是因为64位才能表示够所有的中断源
在这里插入图片描述

Threshold

在这里插入图片描述

Claim/Complete

在这里插入图片描述

PLIC工作流程

1和2中断源分别优先级为1,2. hart0的所有设备对应的Enable打开而hart1关闭。hart0的threshold设置为零

  1. 当1和2中断源同时发生时,首先中断源的中断优先级互相比较,高优先级先进入
  2. 此时hart0的Enable允许进入,hart1不允许
  3. 然后hart0的threshold为零,允许进入
  4. pending对应的中断源位置为1,此时再传给CPU,CPU就知道某个中断发生了
  5. 然后Claim可以得知此时中断源的ID号,并把padding位关掉,然后走中断处理程序
  6. 然后再complete,通知PLIC当前中断处理完了,然后处理1号中断源,然后过程同上
    在这里插入图片描述

设置uart寄存器IER

在这里插入图片描述

设置uart寄存器LSR

在这里插入图片描述

asm volatile(“mv %0, tp” : “=r” (x) );

这段代码是一个RISC-V架构上的内联汇编语句,用于C或C++编程环境。它具有以下含义:

asm volatile("mv %0, tp" : "=r" (x) );
  1. asm volatile: 这表明这是一个内联汇编指令,且标记为volatile。这意味着编译器不会对此段代码进行优化,每次都会按照字面意义执行,且执行的结果可能会影响到程序的状态。

  2. "mv %0, tp": 这是RISC-V架构的汇编指令。mv是move(移动)指令,用于将一个值从源寄存器复制到目标寄存器。在这里,tp表示线程指针寄存器,而%0是一个占位符,代表将在输出约束中指定的C/C++变量。

  3. : "=r" (x): 这是一个输出约束,描述了汇编指令如何与C/C++变量交互。=r意味着需要一个寄存器作为输出,并且将该寄存器的值赋给变量x

头文件不能定义函数,不然每次导入都会定义一次

/usr/lib/riscv64-unknown-elf/bin/ld: plic.o: in function read_mie': /home/llk/Desktop/risllkos/github/Fullkenerl6/trap.h:14: multiple definition of read_mie'; Trap.o:/home/llk/Desktop/risllkos/github/Fullkenerl6/trap.h:14: first defined here /usr/lib/riscv64-unknown-elf/bin/ld: plic.o: in function write_mie': /home/llk/Desktop/risllkos/github/Fullkenerl6/trap.h:19: multiple definition of write_mie'; Trap.o:/home/llk/Desktop/risllkos/github/Fullkenerl6/trap.h:19: first defined here 

这个链接错误提示说明项目中有两个对象文件(plic.oTrap.o)都在尝试定义相同的函数 read_miewrite_mie,并且这些函数定义位于头文件 /home/llk/Desktop/risllkos/github/Fullkenerl6/trap.h 的第14行和第19行。

在C/C++中,函数不应该在头文件中直接定义,而应该只声明函数原型。否则,当包含这个头文件的源文件被编译后,就会导致每个源文件都生成一次该函数的定义,进而引发链接阶段的重复定义错误。

解决方法如下:

  1. read_miewrite_mie 函数的定义移到一个单独的源文件(如 trap.ctrap.s,取决于它们是C函数还是汇编函数)中。

  2. 在头文件 trap.h 中只保留函数的声明(prototype):

#ifndef _TRAP_H_
#define _TRAP_H_

// 声明函数,而不是定义
extern uint32_t read_mie(void);
extern void write_mie(uint32_t value);

#endif // _TRAP_H_
  1. 确保在项目中只在一个源文件中定义这两个函数的实际实现,然后正常编译和链接该项目的所有源文件。

  2. 如果这些函数是非常底层的汇编函数,且你确实希望在头文件中放置定义,那么你需要确保使用 static inline 关键字来声明它们,以避免链接时的多重定义错误。但请注意,这种方法适用于非常小且适合内联展开的函数。对于较大的函数或涉及特殊寄存器访问的函数,通常不建议这样做。

static line

在C或C++中,当你在一个头文件中定义了一个常规(非inline)函数并且在多个源文件(.c或.cpp)中包含了这个头文件,编译器会在每个包含此头文件的源文件中生成这个函数的机器码。当链接器试图将所有目标文件链接成一个可执行文件时,会发现同一函数在多个地方都有定义,从而引发多重定义的链接错误。

然而,对于static inline函数,情况有所不同:

  1. Staticstatic关键字在这里用于限定函数的作用域。对于函数来说,这意味着函数是“内部链接”的,也就是它只在包含它的编译单元(通常是包含该函数定义的源文件)内部可见。尽管此处函数定义在头文件中,但由于它是static的,每个包含此头文件的源文件都会得到该函数的一个独立副本,这些副本彼此之间互不影响,都在各自的作用域内有效。

  2. Inlineinline关键字是用来请求编译器尝试将函数体直接嵌入到每个调用该函数的地方,就像宏那样,而不是生成一个单独的函数调用。这样一来,理论上就不需要在链接时处理此函数的外部引用。

结合两者,static inline函数既限定了作用域(每个源文件视为一个独立的作用域),又要求编译器尽可能内联展开,即便编译器出于某种原因无法内联展开,由于static的作用,各个源文件中生成的函数副本依然是独立的,并且只在其所在的编译单元内有效,所以在链接阶段就不会发生多重定义错误。

例如:

// trap.h
#ifndef TRAP_H
#define TRAP_H

static inline void handle_trap() {
    // 函数体...
}

#endif // TRAP_H

// file1.c
#include "trap.h"
void some_function() {
    handle_trap(); // 调用
}

// file2.c
#include "trap.h"
void another_function() {
    handle_trap(); // 另一处调用
}

在这个例子中,尽管handle_trap()函数在file1.cfile2.c中都包含了其定义,但由于它是static inline的,每个源文件都有一个独立的内联版本(理想情况下编译器会内联展开,如果不是则在各自的编译单元内有独立的非内联副本),最终链接时不会出现多重定义的问题。

代码

外设通过uart借口连接到PLIC,PLIC连接到CPU上。当外设输入一个字符时会产生中断,此时会通过PLIC通知CPU进而处理中断。
而输出是直接CPU和uart连接,CPU将字符传给uart,uart再传给外设,显示屏自然就看到了

初始化plic

在这里插入图片描述

中断处理

根据发送的中断进入uart对应中断程序
在这里插入图片描述

代码

https://github.com/FULLK/risllkos/tree/main/Fullkenerl6

待解决

在这里插入图片描述

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

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

相关文章

C++修炼之路之list--C++中的双向循环链表

目录 前言 一:正式之前先回顾数据结构中的双向循环链表 二:list的简介 三:STL中list常用接口函数的介绍及使用 1.构造函数接口 2.list迭代器 范围for 3.数据的修改接口函数 4.list容量操作函数 5.list的迭代器失效 6.演示代码和测…

RAG学习笔记系列(一)

RAG 介绍 RAG 全称为 Retrieval Augmented Generation(检索增强生成)。是基于LLM构建系统的一种架构。 RAG 基本上可以理解为:搜索 LLM prompting。根据用户的查询语句,系统会先使用搜索算法获取到相关内容作为上下文&#xff0…

最大公约数和最小公倍数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现最大公约数函数&#xff1b; int max(int x, int y) {//初始化变量值&#xff1b;int judge 1;//运算&#xff1b;judge x %…

ospf综合路由实验

1配置ip 2配置私网通&#xff08;配置双向验证&#xff09; 3配置静态缺省,公网通&#xff08;nat配置后因为没有缺省所以通不了&#xff0c;要么配置缺省要么配置特殊区域自动下发缺省&#xff09;配置mgre 4链路聚合&#xff0c;配置特殊区域&#xff0c;更改hello更新时间 …

工作必备!快速了解多微信高效管理工具

在如今社交媒体和移动即时通信的时代&#xff0c;微信已成为人们工作和生活中不可或缺的一部分。而对于那些需要同时管理多个微信账号的用户来说&#xff0c;微信管理工具则是一项绝对必备的利器。 1、多微信同时登录 通过微信管理系统&#xff0c;我们可以在同一个界面内同时…

财商的思考

【200万粉福利特供|| 高考后的“分层之战”和“人生破圈算法”-哔哩哔哩】 https://b23.tv/5ASl8WA 社会三层 &#xff08;1&#xff09;上层 &#xff08;2&#xff09;中层 &#xff08;3&#xff09;基层&#xff1a; 上层 定义&#xff1a;高护城河生产资料和权利的所有…

视频拍摄知识+AIGC数据预处理

视角 参考链接&#xff1a;https://www.polarpro.com/blogs/polarpro/filmmaking-101-types-of-camera-shots-and-angles Low Angle Shot 低角度拍摄、horizontal Shot 平视、Dutch Angle Shot 荷兰角斜拍、High Angle Shot 高角度拍摄、Bird’s-eye / Aerial Shot 鸟瞰 / 航…

【工位ubuntu的配置】补充

软件 安装桌面图标的问题 登录密码 root的密码为&#xff1a;19980719 按照如下的链接进行配置&#xff1a; https://blog.csdn.net/zhangmingfie/article/details/131102331?spm1001.2101.3001.6650.3&utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7E…

【MATLAB源码-第28期】基于matlab的16QAM定时同步仿真,采用gardner算法,Costa锁相环。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 正交幅度调制&#xff08;QAM&#xff0c;Quadrature Amplitude Modulation&#xff09;是一种在两个正交载波上进行幅度调制的调制方式。这两个载波通常是相位差为90度&#xff08;π/2&#xff09;的正弦波&#xff0c;因此…

手势估计 | 使用TensorRT实现的实时手势估计+手势分类

项目应用场景 面向手势识别场景&#xff0c;项目具有实时手势识别 手势分类功能&#xff0c;采用 TensorRT 进行 GPU 加速推理&#xff0c;可通过手势识别进行远程控制。 项目效果 项目细节 > 具体参见项目 README.md (1) 安装依赖 git clone https://github.com/NVIDIA-…

VN6501使用方法(学习笔记)

1:总体简介 VNA6501可以进行CAN Stress测试&#xff0c;可以进行采样点测试。此外VN6501还能够定制&#xff0c;外围测试电路&#xff08;通过软件配置&#xff0c;部分情况是需要连接VN6501的部分接口&#xff09;。 关于外围测试电路&#xff08;添加电容&#xff0c;电阻&…

iOS ------ Block的总结

前面看了Block的基本知识&#xff0c;和一些源码。但对于block怎么用的还不了解&#xff0c;代码中出现block会看不懂&#xff0c;现在来具体看一下Block的用法并做个总结。 1.Block是什么 block对象是一个C语言结构体&#xff0c;可以并入C和OC的代码中&#xff0c;Block本质…

C语言基础知识巩固——1.基本知识

语言是面向过程的&#xff0c;体现为其通过函数及其调用关系来描述程序逻辑 将大问题拆解为一套流程&#xff0c;执行这套流程中的各个步骤即可&#xff1a; 每一个步骤有明确的入口和出口每一个步骤可以继续拆解为一套更细化的流程最后得到描述问题解决方案的完整逻辑 函数…

指针专题(1)

前言 指针在C语言中占据着重要的位置&#xff0c;对指针的掌握度会直接影响到编写C语言代码的能力&#xff0c;而且指针的难度较大&#xff0c;所以我们要认真的学习指针。那么废话不多说&#xff0c;我们正式进入今天的指针学习 &#xff08;PS&#xff1a;之前有关指针、结构…

前端开发攻略---Vue项目(Vue2和Vue3)引入高德地图,超详细,超简单,保姆级教程。

1、图片演示 2、引入前的准备 1、前往 高德开放平台 进行账号注册。如果手机上有高德地图App并且已经登录过&#xff0c;则可以直接选择登录 2、注册/登录完成后来到应用管理-->我的应用 3、点击创建新应用 4、填写好应用名称和选择应用类型 5、填写好后点击添加Key 6、填写…

2024.4.18

思维导图 数据库 #include <myhead.h> //添加学生信息 void insert_stu(sqlite3* sq,char* errMsg) {char text[128];int ID,age,height;char name[10];scanf("%d%s%d%d",&ID,name,&age,&height);sprintf(text,"insert into Student values …

网络运输层之(3)GRE协议

网络运输层之(3)GRE协议 Author: Once Day Date: 2024年4月8日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的…

html之标签学习(带你进来,别犹豫,是你喜欢的样子)

html之标签学习 学习 HTML 标签是创建网页的第一步&#xff0c;HTML&#xff08;Hypertext Markup Language&#xff09;是一种用于创建网页的标记语言&#xff0c;它由一系列的元素&#xff08;标签&#xff09;组成&#xff0c;每个元素都可以用来标记文档的不同部分或者给文…

仿真测试平台设计资料:921-6U CPCI卫星接口仿真测试平台

6U CPCI卫星接口仿真测试平台 一、设备概述 卫星接口仿真测试平台基于6U CPCI的结构&#xff0c;包含信号接口前板、后板&#xff0c;计算机主板、机箱、电源等硬件。硬件设计包括&#xff1a;信号接口前板、后板&#xff08;直接遥测遥控、串行RS422、LVDS&#xff0c;模拟量输…

Http 请求偶发400错误

1. 背景 生产环境偶发400请求错误&#xff0c;发生概率万分之一&#xff0c;异常信息如下&#xff1a; 1&#xff09; 从异常信息可以看到&#xff0c;skywalking的sw8 header解析失效导致异常信息。 2&#xff09; 0x0d0x0a 作为回车换行符号&#xff0c;没有被正确处理&#…