【S5PV210】 | 按键和CPU的中断系统

S5PV210 | 按键和CPU的中断系统


时间:2024年3月17日14:04:27

目录

[TOC]

1.参考

1.项目管理

2.x210bv3s: ARM Cortex-A8 (s5pv210)的开发与学习 硬件版本:(九鼎)X210BV3S 20160513

3.知识星球 | 深度连接铁杆粉丝,运营高品质社群,知识变现的工具

4.按键—朱老师物联网大课堂_四引脚按键 可以分成2对吗-CSDN博客

5.项目目录预览 - mark-down-s5pv210 - GitCode

6.x210bv3s电路原理图

7.【S5PV210】 | 按键和CPU的中断系统-CSDN博客

2.原理

在这里插入图片描述


在这里插入图片描述

对应GPIO口默认硬件上拉,有按键按下时对应的IO口变为低电平。

我们可以将对应GPIO口设置为输入,检测对应的电平即可。

3.DataSheet查询

在这里插入图片描述

1向量中断控制器

1.1向量中断控制器概述

S5PV210中的中断控制器由四个向量中断控制器(VIC),ARM PrimeCell组成PL192和四个TrustZone中断控制器(TZIC)SP890。
菊花链式连接了四个TZIC和四个VIC,以支持多达93个中断源。 TZIC提供软件TrustZone设计中与安全中断系统的接口。 它提供对nFIQ中断和在系统(VIC)非安全侧屏蔽来自中断控制器的中断源。 使用后者产生nIRQ信号。
为了从非安全中断源生成nFIQ,TZIC0从非安全中断控制器获取nNSFIQIN信号。

1.1.1向量中断控制器的主要功能

•支持93个向量IRQ中断
•固定硬件中断优先级
•可编程中断优先级
•支持硬件中断优先级屏蔽
•可编程中断优先级屏蔽
•生成IRQFIQ
•产生软件中断
•测试寄存器
•原始中断状态
•中断请求状态
•支持特权模式以限制访问

1.2中断源

S5PV210支持中断源,如下表所示

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

1.3功能说明

