zoukankan      html  css  js  c++  java
  • 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);
    }


     

  • 相关阅读:
    HashMap的负载因子为什么默认是0.75?这篇文章告诉你答案
    如何设计短网址系统?
    前端HTML史上最全总结,入门级边学边实战!
    阿里2021最全新的java面试题总结
    三万字,100题!Linux知识汇总!
    程序员路线图
    基于nodejs的selenium的自动化测试之网络元素
    Electron桌面程序入门研究
    Git常用命令
    二次探测法
  • 原文地址:https://www.cnblogs.com/hello2mhb/p/3278657.html
Copyright © 2011-2022 走看看