嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十四)Linux系统对中断的处理(下)

简介: 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十四)Linux系统对中断的处理

1.4.1.2 设备树里使用中断


一个外设,它的中断信号接到哪个“中断控制器”的哪个“中断引脚”,这个中断的触发方式是怎样的?

这3个问题,在设备树里使用中断时,都要有所体现。


① interrupt-parent=<&XXXX>

你要用哪一个中断控制器里的中断?

② interrupts

你要用哪一个中断?

Interrupts里要用几个cell,由interrupt-parent对应的中断控制器决定。在中断控制器里有“#interrupt-cells”属性,它指明了要用几个cell来描述中断。

比如:

i2c@7000c000 {
  gpioext: gpio-adnp@41 {
  compatible = "ad,gpio-adnp";
  interrupt-parent = <&gpio>;
  interrupts = <160 1>;
  gpio-controller;
  #gpio-cells = <1>;
  interrupt-controller;
  #interrupt-cells = <2>;
  };
......
};


③ 新写法:interrupts-extended

一个“interrupts-extended”属性就可以既指定“interrupt-parent”,也指定“interrupts”,比如:

interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;


1.4.2 设备树里中断节点的示例


以100ASK_IMX6ULL开发板为例,在arch/arm/boot/dts目录下可以看到2个文件:imx6ull.dtsi、100ask_imx6ull-14x14.dts,把里面有关中断的部分内容抽取出来。

1670923538261.jpg

从设备树反推IMX6ULL的中断体系,如下,比之前的框图多了一个“GPC INTC”:

1670923555570.jpg

GPC INTC的英文是:General Power Controller, Interrupt Controller。它提供中断屏蔽、中断状态查询功能,实际上这些功能在GIC里也实现了,个人觉得有点多余。除此之外,它还提供唤醒功能,这才是保留它的原因。


1.4.3 在代码中获得中断


之前我们提到过,设备树中的节点有些能被转换为内核里的platform_device,有些不能,回顾如下:

A. 根节点下含有compatile属性的子节点,会转换为platform_device

B. 含有特定compatile属性的节点的子节点,会转换为platform_device

如果一个节点的compatile属性,它的值是这4者之一:“simple-bus”,“simple-mfd”,“isa”,“arm,amba-bus”,

那么它的子结点(需含compatile属性)也可以转换为platform_device。

C. 总线I2C、SPI节点下的子节点:不转换为platform_device

某个总线下到子节点,应该交给对应的总线驱动程序来处理, 它们不应该被转换为platform_device。


1.4.3.1 对于platform_device


一个节点能被转换为platform_device,如果它的设备树里指定了中断属性,那么可以从platform_device中获得“中断资源”,函数如下,可以使用下列函数获得IORESOURCE_IRQ资源,即中断号:

/**
 * platform_get_resource - get a resource for a device
 * @dev: platform device
 * @type: resource type   // 取哪类资源?IORESOURCE_MEM、IORESOURCE_REG
*                      // IORESOURCE_IRQ等
 * @num: resource index  // 这类资源中的哪一个?
 */
struct resource *platform_get_resource(struct platform_device *dev,
           unsigned int type, unsigned int num);


1.4.3.2 对于I2C设备、SPI设备


对于I2C设备节点,I2C总线驱动在处理设备树里的I2C子节点时,也会处理其中的中断信息。一个I2C设备会被转换为一个i2c_client结构体,中断号会保存在i2c_client的irq成员里,代码如下(drivers/i2c/i2c-core.c):

1670923620556.jpg

对于SPI设备节点,SPI总线驱动在处理设备树里的SPI子节点时,也会处理其中的中断信息。一个SPI设备会被转换为一个spi_device结构体,中断号会保存在spi_device的irq成员里,代码如下(drivers/spi/spi.c):

1670923629702.jpg


1.4.3.3 调用of_irq_get获得中断号


如果你的设备节点既不能转换为platform_device,它也不是I2C设备,不是SPI设备,那么在驱动程序中可以自行调用of_irq_get函数去解析设备树,得到中断号。


1.4.3.4 对于GPIO


参考:drivers/input/keyboard/gpio_keys.c

可以使用gpio_to_irq或gpiod_to_irq获得中断号。

举例,假设在设备树中有如下节点:

gpio-keys {
  compatible = "gpio-keys";
  pinctrl-names = "default";
  user {
    label = "User Button";
    gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
    gpio-key,wakeup;
    linux,code = <KEY_1>;
  };
};


那么可以使用下面的函数获得引脚和flag:

