最近用到gpio中断,gpio中断也是嵌入式系统用的比较多的。

对于GPIO操作 linux 有一套标准的 API,set value、get value之类的,当然也有关于中断的。

关于中断的就是:

static inline int gpio_to_irq(unsigned int gpio)

{

return __gpio_to_irq(gpio);

}

1 使用gpio中断

在linux模块中使用gpio中断的步骤通常如下

1)实现中断处理函数。

static irqreturn_t myIntHandler(int irq, void *dev_id)

{

printk("Interrupt IN\n");

return IRQ_HANDLED

}

2)初始化函数

int xxx_init()

{

int ret, irqno;

ret = gpio_request(gpioNo, "mygpiopin");

if(ret){

printk("irq pin request io failed.\n");

return -1;

}

irqno= gpio_to_irq(gpioNo);

ret = request_irq(irqno,myIntHandler , RQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "myinterrupt", NULL);

if(ret) {

printk(KERN_ERR "can not get irq\n");

return ret;

}

}就两个函数:

gpio_request  通常用来检测这个gpio是否可用,是否已经在使用了。

gpio_to_irq 转换gpio编号到对应irq号。

之后就是熟悉的request_irq

有时候还会加一个gpio_is_valid,判断一下gpioNo是否合理,通常自己察看芯片手册填入正确gpio number,不需要再再在这里判断一下。

2,gpio中断API的实现过程

简单看一下。

int gpio_request(unsigned gpio, const char *label)

{

return gpiod_request(gpio_to_desc(gpio), label);

}

先看参数

gpio_to_desc(gpio)

都在gpiolib.c中

static struct gpio_desc *gpio_to_desc(unsigned gpio)

{

if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))

return NULL;

else

return &gpio_desc[gpio];

}

这里有个全局的数组,看样子是每一个gpio都在这个数组里有这么一项,这个结构体如下

struct gpio_desc {

struct gpio_chip*chip;

unsigned longflags;

/* flag symbols are bit numbers */

#define FLAG_REQUESTED0

#define FLAG_IS_OUT1

#define FLAG_EXPORT2/* protected by sysfs_lock */

#define FLAG_SYSFS3/* exported via /sys/class/gpio/control */

#define FLAG_TRIG_FALL4/* trigger on falling edge */

#define FLAG_TRIG_RISE5/* trigger on rising edge */

#define FLAG_ACTIVE_LOW6/* sysfs value has active low */

#define FLAG_OPEN_DRAIN7/* Gpio is open drain type */

#define FLAG_OPEN_SOURCE 8/* Gpio is open source type */

#define ID_SHIFT16/* add new flags before this one */

#define GPIO_FLAGS_MASK((1 << ID_SHIFT) - 1)

#define GPIO_TRIGGER_MASK(BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))

#ifdef CONFIG_DEBUG_FS

const char*label;

#endif

};主要就是有个 struct gpio_chip类型的指针

回到gpiod_request,其他代码先忽略,主要就两句,就是我加注释的地方

static int gpiod_request(struct gpio_desc *desc, const char *label)

{

struct gpio_chip*chip;

intstatus = -EPROBE_DEFER;

unsigned longflags;

if (!desc) {

pr_warn("%s: invalid GPIO\n", __func__);

return -EINVAL;

}

spin_lock_irqsave(&gpio_lock, flags);

chip = desc->chip;//取得desc中的struct gpio_chip.

if (chip == NULL)

goto done;

if (!try_module_get(chip->owner))

goto done;

/* NOTE: gpio_request() can be called in early boot,

* before IRQs are enabled, for non-sleeping (SOC) GPIOs.

*/

if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {

desc_set_label(desc, label ? : "?");

status = 0;

} else {

status = -EBUSY;

module_put(chip->owner);

goto done;

}

if (chip->request) {

/* chip->request may sleep */

spin_unlock_irqrestore(&gpio_lock, flags);

status = chip->request(chip, gpio_chip_hwgpio(desc));//调用desc[gpio]-〉chip-〉request

spin_lock_irqsave(&gpio_lock, flags);

if (status < 0) {

desc_set_label(desc, NULL);

module_put(chip->owner);

clear_bit(FLAG_REQUESTED, &desc->flags);

goto done;

}

}

if (chip->get_direction) {

/* chip->get_direction may sleep */

spin_unlock_irqrestore(&gpio_lock, flags);

gpiod_get_direction(desc);

spin_lock_irqsave(&gpio_lock, flags);

}

done:

if (status)

pr_debug("_gpio_request: gpio-%d (%s) status %d\n",

desc_to_gpio(desc), label ? : "?", status);

spin_unlock_irqrestore(&gpio_lock, flags);

return status;

}

