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

《嵌入式硬件(十一):基于IMX6ULL的中断操作》

一、中断的基本概念

        外设可以产生中断->GIC(Generic Interrupt Controller)控制器接收中断->传输给内核

        GIC(Generic Interrupt Controller,通用中断控制器)是ARM架构中用于管理中断请求的硬件模块,主要作用是在多核心、多外设的场景下,对中断进行分发与管理,确保不同的中断能被正确地路由到对应的处理器核心,以实现高效的中断处理。

二、外设原理

        1.ICR1

        2.ICR2

3.IMR(中断屏蔽寄存器)

        4.ISR(中断状态寄存器)

        

        5.EDGE_SEL(边缘寄存器)

三、GIC原理

        1.基本概念

GIC

        最多八核;

        中断总共有1020,分为三类,SPI(32-1019),共享外设中断,PPI(16~31),私有外设中断,SGI(0~15号),软件产生中断。

IMX6ULL

        内核中断有32个,外设中断有128个

        e.g. GPIO1组的中断,后俩个是引脚号结合起来的中断

  GPIO1_INT4_IRQn              = 93,               /**< INT4 interrupt request. */GPIO1_INT3_IRQn              = 94,               /**< INT3 interrupt request. */GPIO1_INT2_IRQn              = 95,               /**< INT2 interrupt request. */GPIO1_INT1_IRQn              = 96,               /**< INT1 interrupt request. */GPIO1_INT0_IRQn              = 97,               /**< INT0 interrupt request. */GPIO1_Combined_0_15_IRQn     = 98,               /**< Combined interrupt indication for GPIO1 signals 0 - 15. */GPIO1_Combined_16_31_IRQn    = 99,               /**< Combined interrupt indication for GPIO1 signals 16 - 31. */

        e.g.中断寄存器

  __IOM uint32_t C_CTLR;                 /*!< Offset: 0x2000 (R/W) CPU Interface Control Register */__IM  uint32_t C_IAR;                  /*!< Offset: 0x200C (R/ ) Interrupt Acknowledge Register */__OM  uint32_t C_EOIR;                 /*!< Offset: 0x2010 ( /W) End Of Interrupt Register */

中断优先级屏蔽寄存器

中断通知寄存器:保存终端号

中断结束寄存器:清楚中断标记

2.协处理器

        协处理器是一种为了协助主处理器完成特定功能(如浮点运算、加密、信号处理等)而设计的处理器,它可以分担主处理器的任务,提升系统在特定领域的处理效率。  ARM Cortex A7内核配备了16个协处理器,其中CP15(系统控制协处理器)使用的多,保存着GIC基地址。

        要对异常向量表进行映射

        重映射原因:异常向量表默认位于固定的低地址区域(如0x00000000附近),该区域在系统运行过程中可能会被其他代码(如引导程序、应用程序)占用或修改,导致异常处理程序无法正常执行。通过重映射,可以将异常向量表移到安全、不会被干扰的内存区域(如高地址的RAM区域),保证异常处理的可靠性。

        重映射方法:通过设置ARM处理器的协处理器CP15中的相关寄存器(如Vector Base Address Register,VBAR),将异常向量表的基地址指向新的内存区域,从而实现异常向量表的重映射。

读取协处理器内容的指令

        MRC <c> <coproc>, <opc 1>, <rt>, <CRn> , <CRm>{,<opc2> }        [对照着协处理器表填]

写协处理器的指令

        MCR <c> <coproc>, <opc 1>, <rt>, <CRn> , <CRm>{,<opc2> }        [对照着协处理器表填]

        设置基地址(库里面已经写了),但是可以学习怎么自己写

                mrc p15, 4, r0, c15, c0, 0

        初始化函数:在core_ca7.h里,GIC_Init()

        tpis:内联函数,调用前需要有定义,所以把他写在头文件里(static inline xxxxx),调用时可能会展开,此时会提高效率

四、CPU原理

        

        1.CPSR

                IF位

tips:如果不是软中断,需要加一行subs lr, lr, #4(ARM规定)

        异常向量返回地址偏移量

tips:cps,armv6以上支持

        作用1:修改处理器的状态

                CPS #<mode>

作用2:CPS<effect>{<q>} <iflags> {, #<mode>}

        允许中断通过,cpsie i == bic r0, r0, #(1 << 7)

五、代码

        结构与之前一样

        1.bsp

                1)key.c

#include "key.h"
#include "fsl_iomuxc.h"
#include "gpio.h"
#include "led.h"
#include "MCIMX6Y2.h"
#include "core_ca7.h"
#include "interrupt.h"
#include "beep.h"void key_interrupt_handler(void)
{    if((GPIO1->ISR & (1 << 18)) != 0){beep_on();led_nor();GPIO1->ISR |= (1 << 18);}
}void init_key(void)
{IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);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->IMR |= (1 << 18);system_interrupt_register(GPIO1_Combined_16_31_IRQn, key_interrupt_handler);GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);//使能中断GIC_SetPriority(GPIO1_Combined_16_31_IRQn,0);//设置优先级
}int key_pressed(void)
{if(read_gpio(GPIO1, 18) == 1)//没有按下{return 0;}else{return 1;}
}

                2)key.h

#ifndef _KEY_H_
#define _KEY_H_extern void init_key(void);
extern int key_pressed(void);#endif

                3)interrupt.c

#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方便使用0处理器
}void system_interrupt_register(int num, irq_handler_t handler)
{interrupt_vector_table[num] = handler;
}void system_interrupt_handler(int num)
{if(interrupt_vector_table[num] != NULL){interrupt_vector_table[num]();}
}

                4)interrupt.h

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

