Hi3531 GPIO驱动中断示例

易百纳用户79822 2017-11-15 11:09:58 5217

对于海思的GPIO分组深恶痛绝,而且根据我的实际测试GPIO_RIS寄存器说明还写反了。测试代码用的是边沿触发,电平触发测试了始终有问题,在保持某电平(高或低)中断会一直触发很头疼清除了中断寄存器GPIO_IC也不行!!!!

约定GPIO号,对其分组形式做了一层处理以下是公式:
*gpio = base8+offset*
base:组号 ,offset:偏移
例如:GPIO15_2得到的GPIO号就是15
8+2=122
测试代码如下:


#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/fs.h>  
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>

#define DEBUG

#ifdef DEBUG
# define PRINTK(fmt, arg...)  printk(fmt, ##arg)
#else
# define PRINTK(fmt, arg...)  do {} while(0)
#endif

#define GPIO_15_BASE   0x20240000       //for GPIO15
#define GPIO_DATA(o)   IO_ADDRESS(GPIO_15_BASE + (1<<(o+2)))
#define GPIO_DIR       IO_ADDRESS(GPIO_15_BASE + 0x400)
#define GPIO_IS        IO_ADDRESS(GPIO_15_BASE + 0x404)
#define GPIO_IBE       IO_ADDRESS(GPIO_15_BASE + 0x408)
#define GPIO_IEV       IO_ADDRESS(GPIO_15_BASE + 0x40C)
#define GPIO_IE        IO_ADDRESS(GPIO_15_BASE + 0x410)      
#define GPIO_RIS       IO_ADDRESS(GPIO_15_BASE + 0x414)     
#define GPIO_MIS       IO_ADDRESS(GPIO_15_BASE + 0x418)      
#define GPIO_IC        IO_ADDRESS(GPIO_15_BASE + 0x41C)     
#define GPIO_AFSEL     IO_ADDRESS(GPIO_15_BASE + 0x420)      

#define GPIO_15_2       122
#define GPIO_15_3       123
#define GPIO_IRQ            116

struct gpc_dev {
    spinlock_t      lock; 
    struct miscdevice *misc_dev;
};

struct miscdevice this_misc =   
{  
    .minor  =   MISC_DYNAMIC_MINOR,  
    .name   =   "higpio",  
    .nodename = "higpio"  
};  

struct gpc_dev dev = 
{
    .misc_dev = &this_misc,
};

static int gpio_offset(int gpio, int *offset)
{
    if(offset)
        *offset = gpio%8;
    return 0;   
}

static int get_value(int gpio)
{
    int offset; 
    if(gpio_offset(gpio, &offset) !=0)
        return -1;

    return readl(GPIO_DATA(offset)) & (1<<offset)? 1 : 0;
}

static int gpio_input(int gpio)
{
    u32 value;
    int offset;

    if(gpio_offset(gpio, &offset) !=0)
        return -1;

    spin_lock(&dev.lock);

    value = readl(GPIO_DIR);
    value &= ~(1<<offset);
    writel(value, GPIO_DIR);

    spin_unlock(&dev.lock);

    return 0;
}