chip-〉request有两个参数,一个是chip另一个是

/*

* Return the GPIO number of the passed descriptor relative to its chip

*/

static int gpio_chip_hwgpio(const struct gpio_desc *desc)

{

return desc - &desc->chip->desc[0];

}

看注释也很清楚,gpio号相对于它的chip的偏移。 看来这个struct gpio_chip非常重要,看看这个chip是在哪里赋值到gpio_desc[]这个数组的。

/**

* gpiochip_add() - register a gpio_chip

* @chip: the chip to register, with chip->base initialized

* Context: potentially before irqs or kmalloc will work

*

* Returns a negative errno if the chip can't be registered, such as

* because the chip->base is invalid or already associated with a

* different chip. Otherwise it returns zero as a success code.

*

* When gpiochip_add() is called very early during boot, so that GPIOs

* can be freely used, the chip->dev device must be registered before

* the gpio framework's arch_initcall(). Otherwise sysfs initialization

* for GPIOs will fail rudely.

*

* If chip->base is negative, this requests dynamic assignment of

* a range of valid GPIOs.

*/

int gpiochip_add(struct gpio_chip *chip)

{

..........略

if (status == 0) {

chip->desc = &gpio_desc[chip->base];

for (id = 0; id < chip->ngpio; id++) {

struct gpio_desc *desc = &chip->desc[id];

desc->chip = chip;

/* REVISIT: most hardware initializes GPIOs as

* inputs (often with pullups enabled) so power

* usage is minimized. Linux code should set the

* gpio direction first thing; but until it does,

* and in case chip->get_direction is not set,

* we may expose the wrong direction in sysfs.

*/

desc->flags = !chip->direction_input

? (1 << FLAG_IS_OUT)

: 0;

}

}

..............略

}

在这个函数里面全局数组gpio_desc被一一赋值了。

而这个gpiochip_add会在底层芯片厂商各自的gpio初始化函数里调用。 位置通常在各厂商各自的gpio-xxx.c

struct gpio_chip也会在那里定义,通常与硬件寄存器相关,不做分析。

gpio_request完了,还有gpio_to_irq,其实是一样的,还是最终会调用,stuct gpio_chip中的to_irq。

反过来说bsp的编写者,初始化之后,只要实现stuct gpio_chip 再调用gpiochip_add,gpio的API就可以供用户使用了。

