key-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; /\* KEY0 \*/
interrupt-parent = <&gpio1>;
interrupts = <18 IRQ_TYPE_EDGE_BOTH>; /\* FALLING RISING \*/
status = "okay"
}
在这个例子中, 我们先使用 pinctrl 和 gpio 子系统把这个引脚设置为了 gpio 功能, 因为在使用中断的时候需要把引脚设置成输入。然后使用 interrupt-parent 和 interrupts 属性来描述中断。 interrupt-parent 的属性值是 gpio1,也就是要使用 gpio1这个中断控制器, 为什么是 gpio1 呢,因为引脚使用的是 gpio1 里面的io18,所以使用的是gpio1这个中断控制器。interrupts 属性设置的是中断源,为什么里面是俩个cells 呢, 因为在 gpio1 这个中断控制器里面#interrupt-cells 的值为 2, 如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/93fb9df620a24178a4b2a8688ca0bbcd.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qKF5bGx5YmR5a6i,size_20,color_FFFFFF,t_70,g_se,x_16)
例子中的第一个 cells 的 18 表示 GPIO1 组的 18 号 IO。 IRQ\_TYPE\_EDGE\_BOTH 表示 上升沿和下降沿同时有效。 IRQ\_TYPE\_EDGE\_BOTH 定义在文件 include/linux/irq.h 中, 定义如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/3891dd053349418c8b4e6366d7e38103.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qKF5bGx5YmR5a6i,size_20,color_FFFFFF,t_70,g_se,x_16)
所以在设备树里面配置中断的时候只需要俩个步骤即可, 第一个步骤是把管脚设置为 gpio 功能。 第二个步骤是使用 interrupt-parent 和 interrupts 属性来描述中断。
#### 二. 中断相关函数
<1>获取中断号相关函数
编写驱动的时候需要用到中断号,每一个中断都有中断号, 用到中断号,中断信息已经写到了设备树里面, 因此可以通过 irq\_of\_parse\_and\_map 函数从 interupts 属性中提取到对应的设备号,函数原型如下:
unsigned int irq_of_parse_and_map(struct device_node *dev,int index)
参数: dev 设备节点。
index: 索引号,interrupts 属性可能包含多条中断信息,通过 index 指定要获取的信息。
返回值: 中断号。
如果使用 GPIO 的话,可以使用 gpio\_to\_irq 函数来获取 gpio 对应的中断号,函数原型如下:
int gpio_to_irq(unsigned int gpio)
参数: gpio: 要获取的 GPIO 编号。
返回值: GPIO 对应的中断号。
<2>申请中断函数 同 GPIO 一样,在 Linux 内核里面,如果要使用某个中断也是需要申请的,申请中断使用的函数是 request\_irq函数原型:
int request_irq( unsigned int irq, i rq_handler_t handler, unsigned long flags, const char *name, void *dev)
参数:
irq:要申请中断的中断号。
handler:中断处理函数,当中断发生以后就会执行此中断处理函数。
flags:中断标志。
中断标识可以在文件 include/linux/interrupt.h 里面查看所有的中断标志, 介绍几个常用的中断标志,如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/9d97c973ee1e4cb5a65cbf4db68d3358.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qKF5bGx5YmR5a6i,size_20,color_FFFFFF,t_70,g_se,x_16)name: 中断名字,设置以后可以在/proc/interrupts 文件中看到对应的中断名字。
dev: 如果将 flags 设置为 IRQF\_SHARED 的话, dev 用来区分不同的中断, 一 般 情 况 下将 dev 设置为设备 结构体,dev会传递给中断处理函数 irq\_handler\_t 的第二个参数。
返回值:0 中断申请成功, 其他负值中断申请失败,如果返回-EBUSY的话表示中断已经被申请了。
< 3 > 中断处理函数
使用 request\_irq 函数申请中断的时候需要设置中断处理函数, 中断处理函数 格式 如下所示:第一个参数是要中断处理函数要相应的中断号。 第二个参数是一个指 向 void 的指 针 ,也就是个通用 指 针 , 需要 与 request\_irq 函数的 dev 参数 保持 一 致 。 用于区分 共享 中断的不同设备, dev 也可以指 向 设备数 据结构 。 中断处理函数的返回值为 i rqreturn\_t 类 型, irqreturn\_t 类 型定义如下所示:
enum irqreturn {
IRQ_NONE = (0 << 0),
IRQ_HANDLED = (1 << 0),
IRQ_WAKE_THREAD = (1 << 1),
};
typedef enum irqreturn irqreturn_t;
可以看 出 irqreturn \_t 是个枚举类 型, 一共 有三种返回值。一般中断服务函数返回值使用如下 形式 :
< 4 >free\_irq 函数
中断使用完成以后就要通过 free\_irq 函数释放掉相应的中断。如果中断不是共享 的,那么 free\_irq 会删除中断处理函数并且禁止中断。free\_irq 函数原型如下所示:
void free_irq(unsigned int irq,void *dev)
参数:
irq:要释放的中断。
dev: 如果中断设置为 共享( IRQF\_SHARED ) 的话, 此参数用来区分具体的中断。共享中断只有在 释放最 后中断处理函数的时候才会被禁止掉。
返回值: 无
#### 按键中断实验
包含头文件
#include <linux/interrupt.h>
修改设备树信息
test_key{
compatible = “keys”;
pinctrl-names = “default”;
pintrl-0=<&pinctrl_gpio_keys>;//通过宏 把管脚设置为gpio功能
gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
}
修改驱动匹配函数
const struct of_device_id of_match_table[] =
{
{.compatible = “keys”},
{},
};
在beep\_probe添加如下的代码:
int beep_probe(struct platform_device *pdev){
/\*查找我们要查找的节点\*/
test_device_node = of\_find\_node\_by\_path("/test\_key");
if (test_device_node == NULL)
{
printk("of\_find\_by\_path is erron\n");
return -1;
} //获取gpio的节点
gpio_num = of\_get\_named\_gpio(test_device_node,"gpios",0);//获取gpio
if (gpio_num<0)
{
printk("of\_get\_named\_gpio is erron\n");
return -1;
}
gpio\_direction\_input(gpio_num);//设置方向为输入
irq = gpio\_to\_irq(gpio_num);//获取中断号
printk("irq is %d\n", irq);
ret = request\_irq(irq,test_key,IRQF_TRIGGER_RISING,"test\_key",NULL);
if (ret<0)
{
printk("request\_irq is erron\n");
return -1;
}
return 0;
}
烧入驱动:cat /proc/interrupts 查看中断是否加载完成。
cat /proc/irq/48/spurious 查看中断次数。
#### 方法2:修改设备树代码
驱动设备树代码:
test_key{
compatible = “keys”;
pinctrl-names = “default”;
pintrl-0=<&pinctrl_gpio_keys>;//通过宏 把管脚设置为gpio功能
gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
//方法2 :在设备树上修改代码
interrupt-parent = <&gpio1>;
interrupts =<18 IRQ_TYPE_EDGE_BOTH>;/*FALLING RISING*/
}
包含头文件
#include<linux/of_irq.h>
驱动代码:
int beep_probe(struct platform_device *pdev){
/\*查找我们要查找的节点\*/
test_device_node = of\_find\_node\_by\_path("/test\_key");
if (test_device_node == NULL)
{
printk("of\_find\_by\_path is erron\n");
return -1;
} //获取gpio的节点
/\*获取GPIO的编号\*/
gpio_num = of\_get\_named\_gpio(test_device_node,"gpios",0);//获取gpio
if (gpio_num<0)
{
printk("of\_get\_named\_gpio is erron\n");
return -1;
}
/\*设置gpio的方向\*/
gpio\_direction\_input(gpio_num);//设置方向为输入
//irq = gpio\_to\_irq(gpio\_num);//获取中断号
/\*获取irq的编号\*/
irq = irq\_of\_parse\_and\_map(test_device_node,0);//第二种获取中断号的方式,索引号为0
printk("irq is %d\n", irq);
/\*申请中断\*/
ret = request\_irq(irq,test_key,IRQF_TRIGGER_RISING,"test\_key",NULL);
if (ret<0)
{
printk("request\_irq is erron\n");
return -1;
}
return 0;
}
#### 中断下文之tasklet
#### 一、tasklet 相关知识点
1、什么是 tasklet ?
tasklet 是中断处理中断下文常用的一种方法,tasklet 是一种特殊的软中断。 处理中断下文的机制还有工作队列和软中断。
2、怎么使用 tasklet 来设计中断下文?
框图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/9e56c0f905214a2b92e4fd9c54d27d5b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qKF5bGx5YmR5a6i,size_17,color_FFFFFF,t_70,g_se,x_16)
Linux 把中断分成俩个部分,一个是上半部分,一个是下半部分,在上半部分我们只 处理紧急的事情,同时可以调用 tasklet 来启动中断下文,比较耗时间的就要放到下文来 处理,调用 tasklet 以后, tasklet 绑定的函数并不会立马执行,而是出中断以后,经过一 个很短的不确定时间在来执行。
3、tasklet 定义
tasklet 由 tasklet\_struct 结构表示,每个结构体单独代表一个 tasklet , 在<linux/interrupt.h> 中定义为:
struct tasklet_struct {
struct tasklet_struct *next;
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!
-1715840826412)]
[外链图片转存中…(img-yf5e6nYq-1715840826413)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!