arm GPIO访问规则

1、简介

开发板裸机开发需要自己按照数据手册自己计算每个gpio的偏移,以实现相应功能,如上拉,第二功能等。
linux为开发者提供了一套统一的方法,方便开发。

1.1 gpio申请与释放函数

想要使用gpio需要先申请,申请成功才能使用。这些头文件定义在内核文件的”include/linux/gpio.h”中。

//申请io 成功返回0 失败返回错误码
static inline int gpio_request(unsigned gpio, const char *label)
gpio:需要申请的gpio号,一般是gpio的宏定义
label:为申请的gpio取的名字,方便阅读
//释放gpio
static inline void gpio_free(unsigned gpio)
gpio:申请成功的gpio 
//检测此gpio口是否有效                           
static inline bool gpio_is_valid(int number) 

//设置为输入
int gpio_direction_input(unsigned gpio);       
//设置为输出,并初始化值为value.               
int gpio_direction_output(unsigned gpio, int value);   

获取/设置gpio值:    int gpio_cansleep(unsigned gpio); 
a.不可睡眠: 
//返回value
gpio_get_value(unsigned gpio);   
//设置值                           
gpio_set_value(unsigned gpio, int value);                    
b.可睡眠:(对于有些挂载在I2C,SPI总线上的扩展GPIO,读写操作可能会导致睡眠,因此不能在中断函数中使用。使用下面的函数以区别于正常的GPIO)
//输入端口:返回零或非零,可能睡眠
int gpio_get_value_cansleep(unsigned gpio);   
//输出端口:可能睡眠               
void gpio_set_value_cansleep(unsigned gpio, int value); 

批量初始化方法:
//申请:
err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
//释放:
gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));

Gpio设置中断:
//首先应该设置此gpio为输入状态,然后获取对应的中断号(或错误码)。返回编号调用:request_irq()和free_irq()。
static inline int gpio_to_irq(unsigned gpio)
//返回gpio编号,再调用gpio_get_value()获取相应的值。(避免使用反向映射,不支持)
static inline int irq_to_gpio(unsigned irq)
1.2 参数宏定义

GPIO 宏定义文件都是由原厂提供,一般位置在”arch/arm(cpu架构)/mach-exynos(cpu型号)/include/mach/gpio-exynos4.h(具体的文件)”

主要用宏定义了gpio的地址
如:
gpioA的地址为 0xE0031080
使用宏定义成了 GPA 以后直接使用GPA即可

1.3 配置函数

主要是对gpio口的配置操作,如上拉,中断触发条件等。
位置定义在”arch/arm(cpu架构)/plat-samsung(平台)/include/plat/gpio-cfg.h”

//设置上拉、下拉
int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);
//配置管脚是输入、输出、第二功能
int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);
//配置为中断
int s5p_register_gpio_interrupt(int pin);
1.4 中断

主要是外部中断的申请与释放

#include <linux/interrupt.h>
//申请中断
static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
irq:中断号,与平台架构相关;可以通过gpio_to_irq映射
handler:用户中断处理函数;
flags:一个或多个中断标记
IRQF_DISABLED, 用于保证中断不被打断和嵌套
IRQF_SHARED, 申请子中断时,共享中断源
IRQF_SAMPLE_RANDOM, 表示对系统熵有贡献,对系统获取随
机数有好处
devname:中断名字,可以通过 cat /proc/interrupts 查看;
dev_id:在 free_irq 中有用,也用做区分中断处理函数

//中断处理函数
irqreturn_t (*handler)(int, void *, struct pt_regs *)

//设置中断触发方式(外部中断)
int set_irq_type(int irq, int edge);
irq:中断号
edge:外部中断触发方式定义在linux/irq.h
IRQ_TYPE_LEVEL_LOW,
IRQ_TYPE_LEVEL_HIGH,
IRQ_TYPE_EDGE_FALLING,
IRQ_TYPE_EDGE_RISING,
IRQ_TYPE_EDGE_BOTH

//释放中断
void free_irq(unsigned int irq, void *dev_id)
irq:中断号,与 request_irq 中的 irq 一致,用于定位 action 链表;
dev_id:用于在 action 链表中找到要卸载的表项;同一个中断的不同中断处理函数必须使用不同的dev_id来区分,这就要求在注册中断共享时参数 dev_id 必须唯一。

//使能中断
void enable_irq(unsigned int irq);

//关闭中断,并等待中断处理完成后返回
void disable_irq(unsigned int irq);
注意:当用户在中断处理函数中使用该函数会形成死锁

//关闭中断,立即返回
void disable_irq_nosync(unsigned int irq);

