文章标题
2015-08-12 18:35
561 查看
这几天,在调试A20的GPIO终端功能,发现并不像LINUX2.6的内核函数那样简单,遇到了一些问题,希望在这里能够帮助许多朋友少走弯路。 1.中断函数的选择:sw_gpio_irq_request()还是request_irq()呢? 下面来看一段代码,这是A20 Plat库中的函数,主要完成中断请求的一些功能,如中断使能,中断方式等。
u32 sw_gpio_irq_request(u32 gpio, enum gpio_eint_trigtype trig_type,
peint_handle handle, void *para)
{
int irq_no = 0;
int irq_ret = 0;
struct gpio_config_eint_all cfg = {0};
struct gpio_irq_handle *pdev_id = NULL;
PIO_DBG("%s: gpio %d, trig %d, handle 0x%08x, para 0x%08x\n", __func__, gpio, trig_type, (u32)handle, (u32)para); WARN(NULL == handle, "%s: NULL handle\n", __func__); if (false == is_gpio_canbe_eint(gpio)) { PIO_ERR("%s: gpio %d can not be eint\n", __func__, gpio); return 0; } /* config to eint, enable the eint, and set pull, drivel level, trig type */ cfg.gpio = gpio; cfg.pull = GPIO_PULL_DEFAULT; cfg.drvlvl = GPIO_DRVLVL_DEFAULT; cfg.enabled = 0; cfg.trig_type = trig_type; if (sw_gpio_eint_setall_range(&cfg, 1)) { PIO_ERR("%s: gpio %d eint set all range failed\n", __func__, gpio); return 0; } /* request irq */ pdev_id = (struct gpio_irq_handle *)kmalloc(sizeof(struct gpio_irq_handle), GFP_KERNEL); if (NULL == pdev_id) { PIO_ERR("%s: alloc memory for gpio irq handle failed\n", __func__); return 0; } pdev_id->gpio = gpio; pdev_id->handler = handle; pdev_id->parg = para; irq_no = __gpio_to_irq(gpio); PIO_DBG("%s: __gpio_to_irq return %d\n", __func__, irq_no); irq_ret = request_irq(irq_no, gpio_irq_hdl, IRQF_DISABLED | IRQF_SHARED, "gpio_irq", (void *)pdev_id); if (irq_ret) { PIO_ERR("%s: request_irq failed\n", __func__); kfree(pdev_id); return 0; } if (sw_gpio_eint_set_enable(gpio, 1)) { PIO_ERR("%s: sw_gpio_eint_set_enable failed\n", __func__); free_irq(irq_no, (void *)pdev_id); kfree(pdev_id); return 0; } return (u32)pdev_id;
}
下面我们来看最重要的一个函数,irq_ret = request_irq(irq_no, gpio_irq_hdl, IRQF_DISABLED | IRQF_SHARED, “gpio_irq”, (void *)pdev_id);
这个函数就主要完成了中断号的请求功能。
irq_no:通过__gpio_to_irq(gpio)来获取
gpio_irq_hdl:这是个自定义的结构体指针,指向具体的回调函数和其他的定义。
IRQF_DISABLED:表示屏蔽其他的中断,并快速执行完中断程序
IRQF_SHARED:表示与其他的中断共享此中断号
pdev_id:传递私有指针头
所以,最终还是选择这个函数来完成中断的申请。其中需要特别注意的是中断函数的入口参数只有一个pdev_id,出口返回值必须为0;
2.错误记录:
2.1 Unable to handle kernel NULL pointer dereference at virtual address 00000018,主要是由于指针传递错误导致的。
2.2nobody cared…..
主要是当一个中断号上有多个中断共享的时候,该中断来的时候,内核会依次调用共享该中断号的各个中断处理函数,如果中断处理函数检测到该中断不是自己的中断时就会返回IRQ_NONE,这时内核就会调用下一个中断处理函数,而这些中断处理函数中必须至少有一个返回IRQ_HANDLED告知内核该中断是自己的中断,已经正常处理,若内核依次调用完所有该中断号的中断处理函数仍未得到IRQ_HANDLED的返回值,内核就会报告上述错误,并在该中断出现一定次数后关闭该中断。
相关文章推荐
- 关于树莓派的一些事
- C++对象模型——"无继承"情况下的对象构造(第五章)
- 试用log4jdbc
- eclipse编译数学函数库
- Min Stack
- 在O(1)时间删除链表结点
- wordpress 使用误区
- 自关联去掉组内重复数据
- IE 兼容模式下不支持DIV CSS样式display:inline-block,解决
- not in\in与not exists\exists—SQLCookbook
- Problem K: 二进制表示中1的个数
- OData - ASP.NET Web API 2 中Odata路由约定
- 读书笔记-APUE第三版-(10)信号
- Web安全测试之跨站请求伪造(CSRF)
- 【读书笔记】iOS-截屏功能的实现。
- 深入理解Java异常
- hdu 1228 A + B 详细题解 字符串/哈希
- nginx的数据结构集合(随时更新)
- MyEclipse UTF-8环境设置
- 黑马学习笔记_Java 反射技术