led驱动

驱动步骤:

1、驱动框架:一般读驱动代码需要module_init一层层找代码


2、硬件配置

代码中led_ioctl函数设置引脚的电平高低,该函数是驱动程序对设备的通道进行统一设置/控制的函数

一、  在用户空间,使用ioctl系统调用来控制设备,原型如下:

    int ioctl(int fd,unsigned long cmd,...);
  fd:文件描述符  cmd:控制命令  ...:可选参数:插入*argp,具体内容依赖于cmd用户程序所作的只是通过命令码告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情
二、驱动ioctl方法:int (*ioctl) (struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);/*inode与filp两个指针对应于应用程序传递的文件描述符fd,这和传递open方法的参数一样。cmd 由用户空间直接不经修改的传递给驱动程序arg 可选。*/在驱动程序中实现的ioctl函数体内,实际上是有一个switch {case}结构,每一个case对应一个命令码,做出一些相应的操作。怎么实现这些操作,这是每一个程序员自己的事情,因为设备都是特定的。关键在于怎么样组织命令码,因为在ioctl中命令码是唯一联系用户程序命令和驱动程序支持的途径。

  用户使用  int ioctl(int fd,unsinged long cmd,...)  时,...就是要传递的参数;
  再通过  int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long  arg)  中的arg传递;不同颜色代表对应的参数

现阶段能够理解成每一个用户程序的ioctl对应其内核中的一个ioctl函数,且参数需要用户层传递给驱动层 (该例中)

代码很简单 :

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#define DEVICE_NAME "myled"   /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
static struct class *leds_class;
static struct class *led_dev_class;
int major;

/* 用来指定LED所用的GPIO引脚 */
static unsigned long led_table[]={

    S3C2410_GPF5,
    S3C2410_GPF6,

};

/* 用来指定GPIO引脚的功能:输出 */
static unsigned int led_cfg_table [] = {

    S3C2410_GPF5_OUTP,
    S3C2410_GPF6_OUTP,
};

/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define LED_ON    0
#define LED_OFF   1
/* 应用程序对设备文件/dev/leds执行open(...)时,
 * 就会调用s3c24xx_leds_open函数
 */
static int led_open (struct inode *inode, struct file *filep)
{
    int i;
    // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能
     for (i = 0; i <2; i++) {
        // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能
        s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
    }
    return 0;
}
static int led_ioctl(
    struct inode *inode,
    struct file *file,
    unsigned int cmd,
    unsigned long arg)
{

    if (arg > 2) {
        return -EINVAL;
    }
     switch(cmd) {
         case LED_ON:
        // 设置指定引脚的输出电平为0
        s3c2410_gpio_setpin(led_table[arg], 0);
        return 0;
        case LED_OFF:
        // 设置指定引脚的输出电平为1
        s3c2410_gpio_setpin(led_table[arg], 1);
        return 0;
          default:
        return -EINVAL;
    }
}
/* 这个结构是字符设备驱动程序的核心
 * 当应用程序操作设备文件时所调用的open、read、write等函数,
 * 最终会调用这个结构中指定的对应函数
 */
static struct file_operations led_ops=
{
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   = led_open,
    .ioctl  = led_ioctl ,

}; 

/*
 * 执行insmod命令时就会调用这个函数
 */

static int led_init(void)
{
    int ret;
    /* 注册字符设备
     * 参数为主设备号、设备名字、file_operations结构;
     * 这样,主设备号就和具体的file_operations结构联系起来了,
     * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数
     * LED_MAJOR可以设为0,表示由内核自动分配主设备号
     */
     major = register_chrdev(0, DEVICE_NAME, &led_ops);
      if (major < 0)
      {
      printk(DEVICE_NAME  " can‘t register major number number::%d\n",major);
      return ret;
      }
    printk(DEVICE_NAME " initialized1\n");
    leds_class = class_create(THIS_MODULE, "leds");
    if (IS_ERR(leds_class))
        return PTR_ERR(leds_class);
    led_dev_class = class_device_create(leds_class, NULL, MKDEV(major, 0), NULL, "perled"); /* /dev/leds */
    return 0;

}

