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

嵌入式学习硬件I.MX6ULL(五)按键 中断 GIC OCP原则

目录

一、按键

        1.步骤

(1)原理图

        ​编辑

(2)时钟

(3)复用功能

(4)电器属性

(5)输入输出方向

        2.代码

二、中断

        1.步骤

        2.GIC相关

        (1)相关寄存器

        (2)相关指令mcr和mrc(类似cpsr那里的msr和mrs)

        (3)协处理器 coprocessor

        (1)cp15中的c0寄存器的MIDR

(2)cp15中的c1寄存器SCTLR

        (3)cp15中的c12寄存器的VBAR

        (4)cp15中的c15寄存器的CBAR

        (4)异常状态返回地址偏移量

        (5)GPIO相关配置

        (1)设置中断触发方式​编辑

        (2)中断屏蔽设置

        (3)中断状态寄存器

三、OCP原则降低代码耦合度

        1.OCP原则

        interrupt.c

interrupt.h

        gpio.c

        gpio.h


一、按键

        1.步骤

        查看原理图   打开时钟    配置复用功能    配置电器属性   配置输入输出方向

(1)原理图

        

(2)时钟

        

       

(3)复用功能

ps  SION默认是开的

(4)电器属性

(5)输入输出方向

        2.代码

#include"key.h"
#include"MCIMX6Y2.h"
#include"fsl_iomuxc.h"
#include "core_ca7.h"
#include "gpio.h"
void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_UART1_CTS_B,0x10F0);GPIO_Pin_Config_t t = {.direction = GPIO_Direction_In};gpio_pin_config(GPIO1,18,&t);GPIO1->ICR2 |= (3 << 18);GPIO1->IMR |= (1 << 18);GIC_SetPriority(GPIO1_Combined_16_31_IRQn,1);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);}int key_pressed(void)
{return((GPIO1->DR & (1 << 18)) == 0) ? 1 : 0;}

二、中断

        1.步骤

        1.中断源发出中断请求

        2.CPU检查是否响应中断以及该中断是否被屏蔽

        3.检查中断的优先级

        4.保护现场

        5.执行终端服务函数

        6.恢复现场

        2.GIC相关

    

        1. SPI(Shared Peripheral Interrupt),共享中断, (注意!不是 SPI 总线那个中断),这类中断泛指所有的外设中断;

        2. PPI(Private Peripheral Interrupt),私有中断,我们说了 GIC 是支持多核的,每个核肯定有自己独有的中断。这些独有的中断肯定是要指定的核心处理,因此这些中断就叫做私有中断;
        3. SGI(Software-generated Interrupt),软件中断,由软件触发引起的中断,通过向寄存器GICD_SGIR写入数据来触发,系统会使用 SGI 中断来完成多核之间的通信。

        (1)相关寄存器

  __IM  uint32_t C_IAR;                  /*!< Offset: 0x200C (R/ ) Interrupt Acknowledge Register */                    GIC向内核发送中断号时先把中断号保存在此寄存器

  __OM  uint32_t C_EOIR;                 /*!< Offset: 0x2010 ( /W) End Of Interrupt Register */

                  中断结束寄存器      处理完中断后把中断标志位清除

        用法:把第一个寄存器的数值写入到第二个寄存器中实现中断标志位的清除

        (2)相关指令mcr和mrc(类似cpsr那里的msr和mrs)

MRC<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}

<c>是条件可以省略,<Rt>是目标寄存器,读协处理器<coproc>的某个寄存器的值到<Rt>中。

eg    mrc p15,0,r0,c0,c0,0     MIDR寄存器的值就会被写到r0寄存器中

MCR<c> <coproc>, <opc1>, <Rt>, <CRn>, <CRm>{, <opc2>}

        把<Rt>中的数写到协处理器<coproc>中。

        (3)协处理器 coprocessor

        常用cp15(找出GIC寄存器的基地址),cp10,cp11(浮点型运算)

        

        cp15有c0-c15共16个寄存器   

        (1)cp15中的c0寄存器的MIDR

(2)cp15中的c1寄存器SCTLR

        bit13,选择异常向量表的基地址。

        为0时,普通异常向量表,基地址为0x00000000。软件可以使用VBAR重新映射这个基地址。

        为1时,高异常向量表,基地址为0xFFFF0000,这个基地址不能再被映射。

        bit12,指令高速缓存使能位。这是一个全局的指令高速缓存使能位。

  mrc p15,0,r0,c1,c0,0

    bic r0,r0,#(1 << 13)   

    orr r0,r0,#(1 << 12)

    mcr p15,0,r0,c1,c0,0

        (3)cp15中的c12寄存器的VBAR

用VBAR重新映射和GIC的初始化函数,越早调用该初始化函数越好。

void system_interrupt_init(void)