当用户清除待处理的中断时,用户必须将0写入所有VICADDRESS寄存器(VIC0ADDRESS
VIC1ADDRESSVIC2ADDRESSVIC3ADDRESS

1.4寄存器描述

详见数据手册

4.代码编写

裸机代码:07-key_int · x210bv3s/v210_NoOs - 码云 - 开源中国 (gitee.com)

int.c

/********************************************************************   > File Name: int.c*   > Author: fly*   > Mail: lf.ye@samoon.net*   > Create Time: 2020年08月07日 星期五 14时01分36秒*================================================================*/
#include "int.h"
#include "stdio.h"void reset_exception(void)
{printf("reset_exception.\n\r");
}void undef_exception(void)
{printf("undef_exception.\n\r");
}void soft_int_exception(void)
{printf("soft_int_exception.\n\r");
}void prefetch_exception(void)
{printf("prefetch_exception.\n\r");
}void data_exception(void)
{printf("data_exception.\n\r");
}// 主要功能:绑定第一异常向量表;禁止所有中断;选择所有中断类型为IRQ;
// 清除VICnADDR为0
void system_init_exception(void)
{// 第一阶段处理,绑定异常向量表r_exception_reset = (unsigned int)reset_exception;r_exception_undef = (unsigned int)undef_exception;r_exception_soft_int = (unsigned int)soft_int_exception;r_exception_prefetch = (unsigned int)prefetch_exception;r_exception_data = (unsigned int)data_exception;r_exception_irq = (unsigned int)IRQ_handle;r_exception_fiq = (unsigned int)IRQ_handle;// 初始化中断控制器的基本寄存器intc_init(); 
}// 清除需要处理的中断的中断处理函数的地址
void intc_clearvectaddr(void)
{// VICxADDR:当前正在处理的中断处理函数的地址VIC0ADDR = 0;VIC1ADDR = 0;VIC2ADDR = 0;VIC3ADDR = 0;
}// 初始化中断控制器
void intc_init(void)
{// 禁止所有中断// 为什么在中断初始化之初要禁止所有中断?// 因为中断一旦打开,因为外部或者硬件自己的原因产生中断后一定会寻找isr(interrupt service routines:中断服务程序)// 而我们可能认为自己用不到这个中断就没有提供isr,这是它自动拿到的就是乱码// 则程序很可能跑飞,所以不用的中断一定要关掉。// 一般的做法是先全部关掉,然后再逐一打开自己感兴趣的中断。一旦打开// 就必须给这个中断提供相应的isr并绑定好。VIC0INTENCLEAR = 0xffffffff;VIC1INTENCLEAR = 0xffffffff;VIC2INTENCLEAR = 0xffffffff;VIC3INTENCLEAR = 0xffffffff;// 选择中断类型为IRQVIC0INTSELECT = 0x0;VIC1INTSELECT = 0x0;VIC2INTSELECT = 0x0;VIC3INTSELECT = 0x0;// 清VICxADDRintc_clearvectaddr();
}// 绑定我们写的isr到VICnVECTADDR寄存器
// 绑定过之后我们就把isr的地址交给硬件了,剩下的我们不用管,硬件会自己处理
// 等发生相应中断的时候,我们直接到相应的VICnADDR中去取isr地址即可。
// 参数:intnum是int.h定义的物理中断号,handler是函数指针,就是我们写的isr// VIC0VECTADDR定义为VIC0VECTADDR0寄存器的地址,就相当于是VIC0VECTADDR0~31这个
// 数组(这个数组就是一个函数指针数组)的首地址,然后具体计算每一个中断的时候
// 只需要首地址+偏移量即可。
void intc_setvectaddr(unsigned long intnum, void (*handler)(void))
{// VIC0if(intnum < 32){*((volatile unsigned long *)(VIC0VECTADDR + 4 *(intnum - 0))) = (unsigned)handler;}// VIC1else if(intnum < 64){*((volatile unsigned long *)(VIC1VECTADDR + 4 *(intnum - 32))) = (unsigned)handler;}// VIC2else if(intnum < 96){*((volatile unsigned long *)(VIC2VECTADDR + 4 *(intnum - 64))) = (unsigned)handler;}// VIC3else{*((volatile unsigned long *)(VIC3VECTADDR + 4 *(intnum - 96))) = (unsigned)handler;}return;
}// 使能中断
// 通过传参的intnum来使能某一个具体的中断源,中断号在int.h中定义,是物理中断号
void intc_enable(unsigned long intnum)
{unsigned long temp;// 确定intnum在哪个寄存器的哪一位// <32就是0~31,必然在VIC0if(intnum < 32){temp = VIC0INTENABLE;temp |= (1<<intnum);    // 如果是第一种设计必须位操作,第二种设计可以直接写。VIC0INTENABLE  = temp;}else if(intnum < 64){temp = VIC1INTENABLE;temp |= (1 << (intnum - 32));VIC1INTENABLE = temp;}else if(intnum < 96){temp = VIC2INTENABLE;temp |= (1 << (intnum - 64));VIC2INTENABLE = temp;}else if(intnum < NUM_ALL){temp = VIC3INTENABLE;temp |= (1 << (intnum - 96));VIC3INTENABLE = temp;}// NUM_ALL : enable all interruptelse{VIC0INTENABLE = 0xffffffff;VIC1INTENABLE = 0xffffffff;VIC2INTENABLE = 0xffffffff;VIC3INTENABLE = 0xffffffff;}
}// 禁止中断
// 通过传参的intnum来禁止某一个具体的中断源,中断号在int.h中定义,是物理中断号
void intc_disable(unsigned long intnum)
{unsigned long temp;if(intnum < 32){temp = VIC0INTENCLEAR;temp |= (1<<intnum);VIC0INTENCLEAR = temp;}else if(intnum < 64){temp = VIC1INTENCLEAR;temp |= (1<<(intnum - 32));VIC1INTENCLEAR = temp;}else if(intnum < 96){temp = VIC2INTENCLEAR;temp |= (1<<(intnum - 64));VIC2INTENCLEAR = temp;}else if(intnum < NUM_ALL){temp = VIC3INTENCLEAR;temp |= (1<<(intnum - 96));VIC3INTENCLEAR = temp;}// NUM_ALL : disable all interruptelse{VIC0INTENCLEAR = 0xffffffff;VIC1INTENCLEAR = 0xffffffff;VIC2INTENCLEAR = 0xffffffff;VIC3INTENCLEAR = 0xffffffff;}return;
}// 通过读取VICnIRQSTATUS寄存器,判断其中哪个有一位为1,来得知哪个VIC发生中断了
unsigned long intc_getvicirqstatus(unsigned long ucontroller)
{if(ucontroller == 0)return VIC0IRQSTATUS;else if(ucontroller == 1)return VIC1IRQSTATUS;else if(ucontroller == 2)return VIC2IRQSTATUS;else if(ucontroller == 3)return VIC3IRQSTATUS;else{}return 0;
}// 真正的中断处理程序。意思就是说这里只考虑中断处理,不考虑保护/恢复现场
void irq_handler(void)
{printf("irq_handler.\n\r");// SoC支持很多个(在低端CPU例如2440中有30多个,在210中有100多个)中断// 这么多中断irq在第一个阶段走的是一条路,都会进入到irq_handle来// 我们在irq_handler中要去区分究竟是哪个中断发生了,然后再去调用该中断// 对应的isr。// 虽然硬件已经自动帮我们把isr放入了VICnADDR中,但是因为有4个,所以我们// 必须先软件去检查出来到底是哪一个VIC中断,也就是isr到底在哪个VICADDR寄存器中unsigned long vicaddr[4] = {VIC0ADDR, VIC1ADDR, VIC2ADDR, VIC3ADDR};int i = 0;void (*isr)(void) = NULL;for(i = 0; i< 4; i++){// 发生一个中断时,4个VIC中有3个是全0,1个的其中1位不是0if(intc_getvicirqstatus(i) != 0){isr = (void(*)(void))vicaddr[i];break;}}(*isr)();   // 通过函数指针来调用函数
}

key.c

/********************************************************************   > File Name: key.c*   > Author: fly*   > Mail: XXXXXXXX@icode.com*   > Create Time: 2020年12月07日 星期一 19时52分42秒******************************************************************/
#include "key.h"
#include "uart.h"
#include "int.h"
#include "printf.h"// -------------------中断方式处理按键-------------------------------
// 以中断方式来处理按键的初始化
void key_init_interrupt(void)
{// 1.外部中断对应的GPIO模式设置rGPH0CON |= 0xFF << 8;		// GPH0_2/GPH0_3设置为外部中断模式rGPH2CON |= 0xFFFF << 0;	// GPH2_0/1/2/3共4个引脚设置为外部中断模式// 2.中断触发模式设置rEXT_INT_0_CON &= ~(0xFF<<8);			// bit8~15全部清零rEXT_INT_0_CON |= ((2<<8) | (2<<12));	// EXT_INT2和EXT_INT3设置为下降沿触发rEXT_INT_2_CON &= ~(0xFFFF<<0);rEXT_INT_2_CON |= ((2<<0) | (2<<4) | (2<<8) | (2<<12));// 3.中断允许rEXT_INT_0_MASK &= ~(0x03<<2);rEXT_INT_2_MASK &= ~(0x0F<<0);// 4.清挂起,清除是写1,rEXT_INT_0_PEND |= (0x03<<2);rEXT_INT_2_PEND |= (0x0F<<0);
}// EINT2通道对应的按键,就是GPH0_2引脚对应的按键,
// 就是开发板上标了LEFT的那个按键
void isr_eint2(void)
{// 真正的isr应该做2件事情。// 第一,中断处理代码,就是真正干活的代码printf("isr_eint2_LEFT.\n\r");uart2_printf("isr_eint2_LEFT.\n\r");// 第二,清除中断挂起rEXT_INT_0_PEND |= (1<<2);intc_clearvectaddr();
}void isr_eint3(void)
{// 真正的isr应该做2件事情。// 第一,中断处理代码,就是真正干活的代码printf("isr_eint3_DOWN.\n\r");uart2_printf("isr_eint3_DOWN.\n\r");// 第二,清除中断挂起rEXT_INT_0_PEND |= (1<<3);intc_clearvectaddr();
}void isr_eint16171819(void)
{// 第一,中断处理代码;// 因为EINT16~31是共享中断,所以// 要在这里再次去区分具体是哪个子中断if(rEXT_INT_2_PEND & (1 << 0)){printf("eint16_UP.\n\r");uart2_printf("eint16_UP.\n\r");}if(rEXT_INT_2_PEND & (1 << 1)){printf("eint17_RIGHT.\n\r");uart2_printf("eint17_RIGHT.\n\r");}if(rEXT_INT_2_PEND & (1 << 2)){printf("eint18_BACK.\n\r");uart2_printf("eint18_BACK.\n\r");}if(rEXT_INT_2_PEND & (1 << 3)){printf("eint19_MENU.\n\r");uart2_printf("eint19_MENU.\n\r");}// 第二,清除中断挂起rEXT_INT_2_PEND |= (0x0F << 0);intc_clearvectaddr();
}void tester_key_int(void)
{key_init_interrupt();// 如果程序要使用中断,就要调用中断初始化来// 初步初始化中断控制器system_init_exception();// 绑定isr到中断控制器intc_setvectaddr(KEY_EINT2, isr_eint2);intc_setvectaddr(KEY_EINT3, isr_eint3);intc_setvectaddr(KEY_EINT16_19, isr_eint16171819);// 使能中断intc_enable(KEY_EINT2);intc_enable(KEY_EINT3);intc_enable(KEY_EINT16_19);
}

5.拓展

NA

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

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

相关文章

基于SSM开发网上电子购物商城系统

开发工具&#xff1a;EclipseJdkTomcatMySQL数据库 效果视频&#xff1a; 链接: https://pan.baidu.com/s/1qLB1UKQV42t0TNNJRQZd7Q 提取码: g5xg

C语言例:设 int a=11; 则表达式 a+=a-=a*a 的值

注&#xff1a;软件为VC6.0 代码如下&#xff1a; #include<stdio.h> int main(void) {int a11, b;b (aa-a*a); //a*a121 -->a-121结果为a-110 -->a-110结果为a-220printf("表达式aa-a*a 的值为&#xff1a; %d\n",b);return 0; } //优先级&#x…

sparksql简介

什么是sparksql sparksql是一个用来处理结构话数据的spark模块&#xff0c;它允许开发者便捷地使用sql语句的方式来处理数据&#xff1b;它是用来处理大规模结构化数据的分布式计算引擎&#xff0c;其他分布式计算引擎比较火的还有hive&#xff0c;map-reduce方式。 sparksql…

sqllab第二十七A关通关笔记

知识点&#xff1a; 双引号闭合union select 大小写绕过 Union Select这里不能进行错误注入&#xff0c;无回显 经过测试发现这是一个双引号闭合 构造payload:id1"%09and%091"1 页面成功回显 构造payload:id0"%09uNion%09SElect%091,2,3%09"1 页面成功…

简单高效多语言请求的主流电商平台API数据采集实时接口如何采集数据

电商数据采集API功能概述&#xff1a; 1. 实时采集&#xff1a;1688采集能够自动从阿里巴巴和1688网站抓取商品信息&#xff0c;无需人工手动搜索&#xff0c;节省大量时间。 2. 商品筛选&#xff1a;用户可以根据需求设置采集条件&#xff0c;如价格、销量、信用度等&#x…

JDBC编程(Mysql)

目录 1.什么是jdbc 2.使用 2.1下载mysql数据库驱动 2.2导入项目 2.3编写代码 2.3.1数据源 2.3.2和数据库服务器建立连接 2.3.3构建一个操作数据库的sql语句 2.3.4执行sql 2.3.5释放前面创建的各种资源 2.3.6运行java程序 2.4其他操作 2.4.1修改操作 2.4.2删除操作…

基于Springboot和Redis实现的快递代取系统

1.项目简介 本项目基于springboot框架开发而成&#xff0c;前端采用bootstrap和layer框架开发&#xff0c;系统功能完整&#xff0c;界面简洁大方&#xff0c;比较适合做毕业设计使用。 本项目主要实现了代取快递的信息管理功能&#xff0c;使用角色有三类&#xff1a;一是客…

基于Springboot和Redis实现的在线选课系统

1.项目简介 1.1 介绍 毕业设计真的就是demo吗&#xff1f;作为工作前的最后一个校园项目&#xff0c;毕业设计应当尽可能的贴近企业实战&#xff0c;业务不必很复杂&#xff0c;但要做到麻雀虽小五脏俱全。本期学长跟大家一起分享如何开发一个在线选课系统&#xff0c;需求也…

中国联通智慧矿山行业解决方案

中国联通国际公司以其全球化服务能力&#xff0c;针对矿山行业的特殊挑战提供了定制化的解决方案&#xff0c;尤其是在网络通信基础设施搭建和智能应用部署方面&#xff0c;助力企业克服远程作业环境下的通信难题&#xff0c;并有效拓展海外市场。 对于矿山类企业而言&#xf…

如何引入ElementUI组件库,快速上手Element

前言&#xff1a;在上篇文章中分享了如何快速上手Vue框架项目&#xff0c;本篇文章则介绍的是Element的使用&#xff0c;通过本篇文章的分享&#xff0c;我们就可以将Vue和Element结合使用&#xff0c;快速构建出精美的网页界面 目录 一.Element和ElementUI 二.如何引入Eleme…

算法---滑动窗口练习-6(找到字符串中所有字母异位词)

找到字符串中所有字母异位词 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;找到字符串中所有字母异位词 2. 讲解算法原理 有效字符个数count更新条件&#xff1a;满足【hash1表&#xff08;遍历s的表&#xff09;中对应元素出现次数<hash2表&am…

Python基础(八)之流程控制

Python基础&#xff08;八&#xff09;之流程控制 Python控制流程分为三种接口&#xff1a; 顺序结构选择结构循环结构 1、顺序结构 程序代码自上而下运行&#xff0c;逐条执行每一条Python代码&#xff0c;不重复执行任何代码&#xff0c;也不会跳过任何代码。 当语句与语…

【现代C++】智能指针

在现代C中&#xff0c;智能指针是用来管理动态分配的内存&#xff0c;自动进行资源回收&#xff0c;以减少内存泄漏和提升代码安全性。主要有三种类型的智能指针&#xff1a;std::unique_ptr、std::shared_ptr和std::weak_ptr。以下是这些智能指针的详细介绍&#xff1a; 1. s…

使用 VS Code + Github 搭建个人博客

搭建个人博客的方案 现在&#xff0c;搭建个人博客的方式有很多&#xff0c;门槛也很低。 可以选择已有平台&#xff1a; 掘金语雀知乎简书博客园SegmentFault… 也可以选择一些主流的博客框架&#xff0c;自行搭建。 HexoGitBookVuePressdumi… 如何选择&#xff1f; 我…

【TB作品】MSP430,波形发生器,单片机,Proteus仿真

文章目录 题目效果梯形波100个点产生方法锯齿波100个点产生方法c代码和proteus仿真 题目 114 波形发生器的制作 设计要求 设计一个能产生正弦波、方波、三角波、梯形波、锯齿波的波形发生器。设置5个开关K1~K5(从 上到下),分别对应正弦波、方波、三角波、梯形波、锯齿波,按一下…

在Linux中进行OpenSSH升级

由于OpenSSH有严重漏洞&#xff0c;因此需要升级OpenSSH到最新版本。 OpenSSL和OpenSSH都要更新&#xff0c;OpenSSH依赖于OpenSSL。 第一步&#xff0c;查看当前的OpenSSH服务版本。 命令&#xff1a;ssh -V 第二步&#xff0c;安装、启动telnet&#xff0c;关闭安全文件&a…

Pycharm连接远程服务器Anoconda中的虚拟环境

在配置远程解释器时&#xff0c;踩过一些坑&#xff0c;现在记录一下配置过程&#xff1a; 步骤1&#xff1a; 打开pycharm的File里面的Settings 里面的Project:你的项目名称目录下的Python Interpreter。 步骤二&#xff1a; 点击右上角的“add interpreter”&#xff0c;选择…

详解MySql索引

目录 一 、概念 二、使用场景 三、索引使用 四、索引存在问题 五、命中索引问题 六、索引执行原理 一 、概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。暂时可以理解成C语言的指针,文章后面详解 二、使用场景 数据量较大&#xff0c;且…

代码算法训练营day9 | 28. 实现 strStr() 、459.重复的子字符串

day9&#xff1a; 28. 实现 strStr()KMP的主要应用&#xff1a;什么是前缀表&#xff1a;前缀表是如何记录的&#xff1a; 如何计算前缀表&#xff1a;构造next数组&#xff1a;1、初始化2、处理前后缀不相同的情况3、处理前后缀相同的情况 代码&#xff1a; 459.重复的子字符串…

Python算法100例-4.1 将真分数分解为埃及分数

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.补充知识点5.确定程序框架6.完整的程序 1&#xff0e;问题描述 现输入一个真分数&#xff0c;请将该分数分解为埃及分数。 2&#xff0e;问题分析 真分数&#xff08;a proper…