ARM学习笔记之驱动程序篇八----LED设备驱动

一,字符设备控制技术

1.2 设备控制-应用函数

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

int ioctl(int fd,unsigned long cmd)
//fd:要控制的设备文件描述符
//cmd:发送给设备的控制命令
//...:第三个参数是可选的参数,存在与否是依赖于控制命令(第二个参数)

1.3 设备控制-驱动函数

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

1:2.6.36之前的内核

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

2:2.6.36之后的内核

long (*unlock_ioctl)(struct file *filp,unsigned int cmd,unsigned long arg)
//参数cmd:通过应用函数ioctl传递下来的命令

2.1 控制实现-定义命令

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

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

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

@direction:参数传送的方向,可能的值是_IOC_NONE(没有数据传输),_IOC_READ,_IOC_WRITE

@size:参数长度

linux系统提供了下面的宏来帮助定义命令:

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

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

@_IOW(type,nr,datatype):从设备中写参数的命令

例如:

#define MEM_MAGIC 'm'

#define MEM_SET _IOW(MEM_MAGIC,0,int)

2.2 设备控制-实现操作

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

switch (cmd){
case a:
case b:
default:
    return -EINVAL;
}

2.3 LED控制代码实现

//led.h
#define LED_MAGIC 'l'
#define LED_ON _IO(LED_MAGIC,0)
#define LED_OFF _IO(LED_MAGIC,1)

//led.c
#include
#include
#include
#include
#include
#include
#include"led.h"
#define LEDCON 0x7f008800
#define LEDDAT 0x7f008808

unsigned int *led_config;
unsigned int *led_data;

struct cdev cdev;
dev_t devno;

int led_open(struct indoe *node,struct file *filp){
    led_config =ioremap(LEDCON,4);
    writel(0x11110000,led_config);
    led_data=ioremap(LEDDAT,4);
    return 0;	
}

long led_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;
        		
    }
}

static struct file_operations led_fops={
    .open=led_open,
    .unlocked_ioctl=led_ioctl,
};

static int led_init(){
    cdev_init(&cdev,&led_fops);
    alloc_chrdev_region(&devno,0,1,"myled");
    cdev_add(&cdev,devno,1);
    return 0;	
}

static void led_exit(){
    cdev_del(&cdev);
    unregister_chrdev_region(devno,1);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

//led_app.c
#include
#include"led.h"
int main(int argc,char *argv[]){
    int fd;
    int cmd;
    if(argc<2){
        printf("please enter the second para!\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;
 
}

 

你可能感兴趣的:(ARM学习笔记)