当前位置: 首页 > article >正文

【AS32X601驱动系列教程】PLIC_中断应用详解

平台中断控制器(Platform Level Interrupt Controller,PLIC)是国科安芯AS32系列MCU芯片的中断控制器,主要对中断源进行采样,优先级仲裁和分发。各外设中断统一连到PLIC,PLIC统一管理并输出中断请求到内核。

硬件设计

本节硬件同USART章节一致。

软件设计

代码分析

在之前的按键章节我们已经对AS32的中断进行了简单实用,本节将用串口的接收中断实验进一步加深一下使用过程。

回顾之前的启动文件章节,有如下一段代码:

在RISCV指令集中,在机器模式下中断相关的寄存器有MSTATUS、MIE和MTVEC,其中前两个寄存器控制系统中断使能,具体内容颗翻看启动文件讲解,MTVEC用于保存中断入口地址,当中断发生时,程序指针会自动跳转到TrapEntry地址处开始执行,该段代码位于as32x601_trapentry.S文件中,用汇编文件编写,在这个函数下,我们会将RISCV内核所有相关寄存器,包括PC指针等全部进行保存,然后调用中断入口处理函数,完成后恢复现场寄存器值,从而实现中断功能。

中断处理函数位于as32x601_plic.c文件中,我们找到如下函数:

  1. /*
  2.  * Function:        PLIC_TrapHandler
  3.  * Description:     Interrupt handler type selection.
  4.  * Param:           Mcause: determine the type of exception or interrupt based on the value of the mcause register.
  5.  * Return:          None
  6.  */
  7. void PLIC_TrapHandler(uint32_t Mcause)
  8. {
  9.     /* Initializes the external interrupt structure */
  10.     PLIC_EXTITypeDef ExtInt = {{0}, 0};
  11.     if((Mcause & 0x80000000) != 0)
  12.     {
  13.         switch (Mcause & 0x0fff
  14.         {
  15.             case 3/* Machine software interrupt */
  16.                 MSoftWare_IRQ_Handler();
  17.                 break;
  18.             case 7/* Machine timer interrupt */
  19.                 MTimer_IRQ_Handler();
  20.                 break;
  21.             case 11/* Machine external interrupt */
  22.                 PLIC_SwitchMEXTI(&ExtInt);
  23.                 break;
  24.             default:
  25.                 break;
  26.         }
  27.     }
  28.     else
  29.     {
  30.         switch (Mcause & 0xfff
  31.         {   
  32.             case 0/* Instruction address misaligned */
  33.                 InstAddrMisalign_Handler();
  34.                 break;
  35.             case 1/* Instruction access fault */
  36.                 InstAccessFault_Handler();
  37.                 break;
  38.             case 2/* Illegal instruction */
  39.                 IllegalInst_Handler();
  40.                 break;
  41.             case 3/* Breakpoint */
  42.                 Breakpoint_Handler();
  43.                 break;
  44.             case 4/* Load address misaligned */
  45.                 LoadAddrMisalign_Handler();
  46.                 break;
  47.             case 5/* Load access fault */
  48.                 LoadAccessFault_Handler();
  49.                 break;
  50.             case 6/* Store/AMO address misaligned */
  51.                 StoreAMOAddrMisalign_Handler();
  52.                 break;
  53.             case 7/* Store/AMO access fault */
  54.                 StoreAMOAccessFault_Handler();
  55.                 break;
  56.             case 11/* Environment call from M-mode */
  57.                 ECall_Handler();
  58.                 break;
  59.             case 12/* Instruction page fault */
  60.                 InstPageFault_Handler();
  61.                 break;
  62.             case 13/* Load page fault */
  63.                 LoadPageFault_Handler();
  64.                 break;
  65.             case 15/* Store/AMO page fault */
  66.                 StoreAMOPageFalut_Handler();
  67.                 break;
  68.             default:
  69.                 break;
  70.         }
  71.     }
  72. }

在这个函数中,系统中断首先会读取MCAUSE寄存器的最高位,如果最高位为0,代表此事件为异常,RISCV定义了此类型,具体可直接查看MCAUSE寄存器定义;如果最高位为1,证明此事件为系统中断,此时可根据低位去选择处理的中断类型。

AS32除了系统定时中断和软件中断外,plic定义了64个plic中断,之前的的异常和中断均为向量类型,但进入plic中断后即为非向量模式,但可以软件支持嵌套,64个中断类型均已经在此文件中定义,所有定义均为弱函数,因此可以复制中断处理函数名写在自定义位置。接下来以串口中断为例介绍用法:

复制之前的usart工程,在print.c中修改初始化代码如下:

  1. /*
  2.  * Function:        User_Print_Init
  3.  * Description:     Configure Print USART.
  4.  * Param:           BaudRate: USART communication baud rate.                 
  5.  * Return:          None.
  6.  */
  7. void User_Print_Init(uint32_t BaudRate)
  8. {
  9.     USART_InitTypeDef USART_InitStructure;
  10.     GPIO_InitTypeDef  GPIO_InitStructure;
  11.     PLIC_InitTypeDef PLIC_InitStructure;
  12.     
  13.     GPIOD_CLK_ENABLE();
  14.     USART0_CLK_ENABLE();
  15.         
  16.     /* Set GPIO multiplex mapping */
  17.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART0);       /* USART0_TX */
  18.     GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART0);       /* USART0_RX */
  19.     /* GPIO Configure */
  20.     GPIO_InitStructure.GPIO_Pin       = GPIO_Pin_8;             
  21.     GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_OUT;
  22.     GPIO_InitStructure.GPIO_OType     = GPIO_Out_PP;
  23.     GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_4_5mA;
  24.     GPIO_Init(GPIOD, &GPIO_InitStructure);
  25.     GPIO_InitStructure.GPIO_Pin       = GPIO_Pin_9;             
  26.     GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_IN;
  27.     GPIO_InitStructure.GPIO_IType     = GPIO_IN_FLOATING;
  28.     GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_4_5mA;
  29.     GPIO_Init(GPIOD, &GPIO_InitStructure);
  30.     USART_DeInit(USART0);
  31.     USART_StructInit(&USART_InitStructure);
  32.     /* Initializes the USART0 */
  33.     USART_InitStructure.USART_BaudRate     = BaudRate;
  34.     USART_InitStructure.USART_WordLength   = USART_WordLength_8b;
  35.     USART_InitStructure.USART_StopBits     = USART_StopBits_1;
  36.     USART_InitStructure.USART_Parity       = USART_Parity_No;
  37.     USART_InitStructure.USART_Mode         = USART_Mode_Rx | USART_Mode_Tx;
  38.     USART_InitStructure.USART_OverSampling = USART_OverSampling_16;
  39.     USART_Init(USART0, &USART_InitStructure);
  40.     USART_Cmd(USART0, ENABLE);
  41.     
  42.     USART_ITConfig(USART0, USART_IT_RXNE, ENABLE);
  43.     
  44.      /* Configer the USART0 interrupt */
  45.     PLIC_InitStructure.PLIC_IRQChannel = USART0_IRQn;
  46.     PLIC_InitStructure.PLIC_IRQPriority = 1;
  47.     PLIC_InitStructure.PLIC_IRQChannelCmd = ENABLE;
  48.     PLIC_Init(&PLIC_InitStructure);
  49. }
  50. /*
  51.  * Function:        USART0_IRQ_Handler
  52.  * Description:     USART0 interrupt handler function.
  53.  * Param:           None.                 
  54.  * Return:          None.
  55.  */
  56. void USART0_IRQ_Handler()
  57. {
  58.     
  59.     if(USART_GetFlagStatus(USART0, USART_FLAG_RXNE) != RESET)
  60.     {
  61.         /* Clear the interrupt pending bits */
  62.         USART_SendData(USART0,USART_ReceiveData(USART0));
  63.     }
  64. }