static int regs_set_gpio_irq_type(int gpio, unsigned int trigger)
{
    u32 value, val;
    unsigned long flags;
    int offset;

    if(gpio_offset(gpio, &offset) !=0 )
        return -1;

    spin_lock_irqsave(&dev.lock,flags);

    value = readl(GPIO_IS);
    if (trigger & (IRQ_TYPE&#95;LEVEL_HIGH | IRQ_TYPE&#95;LEVEL_LOW)) {
        value |= (1<<offset);
         PRINTK("trigger is level\n");
    }
    else { 
        value &= ~(1<<offset);
         PRINTK("trigger is edge\n");
    }
    writel(value, GPIO_IS);

    value = readl(GPIO_IBE);
    if ((trigger & IRQF_TRIGGER_RISING) && (trigger & IRQ_TYPE&#95;EDGE&#95;FALLING)) {
        value |= (1<<offset);
        PRINTK("trigger both\n");
    }
    else {
        value &= ~(1<<offset);
        val = readl(GPIO_IEV);
        if( trigger & (IRQ_TYPE&#95;LEVEL_LOW  | IRQ_TYPE&#95;EDGE&#95;FALLING))
            val &= ~(1<<offset);
        else
            val |= (1<<offset);
        writel(val, GPIO_IEV);
    }
    writel(value, GPIO_IBE);

    spin_unlock_irqrestore(&dev.lock, flags);
    return 0;
}

static int regs_enable&#95;gpio_irq(int gpio)
{
    u32 value;
    unsigned long flags;
    int offset;

    if(gpio_offset(gpio, &offset) !=0 )
        return-1;

    spin_lock_irqsave(&dev.lock,flags);

    writel(0xff, GPIO_IC);

    value = readl(GPIO_IE);
    value |= (1<<offset);
    writel(value, GPIO_IE);

    spin_unlock_irqrestore(&dev.lock, flags);
    return 0;
}

static void regs_clean_gpio_irq(int gpio)
{
    int offset;
    u32 value;

    if(gpio_offset(gpio, &offset) !=0 )
        return ;
    value = readl(GPIO_IC);
    value |=(1<<offset);
    writel(value, GPIO_IC);
}

static void regs_disable&#95;gpio_irq(int gpio)
{
    u32 value;
    unsigned long flags;
    int offset;

    if(gpio_offset(gpio, &offset) !=0 )
        return;

    spin_lock_irqsave(&dev.lock,flags);
    value = readl(GPIO_IE);
    value &= ~(1<<offset);
    writel(value, GPIO_IE);
    spin_unlock_irqrestore(&dev.lock, flags);
}

static irqreturn_t this_irq_handler(int irq, void* dev_id)
{
    u32 value;
    int i, gpio=120;

    value = readl(GPIO_RIS);

    PRINTK(KERN_NOTICE "gpio:irq=%d, value=%xn",irq, value);

    for(i=0;  i<8; i++) {
        if(value & 0x1){ 
                gpio += i;
                break;
        }
        else {
                value=value>>1;
       }
    }           
    PRINTK(KERN_NOTICE "gpio:gpio=%d\n",gpio);
    regs_clean_gpio_irq(gpio);

    return IRQ_HANDLED;
}

static int this_enable&#95;irq(void)
{
        int err = 0;
        gpio_input(GPIO_15_2);    //设置GPIO_15_2为输入
        gpio_input(GPIO_15_3);
        regs_set_gpio_irq_type(GPIO_15_2, IRQ_TYPE&#95;EDGE&#95;FALLING|IRQF_TRIGGER_RISING);  //设置为单边沿的下降沿出发
        regs_set_gpio_irq_type(GPIO_15_3, IRQ_TYPE&#95;EDGE&#95;FALLING|IRQF_TRIGGER_RISING); //设置为单边沿的下降沿出发
        regs_enable&#95;gpio_irq(GPIO_15_2);      //使能GPIO中断
        regs_enable&#95;gpio_irq(GPIO_15_3);    //使能GPIO中断
        err = request_irq(GPIO_IRQ, this_irq_handler, 0, "higpio", NULL);
        if (err != 0) {
            PRINTK(KERN_ERR "gpc: failed to request irq, err: %d\n", err);
            err = -EBUSY;
        }   
    return err;
}

static void this_disable&#95;irq(void)
{
        regs_disable&#95;gpio_irq(GPIO_15_2);
        regs_disable&#95;gpio_irq(GPIO_15_3);
        free&#95;irq(GPIO_IRQ, NULL);
}

static int __init gpio_init(void)
{
    int err;

    if(this_enable&#95;irq() !=0)
        return -EBUSY;

    spin_lock_init(&dev.lock);
    err = misc_register(dev.misc_dev); 
    return err;
}

static void __exit gpio_exit(void)
{
    this_disable&#95;irq();
    misc_deregister(dev.misc_dev);  
}

module&#95;init(gpio_init);
module&#95;exit(gpio_exit);

MODULE&#95;AUTHOR("GoodMan<2757364047@qq.com>");
MODULE&#95;LICENSE("Dual BSD/GPL");
MODULE&#95;VERSION("V1.00");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
<
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
关于作者
易百纳用户79822

易百纳用户79822

暂无个性签名~

原创18
阅读9.2w
收藏8
点赞23
评论12
打赏用户 0
我要创作
分享技术经验,可获取创作收益
分类专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
易百纳用户79822
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区