button->gpio = of_get_gpio_flags(pp, 0, &flags);
bdata->gpiod = gpio_to_desc(button->gpio);


再去使用gpiod_to_irq获得中断号:

irq = gpiod_to_irq(bdata->gpiod);


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


写在前面的话:对于GPIO按键,我们并不需要去写驱动程序,使用内核自带的驱动程序drivers/input/keyboard/gpio_keys.c就可以,然后你需要做的只是修改设备树指定引脚及键值。

但是我还是要教你怎么从头写按键驱动,特别是如何使用中断。因为中断是引入其他基础知识的前提,后面要讲的这些内容都离不开中断:休眠-唤醒、POLL机制、异步通知、定时器、中断的线程化处理。

这些基础知识是更复杂的驱动程序的基础要素,以后的复杂驱动也就是对硬件操作的封装彼此不同,但是用到的基础编程知识是一样的。


1.5.1 编程思路


1.5.1.1 设备树相关


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

例子:

gpio_keys_100ask {
  compatible = "100ask,gpio_key";
  gpios = <&gpio5 1 GPIO_ACTIVE_HIGH
    &gpio4 14 GPIO_ACTIVE_HIGH>;
  pinctrl-names = "default";
  pinctrl-0 = <&key1_pinctrl
     &key2_pinctrl>;
};


1.5.1.2 驱动代码相关


首先要获得中断号,参考上面《18.4.3 在代码中获得中断》;

然后编写中断处理函数;

最后request_irq。


1.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\


1.5.2.1 从设备树获得GPIO


count = of_gpio_count(node);
for (i = 0; i < count; i++)
    gpio_keys_100ask[i].gpio = of_get_gpio_flags(node, i, &flag);


1.5.2.2 从GPIO获得中断号


gpio_keys_100ask[i].irq  = gpio_to_irq(gpio_keys_100ask[i].gpio);


1.5.2.3 申请中断

err = request_irq(gpio_keys_100ask[i].irq, gpio_key_isr, \ 
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "100ask_gpio_key", &gpio_keys_100ask[i]);


1.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;
}


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


本实验的内核版本:

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

commit 6020a20c1277c6b511e5673eecd8523e376031c8


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

1670923747820.jpg


1.6.2 修改设备树


对于一个引脚要用作中断时,

a. 要通过PinCtrl把它设置为GPIO功能;

b. 表明自身:是哪一个GPIO模块里的哪一个引脚

运行NXP提供的图形化设备树配置工具“i.MX Pins Tool v6”,点击左侧选中GPIO5_IO01、GPIO4_IO14,如下图所示:

1670923756427.jpg

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

