您的位置:首页 > 其它

文章标题

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的返回值,内核就会报告上述错误,并在该中断出现一定次数后关闭该中断。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: