硬件驱动——I.MX6ULL裸机启动(3)(按键设置及中断设置

重点:

1.GIC:(Generic  Interrupt  Controller)通用中断控制器,是ARM架构中用于管理中断的核心模块,主要用于现代多核处理器系统。它负责接收,分发并分发中断请求,减轻CPU负担,使其专注于计算任务。目前GIC有四个版本,V1~V4,现在只有V2~V4正在大量使用,IMX6ULL搭载的是V2的GIC控制器。

2.协处理器是一种专门用于辅助CPU执行特定任务的硬件模块,通过分担CPU的运算负荷来提升系统整体效率

AMR Cortex  A7内核配备了16个协处理器

3.将异常向量表重映射的原因:默认情况下,异常向量表在低地址(0x00000000),但系统运行时,可能需要把异常向量表放到其他的地址(比如更高的内存地址,放在操作系统或应用程序灵活管理内存空间),这样能更合理的利用内存,也便于对异常处理程序进行组织和管理。

重映射异常向量表的方法:通过协处理器(CP15)中的相关寄存器(比如向量基地址寄存器),将异常向量表的基地址修改为目标地址,是的处理器在处理异常时,能到新的地址去获得异常处理程序的入口

一.实现按键功能

相关代码:

#include "key.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "core_ca7.h"void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);   //设置IO复用功能IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF0B0);   //配置该引脚的电气属性struct GPIO_Type_t t ={.direction = gpio_input     };init_gpio(GPIO1,18,&t);        //按键为输出方式
}
int key_pressed(void)
{if(read_gpio(GPIO1,18) == 0)    //判断该引脚是高电平还是低电平,低电平为按下按键返回0,高电平为没按按键返回1{return 1;}else{return 0;}}
#ifndef __KEY_H__
#define __KEY_H__
#include "gpio.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"extern void init_key(void);extern int key_pressed(void);
#endif
int main(void)
{enable_clocks();system_interrupt_init();init_beep();init_led();init_key();while(1){delay(0xFFFFF);}return 0;
}

汇编代码与上一节一样

二.中断

1.中断步骤:

        1)中断源发出中断请求;

        2)内核检查是否响应相应中断以及判断该中断是否屏蔽;

        3)内核检查中断的优先级;

        4)保护现场

        5)执行中断服务函数;

        6)恢复现场

2.GIC中断控制器

GIC:(Generic  Interrupt  Controller)通用中断控制器,是ARM架构中用于管理中断的核心模块,主要用于现代多核处理器系统。它负责接收,分发并分发中断请求,减轻CPU负担,使其专注于计算任务。目前GIC有四个版本,V1~V4,现在只有V2~V4正在大量使用,IMX6ULL搭载的是V2的GIC控制器。

GIC能处理1200个中断,分为三大类:

1.SPI:共享外设中断        32~1019

2.PPI:私有外设中断,内核与内核之间的通信中断        16~31号

3.SGI:软件产生中断        0~15号

IMX6ULL中有160个中断

IAR:中断通知寄存器        将中断编号传给内核

EOIR:中断结束寄存器        清除中断

3.协处理器(Techinal手册)

ARM内核支持16个协处理器,CP0~CP15,

SCTLR:映射异常向量表

VBVR:异常向量的基地址

mrc:用来读的目标寄存器(CP15)的值放到通用寄存器当中去

mcr:用来将通用寄存器里的值写到(CP15)目标寄存器当中去

MRC{cond} p15, <opc1>, <Rt>, <CRn>, <CRm>, <opc2>
cond:指令执行的条件码,就是之前我们使用过的指令条件,eq,lt什么的。如果忽略的话就表
示无条件执行;

p15:表示要读取的是CP15当中的某个寄存器;

opc1:协处理器要执行的操作码1,其实就是一个数,要做什么将来查表;

Rt:ARM 目标寄存器,读出来的数据放到哪个ARM寄存器里。CP15