2、demo itop4412按键中断例子

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>

#include <linux/interrupt.h>
#include <linux/irq.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>

#define DEMO_DEBUG
#ifdef  DEMO_DEBUG
#define dem_dbg(fmt, arg...)        printk(KERN_WARNING fmt, ##arg)
#else
#define dem_dbg(fmt, arg...)        printk(KERN_DEBUG fmt, ##arg)
#endif
//中断回调
static irqreturn_t eint9_interrupt(int irq, void *dev_id) {
    printk("%s(%d)\n", __FUNCTION__, __LINE__);

    return IRQ_HANDLED;
}

static dev_t dev_id;
static unsigned int irq;
static int demo_open (struct inode *pnode, struct file *filp)
{
    int ret;

    dev_id = MKDEV(imajor(pnode), iminor(pnode));
    //申请gpio
    ret = gpio_request(EXYNOS4_GPX1(1), "EINT9");
    if (ret) {
        printk("request EINT9 failed, ret = %d", ret);
        return ret;
    }
    //设置gpio为第二功能引脚 即中断
    s3c_gpio_cfgpin(EXYNOS4_GPX1(1), S3C_GPIO_SFN(0xF));
    //上拉
    s3c_gpio_setpull(EXYNOS4_GPX1(1), S3C_GPIO_PULL_UP);
    //释放gpio
    gpio_free(EXYNOS4_GPX1(1));

    //将GPX1_1映射为中断
    irq = gpio_to_irq(EXYNOS4_GPX1(1));
    //申请中断
    ret = request_irq(irq, eint9_interrupt,
            IRQ_TYPE_EDGE_FALLING /*IRQF_TRIGGER_FALLING*/, "eint9", (void *)&dev_id);
    if (ret < 0) {
        printk("Request IRQ %d failed, %d\n", IRQ_EINT(9), ret);
        goto exit;
    }

exit:
    free_irq(IRQ_EINT(9), (void *)&dev_id);
    return 0;
}

static ssize_t demo_read (struct file *filp, char __user *buf, size_t count, loff_t *offp)
{
    return 0;   
}

static int demo_release (struct inode *pnode, struct file *filp)
{
    printk("==>demo_release\n");
    free_irq(irq, (void *)&dev_id);
    return 0;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = demo_open,
    .read = demo_read,
    .release = demo_release,
};  

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .fops = &fops,
    .name = "demo0",
};

static int __init demo_init(void)
{   
    int res;
    dem_dbg("==>demo_init\n");

    res = misc_register(&misc);
    if(res < 0){
        dem_dbg("register misc device failed!\n");
        return -EFAULT;
    }

    return 0;
}

static void __exit demo_exit(void)
{
    dem_dbg("==>demo_exit\n");

    misc_deregister(&misc);

}

module_init(demo_init);
module_exit(demo_exit);


MODULE_LICENSE("Dual BSD/GPL");
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
rv1126是一款集成了大量通用输入输出(GPIO)接口的应用处理器。GPIO是一种常见的外部设备接口,用于与各种外设进行通信和控制。rv1126应用访问GPIO的过程如下: 首先,应用程序需要通过操作系统提供的API或库函数来访问rv1126的GPIO接口。它可以通过打开特定的GPIO设备节点来获取对GPIO接口的访问权限。 接下来,应用程序可以使用读写操作来读取或控制GPIO接口的状态。例如,可以使用读操作来获取GPIO输入引脚的状态,或使用写操作来设置GPIO输出引脚的电平。 为了方便应用程序对GPIO接口的访问,通常还会提供一些API函数或库来封装对底层GPIO接口的操作,使得应用程序可以更方便地进行GPIO的配置和操作。 在访问GPIO接口时,需要注意以下几点: 1. 设置正确的GPIO模式:GPIO接口通常支持输入和输出模式,应用程序需要根据需要设置正确的模式。 2. 设置正确的引脚状态:对于输出模式的GPIO引脚,需要设置正确的电平(高电平或低电平),以控制外部设备的状态。对于输入模式的GPIO引脚,通常需要设置上拉或下拉电阻,以保证引脚在无输入信号时的默认状态。 3. 避免冲突:不同的GPIO引脚可能有不同的功能或用途,应用程序需要避免在同一时间对不同功能的GPIO引脚进行操作,以避免冲突。 总之,rv1126应用访问GPIO的过程是通过操作系统提供的API或库函数进行的,通过打开设备节点来获取对GPIO接口的访问权限,并使用读写操作来读取或控制GPIO接口的状态。合理设置GPIO模式和引脚状态,避免冲突是使用rv1126应用访问GPIO的重要注意事项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值