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

嵌入式学习硬件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.lryc.cn/news/624863.html

相关文章:

  • seuratv4数据结构
  • 软考 系统架构设计师系列知识点之杂项集萃(129)
  • 【数模国奖冲刺】备赛过程中的常见问题
  • Jmeter对图片验证码的处理
  • vue3 + antd实现简单的图片点开可以缩小放大查看
  • 视觉语言导航(4)——强化学习的三种方法 与 优化算法 2.43.4
  • BeeWorks 私有化会议系统:筑牢企业会议安全防线,赋能高效协同
  • Go并发编程-goroutine
  • 私有化部署本地大模型+function Calling+本地数据库
  • 【秋招笔试】2025.08.17字节跳动秋招机考真题
  • 技术赋能安全:智慧工地构建城市建设新防线
  • IB数学课程知识点有哪些?IB数学课程辅导机构怎么选?
  • [系统架构设计师]未来信息综合技术(十一)
  • 【秋招笔试】2025.08.17大疆秋招机考第一套
  • C++ STL容器相关操作的复杂度分析
  • FPGA驱动量子革命:微美全息(NASDAQ:WIMI)实现数字量子计算关键验证
  • 认证授权系统设计
  • redis-集成prometheus监控(k8s)
  • 【K8s】harbor安装与推送镜像
  • 中断线程化
  • 虚幻基础:动作时间窗
  • 徕芬的冰火两重天:增长困局,转型阵痛还是衰落前奏?
  • SQL注入防御
  • 【168页PPT】IBM五粮液集团数字化转型项目实施方案建议书(附下载方式)
  • 力扣2道dp
  • Dijkstra和多层图 0
  • [NSSCTF 2022 Spring Recruit]rrrsssaaa
  • 决策树学习报告
  • 决策树简单实战
  • 容器化 Android 开发效率:cpolar 内网穿透服务优化远程协作流程