以及之前的代码

        2.project

                1)main.c

#include "beep.h"
#include "led.h"
#include "key.h"
#include "MCIMX6Y2.h" 
#include "core_ca7.h"
#include "gpio.h"
#include "interrupt.h"int main(void)
{enable_clocks();system_interrupt_init();init_led();init_beep();init_key();   while(1){delay(0x0FFFFF);}return 0;
}

                2)start.S

.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_irq_handler:subs lr, lr, #4mrc p15, 4, r1, c15, c0, 0	//GIC获取基地址add r1, r1, #0x2000ldr r0, [r1, #0x0C]stmfd sp!, {r0-r12, lr}stmfd sp!, {r0, r1}cps #0x1fstmfd sp!, {lr}bl system_interrupt_handlerldmfd sp!, {lr}ldmfd sp!, {r0, r1}str r0, [r1, #0x10]ldmfd sp!, {r0-r12, pc}^_fiq_handler:ldr pc, =_fiq_handler_reset_handler://mrs r0, cpsr//bic r0, r0, #0x1F//orr r0, r0, #0x12   //irq//bic r0, r0, #(1 << 7)//msr cpsr, r0cps #0x12ldr sp, =0x86000000	//起始地址80000000,ram大小为512mb(20000000)	80000000~A0000000-1//mrs r0, cpsr//bic r0, r0, #0x1F//orr r0, r0, #0x1F   //system//msr cpsr, r0   cps #0x1fcpsie ildr sp, =0x84000000	//给irq分配的栈指针空间bl _enable_icahcebl _set_vbarbl _bss_clearb main_enable_icahce:mrc p15, 0, r0, c1, c0, 0bic r0, r0, #(1 << 13)orr r0, r0, #(1 << 12)mcr p15, 0, r0, c1, c0, 0bx lr_set_vbar:ldr r0, =0x87800000mcr p15, 0, r0, c12, c0, 0bx 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


文章转载自:

http://VCro9Auw.yLkLr.cn
http://KNMLEiV7.yLkLr.cn
http://ALUeZMXq.yLkLr.cn
http://R85LbrCx.yLkLr.cn
http://gCut9bb8.yLkLr.cn
http://jqHnrnIS.yLkLr.cn
http://C8GHyR20.yLkLr.cn
http://690xOg13.yLkLr.cn
http://S9zClqtR.yLkLr.cn
http://vyspHZrf.yLkLr.cn
http://ncmxUtXQ.yLkLr.cn
http://5nqzEou3.yLkLr.cn
http://EWHyjrnB.yLkLr.cn
http://mecCtWq9.yLkLr.cn
http://5m2D9wIN.yLkLr.cn
http://N6v83jns.yLkLr.cn
http://pgnx1C9z.yLkLr.cn
http://Q7w1OxAV.yLkLr.cn
http://b57rgqqK.yLkLr.cn
http://XijO0WN1.yLkLr.cn
http://OpmCGDBj.yLkLr.cn
http://aveIswgF.yLkLr.cn
http://vha17qfT.yLkLr.cn
http://dZR3nBVb.yLkLr.cn
http://HGgn66bt.yLkLr.cn
http://ZBvcqlLu.yLkLr.cn
http://RnGVYBNg.yLkLr.cn
http://2ilzBPmf.yLkLr.cn
http://s1bMMSYX.yLkLr.cn
http://X3hx2msB.yLkLr.cn
http://www.dtcms.com/a/383215.html

相关文章:

  • 【Pywinauto库】12.4 pywinauto.uia_element_info后端内部实施模块
  • 工程机械健康管理物联网系统:移动互联与多工况诊断的技术实现
  • python递归解压压缩文件方法
  • 深入 Spring MVC 返回值处理器
  • 黑马JavaWeb+AI笔记 Day05 Web后端基础(JDBC)
  • Open3D 射线投射(Ray Casting,Python)
  • RL【10-1】:Actor - Critic
  • 计算机视觉(opencv)实战二十一——基于 SIFT 和 FLANN 的指纹图像匹配与认证
  • 纯`css`固定标题并在滚动时为其添加动画
  • 金融科技:银行中的风险管理
  • 【办公类-113-01】20250914小2班生日手机备忘录提示、手机同屏到电脑UIBOT(双休日前移、节假日前移)
  • K8s学习笔记(二) Pod入门与实战
  • 如何下载Jemeter测试工具;如何汉化Jmeter2025最新最全教程!
  • 子网划分专项训练-2,eNSP实验,vlan/dhcp,IP规划、AP、AC、WLAN无线网络
  • 【LLM】大模型训练中的稳定性问题
  • Electron第一个应用
  • 企业设备维护成本预测模型全解析
  • 【数据结构】二叉树的概念
  • 架构思维: 高并发场景下的系统限流实战
  • 【开题答辩全过程】以 SpringBoot的乡村扶贫系统为例,包含答辩的问题和答案
  • Git 打标签完全指南:从本地创建到远端推送
  • RabbitMQ如何保障消息的可靠性
  • window显示驱动开发—枚举显示适配器的子设备
  • 《嵌入式硬件(九):基于IMX6ULL的蜂鸣器操作》
  • 《嵌入式硬件(十二):基于IMX6ULL的时钟操作》
  • Redis最佳实践——性能优化技巧之监控与告警详解
  • PySpark基础例题(包含map、reduceByKey、filter、sortBy等算子)
  • 导购APP佣金模式的分布式锁实现:基于Redis的并发控制策略
  • 运维自动化工具Ansible大总结20250914
  • Linux 库开发入门:静态库与动态库的 2 种构建方式 + 5 个编译差异 + 3 个加载技巧,新手速看