linux内核中GPIO的使用(二)--标准接口函数

来源:互联网 发布:穿越火线淘宝网买装备 编辑:程序博客网 时间:2024/04/25 16:43

在linux内核中,有一些基本模块可以使用标准的接口函数来操作,比如GPIO、interrupt、clock,所谓的标准接口函数是指一些与硬件平台无关的、linux下做驱动通用的函数,
常用的有:
gpio_request();gpio_free();gpio_direction_output();gpio_direction_input();gpio_set_value();gpio_get_value()等;

函数分析:

1)GPIO申请:

        int gpio_request(unsigned gpio, const char *label)
参数分析:    unsigned gpio:gpio端口号;    const char *label:给该gpio端口起的名字;返回值:    成功返回0;失败返回负数的错误码;

不同平台的gpio端口号是不同的,比如在s5pv210平台上,在内核源码的arch/arm/mach-s5pv210/include/mach下有一个gpio.h的头文件,其中有:

/* S5PV210 GPIO number definitions */#define S5PV210_GPA0(_nr)       (S5PV210_GPIO_A0_START + (_nr))#define S5PV210_GPA1(_nr)       (S5PV210_GPIO_A1_START + (_nr))#define S5PV210_GPB(_nr)        (S5PV210_GPIO_B_START + (_nr))#define S5PV210_GPC0(_nr)       (S5PV210_GPIO_C0_START + (_nr))#define S5PV210_GPC1(_nr)       (S5PV210_GPIO_C1_START + (_nr))#define S5PV210_GPD0(_nr)       (S5PV210_GPIO_D0_START + (_nr))#define S5PV210_GPD1(_nr)       (S5PV210_GPIO_D1_START + (_nr))…..

例如端口GPJD0_1就对应宏定义的S5PV210_GPD0(1)。

2)GPIO的初始化

        初始化为输出,并设置输出电平:        int gpio_direction_output(unsigned gpio, int value);        初始化为输入:        int gpio_direction_input(unsigned gpio);

3)GPIO的输出电平设置:

        void gpio_set_value(unsigned gpio, int value);

4)得到GPIO的电平

        int gpio_get_value(unsigned gpio);

5)释放GPIO

        void gpio_free(unsigned gpio);

下面做一个简单的led驱动,实现对基于S5PV210平台的4盏LED灯控制,对应的GPIO口为GPJ2_0、GPJ2_0、GPJ2_0、GPJ2_0。

static int __init leddev_init(void){       int ret;/*************led gpio request and initial**************/    int i;    for( i = 0; i < 4; i++)    {        ret = gpio_request(S5PV210_GPJ2(i), "led_gpio");        if(ret < 0)        {            printk("S5PV210_GPJ2(%d)_request error!\n", i);            goto err_gpio_request;        }        gpio_direction_output(S5PV210_GPJ2(i), 1);    }    printk("led initial success!\n");       if(cdev_Major)  //初始值不为0,则手动分配设备号    {        cdev_num = MKDEV(cdev_Major, cdev_Minor);          ret= register_chrdev_region(cdev_num, 1, cdev_name);    }    else    {        ret = alloc_chrdev_region(&cdev_num, cdev_Minor, 1, cdev_name);  //动态分配设备号        cdev_Major = MAJOR(cdev_num);    }    if(ret < 0)    {        printk(KERN_WARNING"can not get major %d\n", cdev_Major);        goto err_leddev_region;    }    cdev_init(&leddev, &leddev_fops);//建立字符设备与文件操作集的联系    gpiodev.owner = THIS_MODULE;            ret = cdev_add(&leddev, cdev_num, 1);    if(ret)    {        printk("error while register device!\n");        goto err_gpiodev_add;    }/******************auto create device file****************/    class_ret = class_create(THIS_MODULE, "ledclass");    if(class_ret == NULL)    {        printk("class_create error!\n");        goto err_class_creat;    }    device_ret = device_create(class_ret, NULL, cdev_num, NULL, "leddev");    if(device_ret == NULL)    {        printk("device_create error!\n");        goto err_device_create;    }    return 0;err_device_create:    class_destroy(class_ret);err_class_creat:        err_leddev_add:    unregister_chrdev_region(MKDEV(cdev_Major, cdev_Minor), 1);err_leddev_region:err_gpio_request:for( ; i > 0; i--)                                  {        gpio_free(S5PV210_GPJ2(i - 1));    }    return ret;}static void __exit leddev_exit(void){    int  i;    printk("exit from leddev!\n");    for(i = 0 ; i < 4; i++)                                  {        gpio_free(S5PV210_GPJ2(i));    }    class_destroy(class_ret);    device_destroy(class_ret, cdev_num);    unregister_chrdev_region(MKDEV(cdev_Major, cdev_Minor), 1);    cdev_del(&leddev);}module_init(leddev_init);module_exit(leddev_exit);MODULE_AUTHOR("Mr.Huang");MODULE_DESCRIPTION("This is a leddev for testing!");MODULE_LICENSE("GPL");
0 0
原创粉丝点击