{

    __set_VBAR(0x87800000);

    GIC_Init();

}

        (4)cp15中的c15寄存器的CBAR

 mrc p15,4,r1,c15,c0,0

    add r1,r1,#0x2000

    ldr r0,[r1,#0x0c]

        (4)异常状态返回地址偏移量

_irq_handler:

    subs lr,lr,#4//使程序可以回到正确的位置

    stmfd sp!,{r0-r12,lr}

    mrc p15,4,r1,c15,c0,0

    add r1,r1,#0x2000

    ldr r0,[r1,#0x0c]

    stmfd sp!,{r0,r1}

    cps #0x1f

    stmfd sp!,{lr}

        (5)GPIO相关配置

        (1)设置中断触发方式
        (2)中断屏蔽设置

        (3)中断状态寄存器

    GPIO1->GDIR &= ~(1 << 18);

    GPIO1->ICR2 |= (3 << 4);

    GPIO1->IMR |= (1 << 18);

    GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);//使能中断

        

三、OCP原则降低代码耦合度

        1.OCP原则

        对代码的添加是开放的,对代码的修改是关闭的。

        interrupt.c

#include "interrupt.h"
#include "beep.h"#include "fsl_iomuxc.h"
#include "key.h"
#include "led.h"
#include <MCIMX6Y2.h>
#include "core_ca7.h"static irq_handler_t interrupt_vector_table[160];void system_interrupt_init(void)
{__set_VBAR(0x87800000);GIC_Init();
}void system_interrupt_register(irq_handler_t handler, int num)
{interrupt_vector_table[num] = handler;
}void system_interrupt_handler(int irq)
{if (interrupt_vector_table[irq] != NULL){interrupt_vector_table[irq]();}
}

interrupt.h

#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_typedef void (*irq_handler_t)(void);
extern void system_interrupt_init(void);
extern void system_interrupt_register(irq_handler_t handler, int num);
extern void system_interrupt_handler(int irq);#endif

        gpio.c

#include "gpio.h"
#include "fsl_iomuxc.h"
#include "MCIMX6Y2.h"void init_gpio(GPIO_Type *gpio, int pin, gpio_configt_t *config)
{if(config->pin_direction == gpio_direction_output){gpio->GDIR |= (1 << pin);if(config->default_vaule != 0){gpio->DR |= (1 << pin);}else{gpio->DR &= ~(1 << pin);}}else{gpio->GDIR &= ~(1 << pin);}
}void write_gpio(GPIO_Type *gpio, int pin, int value)
{if(value){gpio->DR |= (1 << pin);}else{gpio->DR &= ~(1 << pin);}
}int read_gpio(GPIO_Type *gpio, int pin)
{return (gpio->DR & (1 << pin)) != 0;
}

        gpio.h

#ifndef _GPIO_H_
#define _GPIO_H_typedef enum
{gpio_direction_input,gpio_direction_output
}gpio_direction_t;typedef struct 
{gpio_direction_t pin_direction;int default_vaule;
}gpio_configt_t;#endif
http://www.xdnf.cn/news/18247.html

相关文章:

  • 云原生:重塑软件世界的技术浪潮与编程语言选择
  • 【每天学点‘音视频’】前向纠错 和 漏包重传
  • Flask 入门详解:从零开始构建 Web 应用
  • Linux中基于Centos7使用lamp架构搭建个人论坛(wordpress)
  • Dify web前端源码本地部署详细教程
  • 软件测试覆盖率:真相与实践
  • 【论文阅读69】-DeepHGNN复杂分层结构下的预测
  • Mybatis执行sql流程(一)
  • Dijkstra和多层图 0
  • Linux 系统(如 Ubuntu / CentOS)阿里云虚拟机(ECS)上部署 Bitnami LAMP
  • 自定义ViewPage2滑动切换效果
  • docker compose再阿里云上无法使用的问题
  • MQTT(轻量级消息中间件)基本使用指南
  • MySQL 函数大赏:聚合、日期、字符串等函数剖析
  • 用户认证与应用控制技术
  • DevExtreme Angular UI控件更新:引入全新严格类型配置组件
  • Tmux Xftp及Xshell的服务器使用方法
  • 黑马java八股文全集
  • 实时视频延迟优化实战:RTSP与RTMP播放器哪个延迟更低?
  • Python 项目里的数据清理工作(数据清洗步骤应用)
  • 《算法导论》第 27 章 - 多线程算法
  • K8S集群环境搭建(一)
  • 母猪姿态转换行为识别:计算机视觉与行为识别模型调优指南
  • ——分治——
  • 腾讯开源:视频生成框架Hunyuan-GameCraft
  • MySQL数据库初识
  • 聊聊Vuex vs Pinia
  • 【Python】Python 面向对象编程详解​
  • Golang database/sql 包深度解析(二):连接池实现原理
  • 【前端面试题】前端面试知识点(第三十一题到第六十一题)