在这个代码中,44行之前和串口章节完全一样,不再重复进行说明。第46行,调用串口的中断使能函数,使能串口接收中断,该处形参中的中断类型已经定义好,可以自行查询,之后需要开启PLIC的中断通道以及优先级配置,之后调用PLIC_Init函数进行初始化。

接下来,需要重写中断处理函数,该函数名已经在PLIC库文件中定义完成,直接复制过来即可,在这个函数中首先判断终端的来源,之后通过调用发送函数原路径发出,当然这只是一个实验,功能比较简单,实际使用过程中切忌这种用法。

最后主函数中对上述代码只需要做初始化即可,没有实际逻辑,因此在这不做展示。

​​​​​​​下板验证

将上述代码编译烧录完成,连接串口线与上位机,观察现象。

​​​​​​​

相关文章:

【AS32X601驱动系列教程】PLIC_中断应用详解

平台中断控制器(Platform Level Interrupt Controller,PLIC)是国科安芯AS32系列MCU芯片的中断控制器,主要对中断源进行采样,优先级仲裁和分发。各外设中断统一连到PLIC,PLIC统一管理并输出中断请求到内核。…...

单目视觉测量及双目视觉测量

一、单目视觉测量 1.1 原理部分讲解 单目视觉系统通过采集图像,将图像转换为二维数据,然后对采集的图像进行模式识别,通过图像匹配算法识别行驶过程中的车辆、行人、交通标志等,最后依据目标物体的运动模式和定位…...