/*
 * 执行rmmod命令时就会调用这个函数
 */
static void led_exit(void)
{
    class_device_unregister(led_dev_class, MKDEV(major, 0));
    class_destroy(leds_class);
     /* 卸载驱动程序 */
    unregister_chrdev(major, DEVICE_NAME);

}

module_init(led_init);
module_exit(led_exit);  

MODULE_AUTHOR("http://www.100ask.net");
MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver");
MODULE_LICENSE("GPL");  

make

insmod XXX.ko

测试代码(应用程序代码):

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */
#define IOCTL_LED_ON    0
#define IOCTL_LED_OFF   1
/*
  *  ledtest <dev> <on|off>
  */

void print_usage(char *file)
{
    printf("Usage:\n");
    printf("./a.out 1 on\n");
}

int main(int argc,char**argv)
{
    int fd;
    int ret;
    int led_NO;
    char val;
    if(argc!=3)
    {

        printf("error USAGE\n");
        exit(1);
    }
  //1、打开设备
    fd = open("/dev/perled",O_RDWR);
    led_NO=strtoul(argv[1],0,0)-1;//确定LED
    if(fd<0)
    {
        perror("open fail \n");
        return -1;
    }
   if (!strcmp("on", argv[2]))
    {
        // 亮灯
       ioctl(fd,IOCTL_LED_ON,led_NO);// 设备 亮灭 那个led、
    }
    else if (!strcmp("off", argv[2]))
    {
        // 灭灯
        ioctl(fd,IOCTL_LED_OFF,led_NO);
    }
    else
    {
        print_usage(argv[0]);
        return 0;
    }

    close(fd);
    return 0;
}
/// //   // / //./a.out 1 on

ioctl:http://www.cnblogs.com/geneil/archive/2011/12/04/2275372.html

时间: 2024-08-10 21:19:11

led驱动的相关文章

第7章:LED驱动的实现原理

本章完成了一个真正意义上的 Linux 驱动.该 Linux 驱动用来控 制开发版上的 4个 LED 小灯.也就是说通过向 Linux 驱动发送数据可以控制 LED 小灯的开关.为 了方便称呼这个驱动,本书及后面的章节都将其称为 LED 驱动. 虽然 LED 驱动并不复杂,只是控制 了 4个 LED,"但 LED 驱动已经包括了 Linux 驱动所有必要的部分 一个完整的 Linux 驱动主要由 内部处理和与硬件交互降部分组成.其中内部处理主要是指 Linux 驱动的装载.卸载.与设备文件 相关

基于S3C2440的linux-3.6.6移植——LED驱动【转】

本文转载自:http://www.voidcn.com/blog/lqxandroid2012/article/p-625005.html 目前的linux版本的许多驱动都是基于设备模型,LED也不例外. 简单地说,设备模型就是系统认为所有的设备都是挂接在总线上的,而要使设备工作,就需要相应的驱动.设备模型会产生一个虚拟的文件系统——sysfs,它给用户提供了一个从用户空间去访问内核设备的方法,它在linux里的路径是/sys.如果要写程序访问sysfs,可以像读写普通文件一样来操作/sys目录

编写LED驱动

1.创建LED驱动的设备文件: (1)使用cdev-init函数初始化cdev (2)指定设备号 设备号的分配有两种指定方法:直接在代码中指定(硬编码) 动态分配 (3)使用cdev-add函数将字符设备添加到内核中的字符设备数组中 (4)使用class-creat宏创建struct class (5)使用device-create函数创建设备文件 2.LED驱动通过两种方式控制LED 通过字符串控制LED 通过I/O命令LED 3.一个完整的linux驱动主要由内部处理和与硬件交互两部分组成.

linux驱动(九)platform驱动模型详解,以及基于platform驱动模型的led驱动

