cpu发生中断,跳到异常向量入口执行动作
1.此时需要保存被中断的现场
2.执行中断处理函数
3.恢复被中断的现场
写程序时:先设置异常入口
异常向量入口:
0地址和0xffff0000两个入口,
嵌入式 arm linux中的选择后者为入口
vim .config文件查看中断向量表的起始地址
ARM 架构的 CPU 的异常向量基址可以是 0x0000 0000,也可以是 0xffff0000, LINUX 内核
使用后者,只需要在某个寄存器里设置下,就可以将异常基址定位到这里来。这个地址并不
代表实际的内存,是虚拟地址。当建立了虚拟地址与物理地址间的映射后,得将那些异常向
量,即相当于把那些跳转指令(如:HandleSWI 等)复制拷贝到这个 0xffff0000 这个地址处去。
(“那些跳转指令”是指 head.S 中那些跳转)。
这个过程是在 trap_init 这个函数里做。
单片机下的中断处理
1.分辨是哪一个中断
2.调用处理函数
3.清中断
linux内核中
所有中断处理通过asm_do_irq()函数实现
linux 内核中处理异常的流程,最后调用到“asm_do_IRQ()”
在发生对应于第 1 个参数 irq 的中断时,则调用第 2 个参数 handler 指定的中断服务函
数(也就是把 handler() 中断服务函数注册到内核中 )。
irq:中断号。
handler:处理函数。
irqflags:上升沿触发,下降沿触发,边沿触发等。指定了快速中断或中断共享等中断处理属性.
*devname:中断名字。通常是设备驱动程序的名称。改值用在 /proc/interrupt 系统 (虚拟)
文件上,或内核发生中断错误时使用。
第 5 个参数 dev_id 可作为共享中断时的中断区别参数,也可以用来指定中断服务函数需
要参考的数据地址。
返回值:
函数运行正常时返回 0 ,否则返回对应错误的负值。
其实在没有自己分析过源码的时候,只靠韦老师讲解的那么一点是远远不够的,但是现在还是先当API和库函数的方式来使用吧,先用起来,之后需要分析源码。
code:
static int third_drv_open(struct inode *inode, struct file *file) { /* 配置GPF0,2为输入引脚 */ /* 配置GPG3,11为输入引脚 */ //IRQ_EINT0为中断源 ,buttons_irq是中断处理(回调)函数,IRQT_BOTHEDGE 双边沿触发,"S2"表示设备名字,pins_desc[0]表示设备id request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]); request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S3", &pins_desc[1]); request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", &pins_desc[2]); request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", &pins_desc[3]); return 0; }
实验现象:
在加载驱动之前,我们查看系统的中断注册情况:
此时没有发现S2-5的中断,现在加载驱动之后再查看:
现在我们使用指令(exec 5< dev/buttons)打开设备,之后使用测试程序打开:
使用下面的命令注销中断:
编译运行应用程序:
应用程序运行之后,按键分别对应不同的键值,就达到了效果,此时top命令查看占用cpu情况:
先使程序在后台运行:在Linux中,如果要让进程在后台运行,一般情况下,我们在命令后面加上&即可,实际上,这样是将命令放入到一个作业队列中了
top查看:
之前轮询方式占用cpu几乎是百分之百,现在几乎不占用cpu,可见中断方式让系统资源能够更加合理地利用。