python学习打卡day34

DAY 34 GPU训练及类的call方法 知识点回归: CPU性能的查看:看架构代际、核心数、线程数GPU性能的查看:看显存、看级别、看架构代际GPU训练的方法:数据和模型移动到GPU device上类的call方法:为什么定义前向传播时可以直…...

掩码与网关是什么?

1. 子网掩码(Subnet Mask) 作用:划分“小区”范围 想象你住在一个小区(子网)里: 小区门牌号 IP地址(如 192.168.1.10) 小区边界 子网掩码(如 255.255.255.0&#xf…...

leetcode-快慢指针系列

开胃小菜 141. 环形链表 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链…...

JAVA05基本数据类型和包装类的转换,转换成其他数据类型,包装类与字符串的转换+学生类的定义实例

1.基本数据类型和包装类的转换 下面是一个自动手动的例题 2.将包装类转换成其他类型 3. 将数据类型转换成字符串 将字符串转换成数据类型 以下是一个例题 学生类的例题...

Python打卡训练营学习记录Day34

知识点回归: CPU性能的查看:看架构代际、核心数、线程数 GPU性能的查看:看显存、看级别、看架构代际 GPU训练的方法:数据和模型移动到GPU device上 类的call方法:为什么定义前向传播时可以直接写作self.fc1(x) CPU性…...

动手学习深度学习V1.1 chapter2 (2.1-2.2)

chapter2:深度学习基础 区分问题:回归问题还是分类问题? 输出结果是不明确的连续值的时候就是回归问题,比如房价预测,销售额预测等。 输出结果是明确几个离散值的时候就是分类问题,比如字符识别&#xf…...

数据结构(6)线性表-队列

一、队列的概述 队列也是一种特殊的线性表,只允许在一段插入数据,另一端删除数据。插入操作的一端称为队尾,删除操作的一端称为队头。 如图: 二、队列相关操作 1.队列结构体的声明 类似于栈,他肯定也得借助于数组或…...

NumPy 2.x 完全指南【十七】转置操作

文章目录 1. 什么是转置2. 转置操作2.1 transpose2.2 ndarray.T2.3 moveaxis2.4 rollaxis2.5 permute_dims2.6 swapaxes2.7 matrix_transpose 1. 什么是转置 在线性代数中,矩阵转置是指将矩阵的行和列进行互换,即原矩阵的第 i i i 行、第 j j j 列元素…...

【数据架构04】数据湖架构篇

✅ 10张高质量数据治理架构图 无论你是数据架构师、治理专家,还是数字化转型负责人,这份资料库都能为你提供体系化参考,高效解决“架构设计难、流程不清、平台搭建慢”的痛点! 🌟限时推荐,速速收藏&#…...

使用OpenSSL生成根证书并自签署证书

生成根CA的私钥和证书 # 生成根 CA 的私钥 [rootdeveloper ssl]# openssl genrsa -out rootCA.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ... ............................................................ e is 65537 (0x010001)# 使用私钥生…...

uniapp-商城-62-后台 商品列表(分类展示商品的布局)

每一个商品都有类别,比如水果,蔬菜,肉,粮油等等,另外每一个商品都有自己的属性,这些都在前面的章节进行了大量篇幅的介绍。这里我们终于完成了商品类的添加,商品的添加,现在到了该进…...

初识C++:模版

本篇博客主要讲解C模版的相关内容。 目录 1.泛型编程 2.函数模板 2.1 函数模版概念 2.2 函数模版格式 2.3 函数模版的原理 2.4 函数模版的实例化 1.隐式实例化&#xff1a;让编译器根据实参推演模板参数的实际类型 2. 显式实例化&#xff1a;在函数名后的<>中指定模…...

【Elasticsearch】给所索引创建多个别名

Elasticsearch 是可以给索引创建多个别名的。 为什么可以创建多个别名 1. 灵活性 - 别名可以为索引提供一个更易于理解的名称&#xff0c;方便用户根据不同的业务场景或用途来引用同一个索引。例如&#xff0c;一个索引可能同时服务于多个不同的应用程序或服务&#xff0c;通…...

Linux入门(九)任务调度

设置任务调度文件 /etc/crontab #设置调度任务 crontab -e #将任务设置到调度文件 # * * * * * # 第1个* 分钟 0-59 # 第2个* 小时 0-23 # 第3个* 天 1-31 # 第4个* 月 1-12 # 第5个* 周 0-7 0和7都代表的是星期天 #每分钟执行 */1 * * * * ls -l /etc/ > /tmp/to.txt0 8,…...

突破认知边界:神经符号AI的未来与元认知挑战

目录 一、神经符号AI的核心领域与研究方法 &#xff08;一&#xff09;知识表示&#xff1a;构建智能世界的语言 &#xff08;二&#xff09;学习与推理&#xff1a;让机器“思考”与“学习” &#xff08;三&#xff09;可解释性与可信度&#xff1a;让AI更透明 &#xf…...

Java 处理地理信息数据[DEM TIF文件数据获取高程]

目录 1、导入依赖包 2、读取方法 3、其他相关地理信息相关内容&#xff1a; 1️⃣常用的坐标系 1、GIS 中的坐标系一般分为两大类&#xff1a; 2. ✅常见的地理坐标系 2.0 CGCS2000&#xff08;EPSG:4490&#xff09; 2.1 WGS84 (World Geodetic System 1984) &#xff08;EPSG…...

谈谈对dubbo的广播机制的理解

目录 1、介绍 1.1、广播调用 1、工作原理 1.2、调用方式 1、Reference 注解 2、XML 配置 3、全局配置 1.3、 广播机制的特性 2、重试机制 2.1、默认行为 2.2、自定义逻辑 1、在业务层封装重试逻辑 2、使用 Reference 3、广播调用的实践 3.1、常用参数 1.…...

对接钉钉消息样例:DING消息、机器人

一、钉钉开放平台配置信息 private static String robotCode private static String appkey private static String appsecret private static Long agentId 二、钉钉开放平台token、用户信息 public static Client createClient() throws Exception {Config config n…...

003-类和对象(二)

类和对象&#xff08;二&#xff09; 1. 类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff…...

使用Rancher在CentOS 环境上部署和管理多Kubernetes集群

引言 随着容器技术的迅猛发展&#xff0c;Kubernetes已成为容器编排领域的事实标准。然而&#xff0c;随着企业应用规模的扩大&#xff0c;多集群管理逐渐成为企业IT架构中的重要需求。 Rancher作为一个开源的企业级多集群Kubernetes管理平台&#xff0c;以其友好的用户界面和…...

Java常用数据结构底层实现原理及应用场景

一、线性结构 1. ArrayList 底层实现&#xff1a;动态数组&#xff08;Object[] elementData&#xff09;。 核心特性&#xff1a; 默认初始容量为 10&#xff0c;扩容时容量增长为原来的 1.5 倍&#xff08;int newCapacity oldCapacity (oldCapacity >> 1)&#xf…...

利用朴素贝叶斯对UCI 的 mushroom 数据集进行分类

朴素贝叶斯&#xff08;Naive Bayes&#xff09;是一种基于贝叶斯定理的简单而有效的分类算法&#xff0c;特别适合处理文本分类和多类别分类问题。UCI的Mushroom数据集是一个经典的分类数据集&#xff0c;包含蘑菇的特征和类别&#xff08;可食用或有毒&#xff09;。 1. 数据…...

Linux火墙管理及优化

网络环境配置 使用3个新的虚拟机【配置好软件仓库和网络的】 F1 192.168.150.133 NAT F2 192.168.150.134 192.168.10.20 NAT HOST-ONLY 网络适配仅主机 F3 192.168.10.30 HOST-ONLY 网络适配仅主机 1 ~]# hostnamectl hostname double1.timinglee.org 【更…...

Visual Studio 制作msi文件环境搭建

一、插件安装 a. 插件寻找 在 Visual Studio 2017 中&#xff0c;如果你希望安装用于创建 MSI 安装包的插件&#xff0c;第一步是&#xff1a;打开 Visual Studio 后&#xff0c;点击顶部菜单栏中的 “工具”&#xff08;Tools&#xff09;&#xff0c;然后选择下拉菜单中的 “…...

(Java基础笔记vlog)Java中常见的几种设计模式详解

前言&#xff1a; 在 Java 编程里&#xff0c;设计模式是被反复使用、多数人知晓、经过分类编目的代码设计经验总结。他能帮助开发者更高效地解决常见问题&#xff0c;提升代码的可维护性、可扩展性和复用性。下面介绍Java 中几种常见的设计模式。 单例模式&#xff08;Singlet…...

C++ vector 深度解析:从原理到实战的全方位指南

一、引言 在 C 编程中&#xff0c;我们经常需要处理一组数据。比如&#xff0c;你想存储一个班级所有学生的成绩&#xff0c;或者保存用户输入的一组数字。最容易想到的方法是使用数组&#xff1a; int scores[100]; // 定义一个能存储100个成绩的数组但数组有两个明显的缺点…...

鸿蒙进阶——Framework之Want 隐式匹配机制概述

文章大纲 引言一、Want概述二、Want的类型1、显式Want2、隐式Want3、隐式Want的匹配 三、隐式启动Want 源码概述1、有且仅有一个Ability匹配2、有多个Ability 匹配需要弹出选择对话框3、ImplicitStartProcessor::ImplicitStartAbility3.1、GenerateAbilityRequestByAction3.1.1…...

antv/g6 图谱封装配置(二)

继上次实现图谱后&#xff0c;后续发现如果要继续加入不同样式的图谱实现起来太过麻烦&#xff0c;因此考虑将配置项全部提取封装到js文件中&#xff0c;图谱组件只专注于实现各种不同的组件&#xff0c;其中主要封装的点就是各个节点的横坐标&#xff08;x&#xff09;,纵坐标…...