使用GIT命令载后,源码“修改后100ask_imx6ull-14x14.dts” 位于这个目录下(使用之前要改名为“100ask_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_100ask: key1_100ask{    /*!< 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_100ask: key2_100ask{  /*!< Function assigned for the core: Cortex-A7[ca7] */
            fsl,pins = <
                MX6UL_PAD_NAND_CE1_B__GPIO4_IO14           0x000010B0
            >;
        };


定义这2个按键的节点:

gpio_keys_100ask {
    compatible = "100ask,gpio_key";
    gpios = <&gpio5 1 GPIO_ACTIVE_HIGH
             &gpio4 14 GPIO_ACTIVE_LOW>;
    pinctrl-names = "default";
    pinctrl-0 = <&key1_100ask &key2_100ask>;
};


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

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


1.6.3 上机实验


实验步骤如下:


编译设备树,把100ask_imx6ull-14x14.dtb放到板子的/boot目录,重启开发板。

编译驱动程序,安装驱动程序,操作按键。

大概命令列出如下:

// 1. 在电脑上设置工具链
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin
// 2. 进入内核目录后执行:
make dtbs   // 生成 arch/arm/boot/dts/100ask_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
相关文章
|
9月前
|
定位技术 开发工具
【HarmonyOS】鸿蒙应用实现调用系统地图导航或路径规划
【HarmonyOS】鸿蒙应用实现调用系统地图导航或路径规划
515 5
【HarmonyOS】鸿蒙应用实现调用系统地图导航或路径规划
|
10月前
|
Linux 编译器 Android开发
鸿蒙系统被抹黑的深层解析:技术、商业与地缘政治的复杂博弈-优雅草卓伊凡
鸿蒙系统被抹黑的深层解析:技术、商业与地缘政治的复杂博弈-优雅草卓伊凡
573 1
鸿蒙系统被抹黑的深层解析:技术、商业与地缘政治的复杂博弈-优雅草卓伊凡
|
9月前
|
安全 开发工具 数据安全/隐私保护
HarmonyOS应用安全全攻略:从系统到代码的全面防护
本文全面解析HarmonyOS应用安全开发,涵盖系统到代码的防护策略。首先介绍HarmonyOS三层安全体系:系统安全层、开发工具层与应用生态层。接着详解设备与数据安全等级划分,提供分级加密实战代码,包括文件读写与HUKS高级加密案例。最后总结开发最佳实践,强调数据分类、最小权限、加密常态及传输安全保障,助你构建更安全的应用。保护用户数据不仅是功能需求,更是开发者责任!
|
7月前
|
移动开发 网络协议 小程序
鸿蒙NEXT即时通讯/IM系统RinbowTalk v2.4版发布,基于MobileIMSDK框架、ArkTS编写
RainbowTalk是一套基于开源即时通讯讯IM框架 MobileIMSDK 的产品级鸿蒙NEXT端IM系统。纯ArkTS编写、全新开发,没有套壳、也没走捷径,每一行代码都够“纯血”。与姊妹产品RainbowChat和RainbowChat-Web 技术同源,历经考验。
327 1
|
8月前
|
缓存 移动开发 网络协议
纯血鸿蒙NEXT即时通讯/IM系统:RinbowTalk正式发布,全源码、纯ArkTS编写
RainbowTalk是一套基于MobileIMSDK的产品级鸿蒙NEXT端IM系统,目前已正式发布。纯ArkTS、从零编写,无套壳、没走捷径,每一行代码都够“纯”(详见:《RainbowTalk详细介绍》)。 MobileIMSDK是一整套开源IM即时通讯框架,历经10年,超轻量级、高度提炼,一套API优雅支持 UDP 、TCP 、WebSocket 三种协议,支持 iOS、Android、H5、标准Java、小程序、Uniapp、鸿蒙NEXT,服务端基于Netty编写。
649 1
|
11月前
|
安全 Linux 测试技术
对鸿蒙 Next 系统“成熟论”的深度剖析-优雅草卓伊凡
对鸿蒙 Next 系统“成熟论”的深度剖析-优雅草卓伊凡
245 10
对鸿蒙 Next 系统“成熟论”的深度剖析-优雅草卓伊凡
|
11月前
|
人工智能 物联网 Android开发
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
596 23
【03】优雅草星云物联网AI智控系统从0开发鸿蒙端适配-deveco studio-在lib目录新建自定义库UtilsLibrary,ComponentLibrary,CommonConstLibrary完成设置SettingsView.ets初始公共类书写-优雅草卓伊凡
|
10月前
|
人工智能 运维 监控
HarmonyOS NEXT~鸿蒙系统运维:全面解析与最佳实践
本书《HarmonyOS NEXT~鸿蒙系统运维:全面解析与最佳实践》深入探讨了鸿蒙系统的运维管理。从架构特点到实际操作,涵盖分布式能力、性能优化、安全维护及故障排查。内容包括设备管理、系统监控、安全管理等核心任务,提供常见问题解决方案与工具推荐。面对未来超级终端和AI赋能的挑战,运维人员需不断学习,以充分发挥鸿蒙的分布式优势,为用户带来流畅体验。
795 8
|
9月前
|
开发工具 数据安全/隐私保护 开发者
打造鸿蒙系统中最好用的加载动画和提示弹窗
幽蓝君开发了鸿蒙平台的轻量级弹窗工具 yloadinghud,旨在实现简洁优雅的提示交互。无需在每个页面重复初始化,只需一行代码即可展示加载动画或提示弹窗。支持多种类型,如成功、失败提示及文字弹窗,且具备自动消失功能,使用便捷。项目已上传至 ohpm 仓库,欢迎搜索体验并提出宝贵建议。#三方SDK #工具效率
|
10月前
|
JavaScript 前端开发 Java
HarmonyOS NEXT~鸿蒙系统下的Cordova框架应用开发指南
《HarmonyOS NEXT:鸿蒙系统下的Cordova框架应用开发指南》详细介绍如何将Cordova应用适配到鸿蒙系统。文章涵盖兼容性分析、环境配置、特性适配、性能优化及发布调试等内容。尽管Cordova官方暂无直接支持,但通过Cordova-Android平台与定制插件可实现功能扩展。开发者需注意性能差异,并借助插件机制融入鸿蒙特色功能,如服务卡片和分布式能力。未来,随着鸿蒙生态完善,Cordova在该平台的应用将更加广泛且高效。
904 1

热门文章

最新文章