文章目录
1.中断子系统
1.1中断子系统实现原理
异常处理流程:4大步,3小步

1.2中断子系统的API
unsigned int irq_of_parse_and_map(struct device_node *dev,int index)
功能:解析得到软中断号
参数:
@dev:节点的指针
@inde:索引号
返回值:成功返回软中断,失败返回0
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
功能:注册中断
参数:
@irq:软中断号
@handler:中断处理函数
irqreturn_t irq_handle(int irqno, void * dev)
{
return IRQ_NONE; //中断处理函数执行失败
return IRQ_HANDLED; //中断处理函数执行成功了
}
@flags:中断触发方式
IRQF_TRIGGER_RISING :上升沿
IRQF_TRIGGER_FALLING :下降沿
IRQF_TRIGGER_HIGH :高电平
RQF_TRIGGER_LOW :低电平
IRQF_SHARED:共享中断
@name:中断的名字
cat /proc/interrupts
@dev:向中断处理函数传递的参数
返回值:成功返回0,失败返回错误码
const void *free_irq(unsigned int irq, void *dev_id)
功能:释放中断
参数:
@irq:软中断号
@dev_id:向中断处理函数传递的参数
返回值:是中断注册时候的第四个参数
1.3中断子系统的设备树添加
1.3.1按键中断的硬件原理图

1.3.2控制器的设备树
stm32mp151.dtsi
gic设备树
intc: interrupt-controller@a0021000 {
compatible = "arm,cortex-a7-gic";
#interrupt-cells = <3>;
interrupt-controller;
reg = <0xa0021000 0x1000>,
<0xa0022000 0x2000>;
};
exti设备树
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
exti: interrupt-controller@5000d000 {
compatible = "st,stm32mp1-exti", "syscon";
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x5000d000 0x400>;
};
};
gpiof的设备树
pinctrl: pin-controller@50002000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,stm32mp157-pinctrl";
interrupt-parent = <&exti>;
gpiof: gpio@50007000 {
interrupt-controller;
#interrupt-cells = <2>;
status = "okay";
};
};
1.3.3参考内核帮助文档,编写自己的设备树
Documentation/devicetree/bindings/interrupt-controller$ vi interrupts.txt
b) two cells
------------
The #interrupt-cells property is set to 2 and the first cell defines the
index of the interrupt within the controller, while the second cell is used
to specify any of the following flags:
- bits[3:0] trigger type and level flags
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive
myirq{
compatilbe = "hqyj,irq";
interrupt-parent = <&gpiof>;
interrupts = <9 0>, <7 0>,<8 0>;
};
1.4按键中断的实例(一个按键)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
// myirq{
// compatilbe = "hqyj,irq";
// interrupt-parent = <&gpiof>;
// interrupts = <9 0>, <7 0>,<8 0>;
// };
struct device_node *node;
unsigned int irqno;
irqreturn_t key_irq(int irq, void *dev)
{
printk("key1 down..........\n");
return IRQ_HANDLED;
}
static int __init myirq_init(void)
{
int ret;
//1.获取到设备树的节点
node = of_find_compatible_node(NULL,NULL,"hqyj,irq");
if(node == NULL){
printk("get node error\n");
return -ENODATA;
}
//2.解析得到软中断号
irqno = irq_of_parse_and_map(node,0);
if(irqno==0){
printk("get irq number error\n");
return -EAGAIN;
}
//3.注册中断
ret = request_irq(irqno,key_irq,IRQF_TRIGGER_FALLING,"keyirq",NULL);
if(ret){
printk("reqest irq error\n");
return ret;
}
return 0;
}
static void __exit myirq_exit(void)
{
free_irq(irqno,NULL);
}
module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");
1.5按键中断的实例(三个按键)
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
// myirq{
// compatilbe = "hqyj,irq";
// interrupt-parent = <&gpiof>;
// interrupts = <9 0>, <7 0>,<8 0>;
// };
struct device_node* node;
unsigned int irqno[3] = {
0 };
char* name[] = {
"key1", "key2", "key3" };
irqreturn_t key_irq(int irq, void* dev)
{
switch ((int)dev) {
case 0:
printk("key1 down..........\n");
break;
case 1:
printk("key2 down..........\n");
break;
case 2:
printk("key3 down..........\n");
break;
}
return IRQ_HANDLED;
}
static int __init myirq_init(void)
{
int ret, i;
// 1.获取到设备树的节点
node = of_find_compatible_node(NULL, NULL, "hqyj,irq");
if (node == NULL) {

最低0.47元/天 解锁文章
753

被折叠的 条评论
为什么被折叠?



