imx6ul 9 之中断系统

一、回顾stm32的中断系统
1、stm32中断向量表
arm芯片从0x00000000开始运行,执行指令;
在程序开始的地方存放着中断向量表。
中断向量表的主要功能描述中断对应的中断服务函数。
对于stm32来说,代码开始的地址(0x8000 0000)存放堆栈栈顶指针
2、中断向量偏移
一般来说,arm从0x0000 0000开始运行,而stm32是从设置链接首地址为0x8000 0000。
如果代码一定要从0x8000 0000开始运行,那么需要告诉cpu(soc内核)。也就是设置中断向量向量偏移。
设置内核里面的SCB控制器的VTOR寄存器为新的中断向量表起始地址即可。
3、NVIC中断控制器
NVIC就是中断管理机构。
使能和关闭指定中断,设置中断优先级。
4、中断服务函数的编写
中断服务函数就是中断要做的事情。

二、cortex-a7中断系统
1、cortex-a7中断系统
cortex-a有中断向量表,内有8个中断,重点关注irq。
此中断向量表需要用户自己去定义,写在启动汇编里面。
2、中断向量偏移
裸机例程都是从0x8780 0000,因此要设置中断向量偏移在函数 int_init()函数中
3、GIC中断控制器
同NVIC一样,GIC用来管理cortex-a的中断。
GIC提供了开关中断,设置中断优先级的功能(有专门的文档v2.0)
4、imx6u中断号
为了区分不同的中断,引入了中断号
每个cpu最多支持1020个中断
ID0 ~ 15 :SGI
ID16 ~ 31:PPI
ID32~1019:SPI,也就是按键中断,串口中断…
参考手册 chapter3
6ul有128个中断,32以后的能被cpu使用(32 - 159)//参考手册page 183
查参考手册的表得到哪个ID对应哪个外设的中断
5、中断服务函数的编写
一个是IRQ中断服务函数的编写
一个是在IRQ中断服务函数里面去查找并运行的具体的外设中断服务函数

三、GIC中断控制器

四、中断实验编写
1、编写按键中断例程
linux中对于按键一般采用按键控制。
key0使用uart1_cts这个io。
编写uart1_cts的中断代码。
2、修改start.s
添加中断向量表,编写复位中断函数 和 IRQ中断服务函数
中断向量表哪个偏移地址上应该写哪个中断服务函数,在arm mannual 手册 page 1167


编写复位中断服务函数,内容如下:

  • 1、关闭 I ,D Cache 和 MMU(内部boot-rom已经做了这件事,这里再做一次用于演示)
  • 2、设置处理器9种工作模式下对应的sp指针(不同模式的sp寄存器一般不同,不同模式使用各自模式的sp),要使用中断则必须设置IRQ模式下的sp指针。索性直接设置所有模式下的sp指针
  • 3、清除bss段
  • 4、跳转到c的main函数

3、cp15协处理器
有c0 ~ c15 共16个寄存器
(开发指南p426)(ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition p1470)
MRC 就是读 CP15 寄存器, MCR 就是写 CP15 寄存器,读写有专门的指令 ,必须大写!!
格式:MCR{cond} p15, , , , ,
MRC p15,0,r0,c0,c0,0
现在要关闭I_Cache,D_Cache 和 MMU
(Cortex-A7 Technical ReferenceManua p105)
找到SCTLR寄存器,也就是系统控制寄存器(也属于cp15协处理器)
此寄存器 bit0 用于开关MMU,bit1 对齐控制位,bit2 控制 data cache 的开关,bit11 用于控制分支预测(和mmu有关,关了),bit12 用于控制instruction cache

中断向量偏移设置(汇编方式)
将新的中断向量表首地址写入CP15协处理器的VBAR寄存器 ------> vector base address(arm mannual v7 p1479,1735)
MCR{cond} p15, , , , ,
MRC p15,0,r0,c12,c0,0----->读取VBAR
MCR p15,0,r0,c12,c0,0----->写VBAR
DMB,DSB,ISB


IRQ中断服务函数(start.S)
(cortex-a7 technical mannual)p68
mrc p15,4,r1,c15,c0,0
读取cp15的CBAR寄存器,该寄存器保存了GIC控制器的寄存器组首地址(cortex a7 tech chapter 8)
GIC寄存器组偏移0x1000 ~ 0x1fff 为GIC的分发器distributor
0x2000~0x3fff为CPU接口端
根据此偏移访问GIC控制器
代码中r1寄存器保存着GIC控制器的CPU接口端基地址
读取CPU接口端的 GICC_IAR 寄存器的值保存到 r2 寄存器里面,可以从 GICC_IAR 的 bit9~0 读取中断ID,我们读取中断ID的目的就是为了从我们定义的数组里面得到对应的中断处理函数 (GIC手册的p 135)
system_irqhandler为具体的中断处理c语言函数,只有一个参数,就是GICC_IAR寄存器的值,存于寄存器 r0 中,在汇编中通过寄存器r0来传递这个寄存器的值,从而获得int_id。
system_irqhandler 处理完具体的中断以后,需要将GICC_IAR的值原样写入到GICC_EOIR里面(GIC page 136,138)


6ull gpio中断设置

1、首先要设置gpio的中断触发方式,也就是设置 GPIO_IR1 或者 GPIO_IR2 。本例程设置key0.也就是uart1_cts为下降沿触发。本例程按下按键,gpio接地变成低电平。
2、使能gpio对应的中断,就是设置 GPIO_IMR 寄存器。
3、处理完中断以后,要向 GPIO_ISR 寄存器对应位写1清除中断标志位。

4、gic配置
- 4.1、使能相应的中断id。gpio1_io18对应的中断id为67 + 32 = 99
- 4.2、设置相应的中断优先级(不需要也可以不设置)
- 4.3、注册gpio1_io18的中断处理函数


输入模式下将DR换成PSR是否能正确读出对应io的数据


  • tips
    Makefile里面,前两个用 ?=,后面用 :=,否则 . S 文件编译报错
    start.S 里面的 push {r0},pop{r0},必须要加大括号 { }
    中断的初始化一定要放在代码的最前面。
    实际开发中,禁止在中断服务函数中调用延时函数。
    start.S 中将清bss段的部分移动到 reset_handler 复位中断里面。使中断向量表的偏移为0x8780 0000
    需要注意的是当 GPIO方向 设置为输入时(GPIO_GDIR = 0),对 GPIO_DR 的读访问不返回 GPIO_DR 数据,相反,它返回 GPIO_PSR 数据,这是相应的输入信号值。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值