CRn:CP15 协处理器的目标寄存器,就是你要读取CP15的哪个寄存器(C0~C15);

CRm:协处理器中附加的目标寄存器或者源操作数寄存器,如果不需要附加信息就将CRm 设置
为 C0,否则结果不可预测。 

opc2:可选的协处理器特定操作码2,使用时查表。

4.实现的代码

#include "key.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "core_ca7.h"
#include "interrupt.h"
#include "led.h"
void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);   //设置IO复用功能IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF0B0);   //配置该引脚的电气属性struct GPIO_Type_t t ={.direction = gpio_input     };init_gpio(GPIO1,18,&t);        //按键为输出方式GPIO1->ICR2 |= (3 << 4);       //将GPIO1当中的18号引脚设置为下降沿触发方式  ICR为中断方式的寄存器GPIO1->IMR |= (1 << 18);       //将GPIO1当中的18号引脚置1,打开18号引脚的中断屏蔽寄存器     IMR为中断屏蔽寄存器system_interrupt_register(GPIO1_Combined_16_31_IRQn,key_interrupt_handler);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);       //打开指定的中断,该位置打开编号为99的中断GIC_SetPriority(GPIO1_Combined_16_31_IRQn,0);   //设置中断优先级为0,即优先级最高
}void key_interrupt_handler(void)
{if((GPIO1->ISR &(1 << 18)) != 0)    //判断中断标记寄存器中产生中断是由GPIO1的18号引脚造成的{led_nor();GPIO1->ISR |= (1 << 18);        //清除中断标记寄存器}
}
int key_pressed(void)
{if(read_gpio(GPIO1,18) == 0)    //判断该引脚是高电平还是低电平,低电平为按下按键返回0,高电平为没按按键返回1{return 1;}else{return 0;}}
#include "interrupt.h"
#include "MCIMX6Y2.h"
#include "core_ca7.h"static irq_handler_t interrupt_vector_table[160];  //定义一个函数的指针的数组,用来存放中断void system_interrupt_init(void)
{GIC_Init();     //对GIC控制器进行初始化操作
}void system_interrupt_register(int num, irq_handler_t handler)  //注册中断服务函数
{interrupt_vector_table[num] = handler;      
}void system_interrupt_handler(int num)      //中断服务函数,num为哪一个中断发出的中断请求,传递其中断号
{if(interrupt_vector_table[num] != NULL)    //什么原因造成的中断,该处为中断编号为99的中断{interrupt_vector_table[num]();      //调用这个函数的指针数组}}
.global _start_start:ldr pc, =_reset_handlerldr pc, =_undefine_handlerldr pc, =_svc_handlerldr pc, =_prefetch_abort_handlerldr pc, =_data_abort_handlerldr pc, =_reserved_handlerldr pc, =_irq_handlerldr pc, =_fiq_handler_undefine_handler:ldr pc, =_undefine_handler_svc_handler:ldr pc, =_svc_handler_prefetch_abort_handler:ldr pc, =_prefetch_abort_handler_data_abort_handler:ldr pc, =_data_abort_handler_reserved_handler:ldr pc, =_reserved_handler
//在main函数当中初始化irq中断函数
_irq_handler:subs lr, lr, #4         //通过查表,将链接寄存器的值减4(异常状态返回地址)mrc p15, 4, r1, c15, c0, 0      //将GIC的基地址放到r1当中去add r1, r1, #0x2000         //得到的是C_CTLR的基地址ldr r0, [r1, #0x0C]         //将r1当中的基地址偏移0x0C的地址(C-IAR(发出中断请求的寄存器))存(读)到r0寄存器当中stmfd sp!, {r0-r12, lr}     //保护现场stmfd sp!, {r0, r1}         //将r0和r1入栈cps #0x1F                   //切换为system模式stmfd sp!, {lr}             //保护system模式下的lrbl system_interrupt_handler //调用C语言函数ldmfd sp!, {lr}             //恢复system模式下的lrcps #0x12                   //切换为irq模式ldmfd sp!, {r0, r1}         //将第38行的r0和r1出栈str r0, [r1, #0x10]         //将r0当中的值写到r1偏移0x10的地址上去(C_EOIR(清除中断标志的寄存器))ldmfd sp!, {r0-r12, pc}^    //恢复现场并且改变模式
_fiq_handler:ldr pc, =_fiq_handler_reset_handler:
/*     mrs r0,cpsrbic r0, r0, #0x1Forr r0, r0, #0x12   //irp(10010)bic r0, r0, #(1 << 7)       //打开irq中断msr cpsr, r0ldr sp, =0x86000000mrs r0,cpsrbic r0, r0, #0x1Forr r0, r0, #0x1F   //system(11111)msr cpsr, r0ldr sp, =0x84000000
*/cps #0x12           //irq(10010)模式ldr sp, =0x86000000 cps #0x1F           //system(11111)模式cpsie ildr sp, =0x84000000//先通过CP15写处理器打开设置基地址的选项,再通过映射异常向量表bl _enable_icahce       bl _set_vbar bl _bss_clear b main  //跳转至main函数当中//处理CP15协处理器(SCTLR)
_enable_icahce:         mrc p15, 0, r0, c1, c0, 0       //读目标寄存器的值放到通用寄存器r0上bic r0, r0, #(1 << 13)          //根据查表,将SCTLR的第13位清0,此位用来选择异常向量的基地址,目的是软件可以通过VBAR来重新设置这个基地址orr r0, r0, #(1 << 12)          //根据查表,将SCTLR的第12位置1,此位用来将指令cache进来打开,默认是关闭状态mcr p15, 0, r0, c1, c0, 0       //将修改后的目标寄存器的值重新写入目标寄存器bx lr
//设置异常向量表基地址(VBAR)
_set_vbar:ldr r0, =0x87800000              //将异常向量表的基地址存入到r0当中mcr p15, 0, r0, c12, c0, 0       //根据查表,将r0当中的基地址通过cp15协处理器写入CBAR当中,当作GIC的基地址bx lr_bss_clear:ldr r0, =__bss_startldr r2, =__bss_end
loop:mov r1, #0str r1, [r0]add r0, r0, #4cmp r0, r2blt loopbx lrfinished:b finished
#include "beep.h"
#include "led.h"
#include "key.h"
#include "core_ca7.h"
#include "interrupt.h"void enable_clocks(void)    //将所有时钟都打开
{CCM->CCGR0 = 0xFFFFFFFF;CCM->CCGR1 = 0xFFFFFFFF;CCM->CCGR2 = 0xFFFFFFFF;CCM->CCGR3 = 0xFFFFFFFF;CCM->CCGR4 = 0xFFFFFFFF;CCM->CCGR5 = 0xFFFFFFFF;CCM->CCGR6 = 0xFFFFFFFF;
}void delay(unsigned int n)
{while(n--);             //进行延时}int main(void)
{enable_clocks();system_interrupt_init();init_beep();init_led();init_key();while(1){delay(0xFFFFF);}return 0;
}

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

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

相关文章

用deepseek对GPU服务器进行压力测试

利用 DeepSeek 模型对 GPU 服务器进行压力测试&#xff0c;核心思路是通过模拟高负载的模型推理 / 微调任务&#xff0c;验证 GPU 服务器在计算、显存、网络等维度的承载能力&#xff0c;同时观察稳定性与性能瓶颈。以下是具体的测试方案&#xff0c;涵盖测试环境准备、核心测试…

ARM(7)IMX6ULL 按键控制(轮询 + 中断)优化工程

一、硬件介绍1. 开关功能定义共 3 个开关&#xff08;两红一黄&#xff09;&#xff0c;功能分工明确&#xff1a;中间开关&#xff1a;复位按钮左边开关&#xff1a;低功耗按钮右边开关&#xff1a;用户独立控制的试验按键&#xff08;核心控制对象&#xff09;2. 核心电平逻辑…

【QT随笔】什么是Qt元对象系统?Qt元对象系统的核心机制与应用实践

【QT随笔】什么是Qt元对象系统&#xff1f;Qt元对象系统的核心机制与应用实践 之所以写下这篇文章&#xff0c;是因为前段时间自己面试的时候被问到了&#xff01;因此想借此分享一波&#xff01;&#xff01;&#xff01;本文主要详细解释Qt元对象系统的概念、作用及实现机制…

从技术视角解析加密货币/虚拟货币/稳定币的设计与演进

随着加密货币行情的持续走高&#xff0c;除了资产价值&#xff0c;我想试着从底层程序设计与架构角度解析比特币、以太坊、稳定币以及新兴公链的核心技术方案。作者在2018年设计实施了基于区块链技术的金融项目&#xff0c;并荣获了国家课题进步奖&#xff0c;对加密货币及场景…

[MySQL]Order By:排序的艺术

[MySQL]Order By&#xff1a;排序的艺术 1. 简介 在数据库管理中&#xff0c;数据的排序是一项至关重要的操作。MySQL 的 ORDER BY 子句为我们提供了强大而灵活的功能&#xff0c;用于对查询结果进行排序。无论是按照字母顺序排列名称&#xff0c;还是根据日期或数值进行升序…

【工具代码】使用Python截取视频片段,截取视频中的音频,截取音频片段

目录 ■截取视频方法 1.下载 ffmpeg-8.0-essentials_build 2.配置到环境变量 3.python代码 4.运行 5.效果 ■更多 截取视频中的音频 截取音频 Sony的CR3图片&#xff0c;转换为JPG ■截取视频方法 1.下载 ffmpeg-8.0-essentials_build "https://www.gyan.de…

Three.js 平面始终朝向相机

instanceMesh需要让实例像粒子一样始终朝向相机 可以如下处理shaderexport const billboarding // billboarding函数的GLSL实现 // 参数: // - position: 顶点动态位置偏移 // - positionLocal: mesh的position // - horizontal: 水平方向是否朝向相机 // - vertical: 垂直方…

旗讯 OCR 识别系统深度解析:一站式解决表格、手写文字、证件识别难题!

在数字化办公日益普及的今天&#xff0c;“纸质文档转电子”“图片信息提取” 等需求愈发频繁&#xff0c;但传统手动录入不仅效率低下&#xff0c;还容易出现数据错误。近期发现一款实用性极强的工具 —— 旗讯数字 OCR 识别系统&#xff0c;其覆盖多场景的识别功能、极简操作…

MissionPlanner架构梳理之(十四)日志浏览

概述和目的 Mission Planner 中的日志浏览系统提供了加载、查看、分析和解读 ArduPilot 驱动的飞行器生成的飞行日志的工具。飞行日志包含飞行操作期间记录的关键遥测数据&#xff0c;使用户能够查看飞行性能、诊断问题并从过去的飞行中获取见解。 本页记录了日志浏览系统的架…

机器学习shap分析案例

在进行数据分析和机器学习时经常用到shap&#xff0c;本文对shap相关的操作进行演示。波士顿数据集链接在这里。 SHAP Analysis Guide Set up 导入必要包 import pandas as pd import numpy as np import lightgbm as lgb import matplotlib import matplotlib.pyplot as p…

网络编程相关函数

1. 套接字操作相关1.1 socketint socket(int domain, int type, int protocol);参数说明int domain协议族&#xff0c;常用 AF_INET&#xff08;IPv4&#xff09;、AF_INET6&#xff08;IPv6&#xff09;int type套接字类型&#xff0c;SOCK_DGRAM&#xff08;UDP&#xff09;、…

ESLint 自定义 Processor(处理器)

ESLint 自定义 Processor&#xff08;处理器&#xff09; &#x1f539; 什么是 Processor&#xff1f; 在 ESLint 中&#xff0c;Processor&#xff08;处理器&#xff09;是一种扩展机制&#xff0c;允许处理非标准 JavaScript/TypeScript 文件。默认情况下&#xff0c;ESLin…

C++语法 | static静态|单例模式

这里写目录标题static 关键字静态局部变量 vs 局部变量静态全局变量 vs 全局变量静态成员变量 vs 成员变量静态成员函数单例模式static 关键字 在此之前, 先了解一下 static 关键字 静态局部变量 vs 局部变量 在静态局部变量中&#xff0c;变量不会在函数调用结束后销毁&…

KEDA/HPA/VPA 三件套:ABP 后台作业的事件驱动伸缩

&#x1f680; KEDA/HPA/VPA 三件套&#xff1a;ABP 后台作业的事件驱动伸缩 &#x1f4da; 目录&#x1f680; KEDA/HPA/VPA 三件套&#xff1a;ABP 后台作业的事件驱动伸缩0. TL;DR ✨1. 背景与目标 &#x1f3af;2. 架构与协作机制 &#x1f9e9;2.1 系统总览&#xff08;组…

webRTc 为何深受直播实现的青睐?

WebRTC(Web Real-Time Communication)之所以在直播场景中备受青睐,核心原因在于它天然契合了现代直播对低延迟、实时互动、跨平台兼容性的核心需求,同时大幅降低了实时音视频开发的门槛。具体来说,其优势体现在以下几个方面: 1. 超低延迟,满足实时互动需求 传统直播协…

HarmonyOS迷宫游戏鸿蒙应用开发实战:从零构建随机迷宫游戏(初版)

在鸿蒙应用开发中&#xff0c;游戏类应用能很好地锻炼 UI 布局、状态管理与逻辑交互能力。本文将以一个随机迷宫游戏为例&#xff0c;详细拆解从首页设计到迷宫生成、角色控制、通关判定的完整开发流程&#xff0c;带你掌握 ArkUI 框架的核心应用技巧。一、项目整体架构本次开发…

石头科技出海升级:全球电商业财一体化与OMS实践

石头科技作为智能清洁设备领域的独角兽&#xff0c;2023 年海外收入占比超过 60%&#xff0c;产品销往全球 60 多个国家。然而&#xff0c;智能硬件出海的复杂性&#xff0c;让企业在业财管理上面临前所未有的挑战。智能硬件业财痛点 产品生命周期管理&#xff1a;研发、生产到…

《URP管线中后处理效果的创新应用与优化实践》

硬件性能的飞速提升与玩家对画面品质的高要求形成了相互推动的态势,而渲染效果作为游戏视觉体验的核心载体,直接决定了玩家对游戏的第一印象与沉浸感。后处理效果作为URP管线的“点睛之笔”,通过在渲染流程末尾对最终图像进行二次加工,能够模拟真实世界的光学现象(如光线散…

【Java 底层】JVM 垃圾回收机制深度剖析:从对象生死判定到收集器实战

【Java 底层】JVM 垃圾回收机制深度剖析&#xff1a;从对象生死判定到收集器实战 【Java 底层】JVM 垃圾回收机制深度剖析&#xff1a;从对象生死判定到收集器实战 Java 之所以被称为 “开发效率利器”&#xff0c;很大程度上得益于其自动内存管理机制 —— 开发者无需手动分配…

网络问题排查

网络连通性测试&#xff1a;ping ip持续性监测&#xff1a;ping -t ipnetstat 可以查看网络连接状态&#xff0c;可以看到显示系统的网络连接&#xff0c;路由表&#xff0c;接口等信息。netstat -nult 回车-t:显示的是tcp的连接-u:显示udp的连接-l:只显示监听状态的端口-n:显示…