文章标题

这几天,在调试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的返回值,内核就会报告上述错误,并在该中断出现一定次数后关闭该中断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值