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

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③

  • 第十八章 Linux系统对中断的处理 ③
    • 18.5 编写使用中断的按键驱动程序 ③
      • 18.5.1 编程思路
        • 18.5.1.1 设备树相关
        • 18.5.1.2 驱动代码相关
      • 18.5.2 先编写驱动程序
        • 18.5.2.1 从设备树获得 GPIO
        • 18.5.2.2 从 GPIO获得中断号
        • 18.5.2.3 申请中断
        • 18.5.2.4 中断函数
    • 18.6 IMX6ULL设备树修改及上机实验
      • 18.6.1 查看原理图确定按键引脚
      • 18.6.2 修改设备树
      • 18.6.3 上机实验

第十八章 Linux系统对中断的处理 ③

在这里插入图片描述

18.5 编写使用中断的按键驱动程序 ③

写在前面的话:对于 GPIO按键,我们并不需要去写驱动程序,使用内核自带的驱动程序drivers/input/keyboard/gpio_keys.c就可以,然后你需要做的只是修改设备树指定引脚及键值。
但是我还是要教你怎么从头写按键驱动,特别是如何使用中断。因为中断是引入其他基础知识的前提,后面要讲的这些内容都离不开中断:休眠-唤醒、POLL机制、异步通知、定时器、中断的线程化处理。
这些基础知识是更复杂的驱动程序的基础要素,以后的复杂驱动也就是对硬件操作的封装彼此不同,但是用到的基础编程知识是一样的。

18.5.1 编程思路

18.5.1.1 设备树相关

查看原理图确定按键使用的引脚,再在设备树中添加节点,在节点里指定中断信息。
例子:

gpio_keys_xxxxxx { compatible = "xxxxxx,gpio_key"; gpios = <&gpio5 1 GPIO_ACTIVE_HIGH &gpio4 14 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&key1_pinctrl &key2_pinctrl>; 
}; 
18.5.1.2 驱动代码相关

首先要获得中断号,参考上面《18.4.3 在代码中获得中断》;
然后编写中断处理函数;
最后 request_irq。

18.5.2 先编写驱动程序

参考:内核源码 drivers/input/keyboard/gpio_keys.c
使用 GIT命令载后,源码 gpio_key_drv.c位于这个目录下: 01_all_series_quickstart\
05_嵌入式 Linux驱动开发基础知识\source\
06_gpio_irq\
01_simple\

18.5.2.1 从设备树获得 GPIO
count = of_gpio_count(node); 
for (i = 0; i < count; i++) gpio_keys_xxxxxx[i].gpio = of_get_gpio_flags(node, i, &flag); 
18.5.2.2 从 GPIO获得中断号
gpio_keys_xxxxxx[i].irq  = gpio_to_irq(gpio_keys_xxxxxx[i].gpio); 
18.5.2.3 申请中断
err = request_irq(gpio_keys_xxxxxx[i].irq, gpio_key_isr, \  
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "xxxxxx_gpio_key", &gpio_keys_xxxxxx[i]); 
18.5.2.4 中断函数
static irqreturn_t gpio_key_isr(int irq, void *dev_id) 
{ struct gpio_key *gpio_key = dev_id; int val; val = gpiod_get_value(gpio_key->gpiod); } 
printk("key %d %d\n", gpio_key->gpio, val); return IRQ_HANDLED; 

18.6 IMX6ULL设备树修改及上机实验

本实验的内核版本:

https://e.coding.net/weidongshan/imx-linux4.9.88 commit 6020a20c1277c6b511e5673eecd8523e376031c8 

18.6.1 查看原理图确定按键引脚

在这里插入图片描述

18.6.2 修改设备树

对于一个引脚要用作中断时,
a. 要通过 PinCtrl把它设置为 GPIO功能;
b. 表明自身:是哪一个 GPIO模块里的哪一个引脚
运行 NXP提供的图形化设备树配置工具“i.MX Pins Tool v6”,点击左侧选中 GPIO5_IO01、GPIO4_IO14,如下图所示:
在这里插入图片描述

按上图右侧去修改设备树 arch/arm/boot/dts/xxxxxx_imx6ull-14x14.dts,修改结果放 GIT中。

使用 GIT命令载后,源码“修改后 xxxxxx_imx6ull-14x14.dts” 位于这个目录下(使用之前要改名为
“xxxxxx_imx6ull-14x14.dts”并上传到内核的 arch/arm/boot/dts目录):

01_all_series_quickstart\ 
05_嵌入式 Linux驱动开发基础知识\source\ 
06_gpio_irq\ 01_simple\ device_tree\ 

主要内容摘录如下:
GPIO5_IO01的 pinctrl定义:

&iomuxc_snvs { pinctrl-names = "default_snvs"; pinctrl-0 = <&pinctrl_hog_2>; imx6ul-evk { key1_xxxxxx: key1_xxxxxx{    /*!< Function assigned for the core: Cortex-A7[ca7] */             fsl,pins = < MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01        0x000110A0 >; }; 
GPIO4_IO14的 pinctrl定义: 
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog_1>; imx6ul-evk { key2_xxxxxx: key2_xxxxxx{  /*!< Function assigned for the core: Cortex-A7[ca7] */             fsl,pins = < MX6UL_PAD_NAND_CE1_B__GPIO4_IO14           0x000010B0 >; }; 
定义这 2个按键的节点: 
gpio_keys_xxxxxx { compatible = "xxxxxx,gpio_key"; gpios = <&gpio5 1 GPIO_ACTIVE_HIGH &gpio4 14 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&key1_xxxxxx &key2_xxxxxx>; }; 

把原来的 GPIO按键节点禁止掉:

gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; status = "disabled";    // 这句是新加的 

18.6.3 上机实验

实验步骤如下:

  1. 编译设备树,把 xxxxxx_imx6ull-14x14.dtb放到板子的/boot目录,重启开发板。
  2. 编译驱动程序,安装驱动程序,操作按键。
    大概命令列出如下:
// 1. 在电脑上设置工具链 
export ARCH=arm 
export CROSS_COMPILE=arm-linux-gnueabihf- 
export PATH=$PATH:/home/book/xxxxxx_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin 
// 2. 进入内核目录后执行: 
make dtbs   // 生成 arch/arm/boot/dts/xxxxxx_imx6ull-14x14.dtb,请把它放到板子的/boot目录 
// 3. 编译驱动: 先进入驱动程序目录,执行 make即可,把生成的 gpio_key_drv.ko放到开发板上 
// 4. 重启开发板后,在板子上执行: 
echo "7 4 1 7" > /proc/sys/kernel/printk insmod gpio_key_drv.ko 
// 5. 按下、松开按键,可以看到输出信息: [   48.396584] key 110 0 
[   48.569403] key 110 1 
[   49.321805] key 129 0 
[   49.498734] key 129 1 

参考资料
中断处理不能嵌套:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e58aa3d2d0cc
genirq: add threaded interrupt handler support
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3aa551c9b4c40018f0e261a178e3d25478dc04a9
Linux RT(2)-硬实时 Linux(RT-Preempt Patch)的中断线程化 https://www.veryarm.com/110619.html
Linux中断管理 (1)Linux中断管理机制
https://www.cnblogs.com/arnoldlu/p/8659981.html

Breakpoint 1, gpio_keys_gpio_isr (irq=200, dev_id=0x863e6930) at drivers/input/keyboard/gpio_keys.c:393 
393 { 
(gdb) bt 
#0  gpio_keys_gpio_isr (irq=200, dev_id=0x863e6930) at drivers/input/keyboard/gpio_keys.c:393 
#1  0x80270528 in __handle_irq_event_percpu (desc=0x8616e300, flags=0x86517edc) at kernel/irq/handle.c:145 
#2  0x802705cc in handle_irq_event_percpu (desc=0x8616e300) at kernel/irq/handle.c:185 
#3  0x80270640 in handle_irq_event (desc=0x8616e300) at kernel/irq/handle.c:202 
#4  0x802738e8 in handle_level_irq (desc=0x8616e300) at kernel/irq/chip.c:518 
#5  0x8026f7f8 in generic_handle_irq_desc (desc=<optimized out>) at ./include/linux/irqdesc.h:150 
#6  generic_handle_irq (irq=<optimized out>) at kernel/irq/irqdesc.c:590 
#7  0x805005e0 in mxc_gpio_irq_handler (port=0xc8, irq_stat=2252237104) at drivers/gpio/gpio-mxc.c:274 
#8  0x805006fc in mx3_gpio_irq_handler (desc=<optimized out>) at drivers/gpio/gpio-mxc.c:291 
#9  0x8026f7f8 in generic_handle_irq_desc (desc=<optimized out>) at ./include/linux/irqdesc.h:150 
#10 generic_handle_irq (irq=<optimized out>) at kernel/irq/irqdesc.c:590 
#11 0x8026fd0c in __handle_domain_irq (domain=0x86006000, hwirq=32, lookup=true, regs=0x86517fb0) at kernel/irq/irqdesc.c:627 
#12 0x80201484 in handle_domain_irq (regs=<optimized out>, hwirq=<optimized out>, domain=<optimized out>) at ./include/linux/irqdesc.h:168 
#13 gic_handle_irq (regs=0xc8) at drivers/irqchip/irq-gic.c:364 
#14 0x8020b704 in __irq_usr () at arch/arm/kernel/entry-armv.S:464 
http://www.lryc.cn/news/180202.html

相关文章:

  • 【Python】返回指定时间对应的时间戳
  • 微服务moleculer03
  • [React] react-router-dom的v5和v6
  • Linux命令(91)之mv
  • C++ 强制类型转换(int double)、查看数据类型、自动决定类型、三元表达式、取反、
  • Android自动化测试之MonkeyRunner--从环境构建、参数讲解、脚本制作到实战技巧
  • Neural Insights for Digital Marketing Content Design 阅读笔记
  • BI神器Power Query(26)-- 使用PQ实现表格多列转换(2/3)
  • 中间件中使用到的设计模式
  • 运用动态内存实现通讯录(增删查改+排序)
  • 基于Cplex的人员排班问题建模求解(JavaAPI)
  • 理解Go中的数据类型
  • 【人工智能导论】线性回归模型
  • 十大常见排序算法详解(附Java代码实现和代码解析)
  • 在Ubuntu上通过Portainer部署微服务项目
  • 软件测试基础学习
  • 移动手机截图,读取图片尺寸
  • 服务器应用程序不可用的原因是什么引起的
  • 使用SPY++查看窗口信息去排查客户端UI软件问题
  • Flink CDC MySQL同步MySQL错误记录
  • 深入了解 Linux 中的 AWK 命令:文本处理的瑞士军刀
  • 【RuoYi项目分析】网关的AuthFilter完成“认证”,注意是认证而不是权限
  • excel将文件夹下面的表格文件指定名称的sheet批量导出到指定文件中,并按照文件名保存在新文件的不同sheet中
  • IIS管理器无法打开。启动后,在任务栏中有,但是窗口不见了
  • 使用VBA实现快速模糊查询数据
  • spring boot flowable多人前加签
  • 结构体运算符重载
  • 幽默直观的文档作者注释
  • 前端开发网站推荐
  • 【C语言】通讯录管理系统(保姆级教程+内含源码)