linux 应用层gpio中断_linux gpio中断相关推荐

  1. 上下文保存 中断_Linux内核中断顶半部和底半部的理解

    @[toc] 中断上半部.下半部的概念   设备的中断会打断内核进程中的正常调度和运行,系统对更高吞吐率的追求势必要求中断服务程序尽量短小精悍.但是,这个良好的愿望往往与现实并不吻合.在大多数真实的系 ...

  2. linux 应用层gpio中断_树莓派官方自带gpio中断驱动bcm2708_gpio.c原理分析 linux 中断架构 中断子系统...

    上一篇记录了树莓派自带的gpio驱动(外链网址已屏蔽),在bcm2708_gpio.c实现gpio驱动的同时其实也实现了中断控制器的驱动,本文记录bcm2708_gpio.c中驱动的实现. 一·bcm ...

  3. ARM(IMX6U)ARM Cortex-A7中断系统(GPIO按键中断驱动蜂鸣器)

    参考:Linux之ARM Cortex-A7 中断系统详解 作者:一只青木呀 发布时间: 2020-09-16 16:07:22 网址:https://blog.csdn.net/weixin_453 ...

  4. LPC1768外部中断与GPIO中断

    LPC1768的外部中断严格来说只有四个,分别是EINT0,EINT1,EINT2,EINT3,技术手册上有如下说明 控制这四个外部中断靠以下寄存器 这三个寄存器的0 1 2 3位分别代表中断的0 1 ...

  5. SDK应用二:S32DS开发环境使用SDK编辑工程代码实例(S32K142配置时钟,中断,GPIO)

    以如下工程为例:涉及到时钟,中断,GPIO,CAN通信,LIN通信,串口通信,IIC通信:为能方便读者快速入门使用SDK,文中写的不详细的地方,直接复制了一下帖子链接,如有侵权,请尽快联系: 第一步: ...

  6. Linux嵌入式驱动开发07——GPIO驱动过程记录(飞凌开发板)

    文章目录 全系列传送门 1. 在/arch/arm/boot/dts/imx6q-pinfunc.h查找 2. 在设备树配置文件中添加设备节点定义以及其引脚定义 3. 修改设备树文件添加配置 4. d ...

  7. Linux内核驱动之GPIO子系统(一)GPIO的使用

    一 概述 Linux内核中gpio是最简单,最常用的资源(和 interrupt ,dma,timer一样)驱动程序,应用程序都能够通过相应的接口使用gpio,gpio使用0-MAX_INT之间的整数 ...

  8. Linux内核4.14版本——GPIO子系统(1)——gpiolib分析

    目录 1.简述 2.Gpiolib 相关数据结构分析 2.1 gpio_chip 结构 2.2 gpio_desc 结构 2.3 gpio_device 结构 3 Gpiolib 对接芯片底层 3.1 ...

  9. linux 在某个core上的中断 affinity c语言函数,Linux中断处理体系结构

    各种的异常的C处理函数可以分为5类,他们分布在不同的文件中. 1.在arch/arm/kernel/trapsc.c中 未定义指令异常,总入口函数为do_undefinstr. 2.在arch/arm ...

最新文章

  1. 基于oracle的数据系统,基于Oracle 的数据库系统
  2. python错误提示:TypeError: ‘builtin_function_or_method‘ object is not subscriptable
  3. python编程入门课程视频-带学《Python编程:从入门到实践》
  4. LeetCode Array Partition I
  5. 浏览器打开html文件显示中文乱码解决方法
  6. MySQL--数据库基础
  7. springboot创建项目(通过spring官网)详细
  8. 论文浅尝 - AAAI2020 | 通过句子级语义匹配和答案位置推断改善问题生成
  9. 《程序员代码面试指南》第二章 链表问题 删除无序链表中值重复的链表
  10. sql server 2005 T-SQL BACKUP CERTIFICATE (Transact-SQL)
  11. 找不到php fpm.pid,找不到文件nginx php-fpm
  12. 网络克隆自动修改计算机名ip,GHOST网克专用IP及计算机名自动修改器
  13. 非域环境下安装并配置Project Server 2007(二)
  14. 廖雪峰Git教程学习总结
  15. 导航条UINavigtionBar,标签栏UITabBarController,抽屉MMDrawerController
  16. go vender 的环境搭建和使用
  17. easyui的datagrid可编辑框小功能实例
  18. Wormhole网站
  19. Vue项目中常见问题(55)提交订单、获取订单号、展示支付信息
  20. 路在脚下【心情转帖】

热门文章

  1. matlab 存mat文件,matlab中mat文件简单存/取
  2. 数据库可用于左右填充0的函数--->LPAD与RPAD
  3. 精选12个时尚的 CSS3 效果【附源码下载】
  4. Linux中使用RAID技术提升磁盘读写速度及数据安全
  5. 贴片电阻封装和功率的的关系
  6. mysql 转为小写_mysql将字符串转成小写的方法
  7. IOS应用程序自身的本地化
  8. 注意力机制(一):注意力提示、注意力汇聚、Nadaraya-Watson 核回归
  9. Java多线程之wait(),notify(),notifyAll()
  10. 以太网适配器 以太网:_在关键任务共享以太网适配器上管理VLAN