3-11 LED驱动程序设计

(本节笔记的实验代码,在这里

一.  字符设备控制理论

1.  概述

    大部分驱动程序除了需要提供读写设备的能力外,还需要具备控制设备的能力,例如设置波特率等。

    在用户空间中,使用ioctl系统调用控制设备,原型为:

int ioctl(int fd, unsigned longcmd, ...)

fd:要控制的设备文件描述符。

cmd:发送给设备的控制命令。

...:第三个参数是可选的参数,存在与否依赖于控制命令(cmd)。

    当应用程序使用ioctl系统调用时,驱动程序将由如下函数来响应:

    在2.6.36之前的内核为:

long (*ioctl)(struct inode*node,struct file *filp,unsigned int cmd,unsigned long arg)

    在2.6.36之后的内核为:

long (*unlocked_ioctl)(structfile *filp,unsigned int cmd,unsigned long arg)


    /*驱动程序模型学习方法*/

    1)先参照应用程序的实现方法,查看函数名和参数

    2)查看file_operations设备方法中的对应函数

    3)实现该对应函数的设备方法

 

2.  设备控制方法的实现

 2.1  定义命令

    命令从是指而言就是一个整数,但为了让这个整数具备更好的可读性,一般会把这个整数分为几个段:类型(8位),序号,参数传送方向,参数长度。

    type(类型/幻数):表明这是属于哪个设备的命令。

    number(序号):用来区分同一设备的不同命令。

    direction:参数传送的方向,可能的值为:_IOC_NONE(没有数据传输),_IOC_READ(从设备读出数据),_IOC_WRITE(向设备写入数据)。

    size:参数长度。

    Linux系统提供下面的宏来定义命令:

    _IO(type,num):不带参数的命令

    _IOR(type,num,datatype):从设备中读参数的命令

    _IOW(type,num,datatype):向设备写入参数的命令

例如:#define MEM_MAGEC 'm' //定义幻数

      #define MEM_SET_IOW(MEM_MAGEIC,0,int)


 2.2  实现设备方法

    unlocked_ioctl函数的实现通常是根据命令执行的一个switch语句。但是,当命令号不能匹配任何一个设备所支持的命令时,将返回-EINVAL

编程模型为:switch (cmd)

            case 命令A:

              //执行A对应的操作

            case 命令B:

              //执行B对应的操作

            default:

              return -EINVAL

3.  范例代码

 3.1   touch memdev.h

 #define MEM_MAGIC 'm'

 #define MEM_RESTART _IO(MEM_MAGIC ,0)

 #define MEM_SET _IOW(MEM_MAGIC,1,int)

                                                             』

 3.2修改memdev.c

 1)包含  #include "memdev.h"

 在file_operations里面加入:

      .unlocked_ioctl = mem_ioctl,

 定义mem_ioctl

      long mem_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)

      {

          switch (cmd)

              case MEM_RESTART:

                  printk("restartdevice!\n");

                  return 0;

              case MEM_SET:

                  printk("arg is%d\n",arg);

                  return 0;

              default:

                  return -EINVAL;

      }

 3.2   touch mem_ctl.c

 #include <sys/types.h>

 #include <sys/stat.h>

 #include <sys/ioctl.h>

 #include <fcntl.h>

 #include "memdev.h"

 

 int main()

 {

    int fd;

    fd = open("/dev/memdev0",O_RDWR);

 

    ioctl(fd, MEM_SET,115200);

    ioctl(fd, MEM_RESTART);

    return 0;

 }

                                                             』

/* 编译时记得加-static选项 */


二.  LED设备程序设计步骤

 

1.函数学习

unsigned int *led_config =ioremap(GPKCON);

writel(0x11110000,led_config);

 

2.代码实现

touch led.c

    #include<linux/module.h>

    #include<linux/init.h>

    #include<linux/cdev.h>

    #include<linux/fs.h>

    #include<linux/io.h>

    #include<mach/gpio-bank-k.h>

    #include"led.h"

 

    #defineLEDCON 0x7f008800

    #defineLEDDAT 0x7f008808

    unsignedint *led_config;

    unsignedint *led_data;

 

    structcdev cdev;

    dev_tdevno;

 

    intled_open(struct inode *node, struct file *filp)

    {

        led_config = ioremap(LEDCON,4);

        writel(0x11110000,led_config);

        led_data = ioremap(LEDDAT,4);

        return 0;

    }

 

    longled_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

    {

        switch (cmd)

        {

           case LED_ON:

               writel(0x00,led_data);

               return 0;

       

           case LED_OFF:

               writel(0xff,led_data);

               return 0;

       

           default:

                return -EINVAL;

        }

    }

 

    staticstruct file_operations led_fops =

    {

       .open = led_open,

        .unlocked_ioctl = led_ioctl,

    };

 

    staticint led_init()

    {

       cdev_init(&cdev,&led_fops);

   

        alloc_chrdev_region(&devno, 0 , 1 ,"myled");

        cdev_add(&cdev, devno, 1);  

        return 0;  

    }

 

    staticvoid led_exit()

    {

        cdev_del(&cdev);

        unregister_chrdev_region(devno,1);

    }

 

module_init(led_init);

module_exit(led_exit);                                                                                                           』


touch led_app.c

    #include<sys/types.h>

    #include<sys/stat.h>

    #include<fcntl.h>

    #include<sys/ioctl.h>

    #include"led.h"

 

    intmain(int argc, char *argv[])

    {

      int fd;

      int cmd;    

      if (argc <2 )

         {

             printf("please enter the secondpara!\n");

         return 0;

     }

    

     cmd = atoi(argv[1]);    

     fd = open("/dev/myled",O_RDWR);   

     if (cmd == 1)

          ioctl(fd,LED_ON);

      else

         ioctl(fd,LED_OFF);        

     return 0;

    }                                                    

                                                               』

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值