Smart210学习记录(四) 之LED驱动


 
 
 

前言

  经过几天的学习,终于linux驱动的基本框架弄清楚了。。。真的很艰辛,,,不过终于还是熬过来了,虽然还是最基础的,,,今晚也完成了我第一个linux驱动,,,心里还是有点小兴奋的,哈哈O(∩_∩)O
 

一、驱动程序

LED 驱动没有什么好讲的,主要是把设备驱动框架弄清楚就可以了。这里直接上驱动源码。
我的开发板是Smart210,根据原理图,IO口输出0 led亮,输出1 led灭

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/delay.h>
   
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>


  #define DEVICE_NAME "leds"
  
  /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
  /*the second parameter that application program execute*/
  #define IOCTL_GPIO_ON         1
  #define IOCTL_GPIO_OFF        0
  
  /* 用来指定LED所用的GPIO引脚 */
  /*appoint the pin the LED will use*/
  static unsigned long leds_table [] =
  {
          S5PV210_GPJ2(0),
          S5PV210_GPJ2(1),
          S5PV210_GPJ2(2),
          S5PV210_GPJ2(3),
          //arch\arm\mach-s5pv210\include\mach\gpio.h
  };
  
  static char leds_name[][4]={{"LED1"},{"LED2"},{"LED2"},{"LED3"}};
  #define LED_NUM                ARRAY_SIZE(leds_table)


   /**
  *函数功能:打开/dev/led设备
  *fuction:open /dev/leds device
  *设备名是:/dev/leds
  *devce name: /dev/leds
  **/
  static int my_led_open(struct inode *inode, struct file *file)
  {
       int i;
       int err;
   
       for (i = 0; i < LED_NUM; i++)
       {
           err = gpio_request(leds_table[i], leds_name[i]);
                      //drivers/gpio/gpiolib.c
           if(err)
           {
              printk(KERN_ERR "failed to request S5PV210_GPH2(%d) for LED%d \n",i-1,i);
              return err;
           }
       }
   
       for (i = 0; i < LED_NUM; i++)
       {
         s3c_gpio_cfgpin(leds_table[i], S3C_GPIO_OUTPUT);//Configuration pin function:input output multiplex
         gpio_set_value(leds_table[i], 1);//Set the pin level
          //arch\arm\plat-samsung\gpio-config.c
//          gpio_direction_output(leds_table[i], 0);//write a value to GPIO port ,also set the port to output mode
//          gpio_set_value(leds_table[i], 0);
          //drivers/gpio/gpiolib.c
   
       }
      printk(KERN_INFO "LEDs driver successfully close\n");
       return 0;
  }


 static long my_led_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
    arg -= 1;
    if(arg > LED_NUM) {
        return -EINVAL;
    }

    switch(cmd) {
        case IOCTL_GPIO_ON:
            printk("led light\n");
            gpio_set_value(leds_table[arg], 0);
        break;

        case IOCTL_GPIO_OFF:
            printk("led no light\n");
            gpio_set_value(leds_table[arg], 1);
        break;

        default:
            printk("led failed\n");
            return -EINVAL;
    }
    return 0;
 }

 static int my_led_close(struct inode * inode,struct file * file)
 {
     int i;
    for(i= 0; i < LED_NUM; i++)
        gpio_free(leds_table[i]);
    printk(KERN_EMERG"close success\n");
    return 0;
 }

struct file_operations my_led_ops = {
    .owner = THIS_MODULE,
    .open  = my_led_open,
    .unlocked_ioctl = my_led_ioctl,
    .release = my_led_close,
};


static struct miscdevice led_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops  = &my_led_ops,
};


static int __init my_led_init(void)
{
    int ret;

    ret = misc_register(&led_misc);
    if(ret) {
        printk(KERN_INFO"misc_register failed\n");
    }

    printk(KERN_INFO"misc_register sucessed\n");
    
    return 0;
}


static void __exit my_led_exit(void) {
    int i;
    misc_deregister(&led_misc);
    for(i= 0; i < LED_NUM; i++)
        gpio_free(leds_table[i]);
    printk(KERN_INFO "LEDs driver successfully exit\n");
}

module_init(my_led_init);
module_exit(my_led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("qigaohua");

 

二、应用程序

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>

#define IOCTL_GPIO_ON           1
#define IOCTL_GPIO_OFF          0



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

    fd = open("/dev/leds",0);
    if(fd < 0) {
        printf("/dev/leds open failed\n");
        exit(1);
    }


    
    do {
        printf("/dev/leds open sucessed\n");
        ioctl(fd, IOCTL_GPIO_ON, 1);
        ioctl(fd, IOCTL_GPIO_OFF, 2);
        ioctl(fd, IOCTL_GPIO_OFF, 3);
        ioctl(fd, IOCTL_GPIO_OFF, 4);
        sleep(1);

        ioctl(fd, IOCTL_GPIO_ON, 1);
        ioctl(fd, IOCTL_GPIO_ON, 2);
        ioctl(fd, IOCTL_GPIO_OFF, 3);
        ioctl(fd, IOCTL_GPIO_OFF, 4);        
        sleep(1);

        ioctl(fd, IOCTL_GPIO_ON, 1);
        ioctl(fd, IOCTL_GPIO_ON, 2);
        ioctl(fd, IOCTL_GPIO_ON, 3);
        ioctl(fd, IOCTL_GPIO_OFF, 4);        
        sleep(1);

        ioctl(fd, IOCTL_GPIO_ON, 1);
        ioctl(fd, IOCTL_GPIO_ON, 2);
        ioctl(fd, IOCTL_GPIO_ON, 3);
        ioctl(fd, IOCTL_GPIO_ON, 4);        
        sleep(1);


        ioctl(fd, IOCTL_GPIO_OFF, 1);
        ioctl(fd, IOCTL_GPIO_OFF, 2);
        ioctl(fd, IOCTL_GPIO_OFF, 3);
        ioctl(fd, IOCTL_GPIO_OFF, 4);
    }while(0);

    close(fd);
    return 0;

}

 

三、实例测试

经过测试OK

 
 
 
 
 
 
 
关注公众号"小败日记",搬砖过程遇到的问题,大家一起探讨,资源共享

小败日记公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值