参考: http://blog.csdn.net/qq_28992301/article/details/52385518 http://blog.csdn.net/zoe6553/article/details/6372445 http://blog.chinaunix.net/uid-25014876-id-111745.html 1:什么是platform总线?platform总线是区别于实体总线USB. I2C.SPI .PIC总线的虚拟总线,一些usb设备选址的话需要通过USB总线来进

兼容可控硅调光的一款LED驱动电路记录

1.该款电路为兼容可控硅调光的LED驱动电路,采用OB3332为开关控制IC,拓扑方案为Buck: 2.FB1:磁珠的单位是欧姆,而不是亨利,这一点要特别注意.因为磁珠的单位是按照它在某一频率 产生的阻抗来标称的,阻抗的单位也是欧姆.磁珠的 DATASHEET上一般会提供频率和阻抗的特性曲线图,一般以100MHz为标准,比如[email protected],意思就是在100MHz频率的时候磁珠的阻抗相当于600欧姆: 3.UFM14PL-TP普通二极管: Maximum Recurrent P

(笔记)linux设备驱动--LED驱动

linux设备驱动--LED驱动 最近正在学习设备驱动开发,因此打算写一个系列博客,即是对自己学习的一个总结,也是对自己的一个督促,有不对,不足,需要改正的地方还望大家指出,而且希望结识志同道合的朋友一起学习技术,共同进步. 作者:liufei_learning(转载请注明出处) email:[email protected] IT学习交流群:160855096 转至:http://blog.csdn.net/liufei_learning/article/details/7025246 开发环

FL2440驱动添加(4)LED 驱动添加

硬件信息:FL2440板子,s3c2440CPU带四个LED,分别在链接GPB5,GPB6,GPB8,GPB10 内核版本:linux-3.8.0 led驱动代码如下: 值得注意地方地方: 1,定时器的使用:在include/linux/timer.h下定义struct timer_list struct timer_list { /* * All fields that change during normal runtime grouped to the * same cacheline *

有注释的LED驱动

裸机下控制LED灯非常方便,只需要配置好GPIO引脚功能,然后向GPIO引脚映射的内存地址处写入数据即可,但linux下驱动就不那么简单了,需要结合字符设备驱动的架构,然后将功能实现添加进去,笔者参考linux设备驱动程序(第三版)中介绍的新的接口来实现驱动.友善之臂官网提供的源码是基于miscdevice的驱动,而且接口似乎有点老,比如在linux设备驱动程序(第三版)中强调需要使用新的内存I/O接口来访问映射内存,建议使用ioread32,iowrite32等,但是它依然使用writel,r

驱动学习之LED驱动框架

一:什么是驱动框架  (1)内核中驱动部分维护者针对每个种类的驱动设计一套成熟的.标准的.典型的驱动实现,然后把不同厂家的同类硬件驱动中相同的部分抽出来自己实现好,再把不同部分留出接口给具体的驱动开发工程师来实现,这就叫驱动框架.  (2)内核维护者在内核中设计了一些统一管控系统资源的体系,这些体系让内核能够对资源在各个驱动之间的使用统一协调和分配,保证整个内核的稳定健康运行.譬如系统中所有的GPIO就属于系统资源,每个驱动模块如果要使用某个GPIO就要先调用特殊的接口先申请,申请到后使用,使用

嵌入式Linux学习笔记之LED驱动

最近在学习嵌入式Linux驱动开发,大致了解了驱动的基本开发流程,本文主要针对字符设备驱动开发做一个简要介绍,也当作是对这几天工作的一个小小总结. 计算机系统是由软硬件相互协调共同完成工作的,作为专用计算机系统的嵌入式系统也不例外,既要有CPU.SDRAM.FLASH.IO等硬件,同时也少不了操作系统和应用软件等软件的支持,而作为应用程序与硬件的桥梁--驱动程序,是整个嵌入式系统开发过程中的关键环节.驱动开发涉及底层,而了解底层作用机制对于整个系统的开发意义重大. Linux内核中有60%以上是