Linux下GPIO驱动(一) 一个简单的LED驱动

/*******************************
 *
 *杂项设备驱动:miscdevice
 *majior=10;
 *
 * *****************************/


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

//#include <linux/moduleparam.h>
//#include <linux/slab.h>//kcalloc,kzalloc等内存分配函数

//---------ioctl------------
#include <linux/ioctl.h>

//---------misc_register----
#include <linux/miscdevice.h>

//----------cdev--------------
#include <linux/cdev.h>

//----------delay-------------
#include <linux/delay.h>

//----------GPIO---------------
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>


#define DEVICE_NAME "leds"

static int led_gpios[] = {
    S5PV210_MP04(4),
    S5PV210_MP04(5),
    S5PV210_MP04(6),
    S5PV210_MP04(7),
};//4个LED

#define LED_NUM        ARRAY_SIZE(led_gpios)


static long fl210_leds_ioctl(struct file *filp, unsigned int cmd,
        unsigned long arg)
{
    switch(cmd) {
        case 0:
        case 1:
            if (arg > LED_NUM) {
                return -EINVAL;
            }

            gpio_set_value(led_gpios[arg], !cmd);//根据cmd设置LED的暗灭
            printk(DEVICE_NAME": %ld %d\n", arg, cmd);
            break;

        default:
            return -EINVAL;
    }

    return 0;
}

static struct file_operations fl210_led_dev_fops = {
    .owner            = THIS_MODULE,
    .unlocked_ioctl    = fl210_leds_ioctl,
};

//----------------miscdevice------------------
static struct miscdevice fl210_led_dev = {
    .minor            = MISC_DYNAMIC_MINOR,
    .name            = DEVICE_NAME,
    .fops            = &fl210_led_dev_fops,
};
//--------------------------------------------


static int __init fl210_led_dev_init(void) {
    int ret;
    int i;

    for (i = 0; i < LED_NUM; i++) {
        ret = gpio_request(led_gpios[i], "LED");//申请GPIO口
        if (ret) {
            printk("%s: request GPIO %d for LED failed, ret = %d\n", DEVICE_NAME,
                    led_gpios[i], ret);
            return ret;
        }

        s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT);//设置GPIO口为输出
        gpio_set_value(led_gpios[i], 1);//初始化GPIO口的值
    }

    ret = misc_register(&fl210_led_dev);//注册杂项设备

    printk(DEVICE_NAME"\tinitialized\n");
    printk("led num is: %d\n",LED_NUM);
    return ret;
}

static void __exit fl210_led_dev_exit(void) {
    int i;

    for (i = 0; i < LED_NUM; i++) {
        gpio_free(led_gpios[i]);//释放GPIO口
    }

    misc_deregister(&fl210_led_dev);//注销设备
}

module_init(fl210_led_dev_init);
module_exit(fl210_led_dev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("");

S5PV210_MP04宏定义在linux/arch/arm/mach-s5pv210/include/mach/gpio.h

#define S5PV210_MP04(_nr) (S5PV210_GPIO_MP04_START + (_nr))

S5PV210_GPIO_MP04_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP03),

#define S5PV210_GPIO_NEXT(__gpio) \ ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)

//这里的CONFIG_S3C_GPIO_SPAC是内核配置选项,在.config中可以找到,我的配置为:   CONFIG_S3C_GPIO_SPACE = 0

上述代码用到以下几个函数:

gpio_set_value();

s3c_gpio_cfgpin();

gpio_request();

gpio_free();

misc_register();

misc_deregister();

后面会逐个分析。

测试程序如下:

#include <stdio.h>
//#include "sys/types.h"
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>//read,write等等
//#include "termios.h"
//#include "sys/stat.h"
#include <fcntl.h>

#define LED2_ON 0x1
#define LED2_OFF 0x0

main(int argc,char *argv[])
{
    int fd;

    if ((fd=open("/dev/leds",O_RDWR /*| O_NDELAY | O_NOCTTY*/)) < 0)
    {
        printf("Open Device  failed.\r\n");
        exit(1);
    }
    else
    {
        printf("Open Device  successed.\r\n");
    }
    if (argc<3)
    {
        /* code */
        printf("Usage: %s <on|off num>\n",argv[0]);
        exit(1);
    }
    if(!strcmp(argv[1],"on"))
    {
        printf("led1 will on!!\n");
       if(ioctl(fd,LED2_ON,atoi(argv[2]))<0)
       {
           printf("ioctl err!!\n");     
       }
    
    }
    if(!strcmp(argv[1],"off"))
    {
        printf("led1 will off!!\n");
        if(ioctl(fd,LED2_OFF,atoi(argv[2]))<0)
        {
            printf("ioctl err!!\n");
        }
    }
    close(fd);
}


 

原文地址:https://www.cnblogs.com/hello2mhb/p/3278657.html