Linux驱动开发-混杂字符设备驱动模型笔记 4

Posted hntea-hong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动开发-混杂字符设备驱动模型笔记 4相关的知识,希望对你有一定的参考价值。

混杂字符设备驱动模型

概念

  • linux系统中,称以主设备号为“10”,但次设备号不同的字符设备为混杂设备
  • 所有的混杂设备形成一个链表
  • 对设备访问时,内核根据次设备号查找到相应的设备

结构描述

struct miscdevice  

int minor; /*次设备号*/

const char *name;/*设备名,驱动加载后会自动创建该设备文件*/

const struct file_operations *fops; /*文件操作*/

struct list_head list; /*以下结构体内核使用..*/

struct device *parent;

struct device *this_device;

const char *nodename;

mode_t mode;

;

如何使用混杂设备驱动模型

a) 初始化混杂设备结构体:struct miscdevice xxx = ...;

b) 注册混杂设备 : int misc_register(struct miscdevice * misc);

c) 注销:int misc_deregister(struct miscdevice *misc)

4、编程模型

#include<linux/module.h>

#include<linux/init.h>

#include<linux/kernel.h>

#include<linux/miscdevice.h>

#include<linux/ioctl.h>

#include<linux/fs.h>

#define MINOR 100

#define DEVICENAME "led"

/*硬件初始化*/

.....



/*文件操作*/

.....

struct file_operations ledfp =



.open = led_open,

.unlocked_ioctl = ledctl,

;



/*1、混杂设备声明*/

struct miscdevice led_misc= 

.minor = MINOR,

.name = DEVICENAME,

.fops = &ledfp,

;



static int led_miscInit(void)



int ret = 0;

/*2、混杂设备注册*/

ret = misc_register(&led_misc);

return ret ;





static void led_miscExit(void)



int ret = 0;

/*注销混杂设备*/

ret = misc_deregister(&led_misc);





MODULE_LICENSE("GPL");

MODULE_AUTHOR("hntea");

module_init(led_miscInit);

module_exit(led_miscExit);

LED 混杂设备驱动编程实现

#include<linux/module.h>

#include<linux/init.h>

#include<linux/kernel.h>

#include<linux/miscdevice.h>

#include<linux/ioctl.h>

#include<linux/fs.h>

#include<linux/mm.h>

#include <asm/io.h>

#include <asm/uaccess.h>

#include "led_ioctl.h"



#define DEV_MINOR 100

#define DEVICENAME "led"



#define ON 1

#define OFF 0

#define LED_ON 0x00000018

#define LED_OFF 0X00000000

#define CON_ADDR 0xE0200060

#define DAT_ADDR 0xE0200064

/*************************************************

函数名: led_hardinit 实现

函数参数:

函数功能:led硬件初始化

*************************************************/

static void led_hardinit(void)



    unsigned int  tmp = 0;

    unsigned int *led_config;

    /*找出物理地址对应的虚拟地址*/

    led_config = ioremap(CON_ADDR,4); /*该寄存器是32位数值*/

    /*读取当前寄存器状态*/

    tmp = ioread32(led_config);

    tmp &= (~(0x11 << 11)); /*注意移位是二进制的...*/

    tmp |= (0x11 << 11);

    /*寄存器设置写回*/

    iowrite32(tmp,led_config);



/*************************************************

函数名: led_switch 实现

函数参数:

函数功能:led 状态切换

*************************************************/

static int led_switch(unsigned char  cmd)



    unsigned int *led_data;

    led_data = ioremap(DAT_ADDR,4);

    switch(cmd)

    

        case ON:

        iowrite32(LED_ON,led_data);

        break;

        case OFF:

        iowrite32(LED_OFF,led_data);

        break;

        default:

        return -1;

        break;

    

    return 0;



/*-------------------------文件操作--------------------*/

int led_open (struct inode *inode, struct file *filp)


    led_hardinit();

    return 0;





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


    /*命令解析*/

    switch(cmd)

    

    case TURNON_LED:

    led_switch(ON);

    break;

    case TURNOFF_LED:

    led_switch(OFF);

    break;

    default:

    return -ENOTTY;

    break;

    

    return 0;





struct file_operations ledfp =

    .open = led_open,

    .unlocked_ioctl = ledctl,
;



/*1、混杂设备声明*/

struct miscdevice led_misc= 

    .minor = DEV_MINOR,

    .name = DEVICENAME,

    .fops = &ledfp,

;

static int led_miscInit(void)

    int ret = 0;

    /*2、混杂设备注册,这能在/dev目录下创建 以设备名为文件名的设备文件*/

    ret = misc_register(&led_misc);

    return ret ;


static void led_miscExit(void)


    int ret = 0;

    /*3、注销混杂设备*/

    ret = misc_deregister(&led_misc);





MODULE_LICENSE("GPL");

MODULE_AUTHOR("hntea");

module_init(led_miscInit);

module_exit(led_miscExit);

LED控制头文件

#define LED_MAGIC 'L' /*幻数*/

#define TURNON_LED _IOW(LED_MAGIC,1,int)

#define TURNOFF_LED _IOW(LED_MAGIC,0,int)

LED驱动测试

#include<sys/fcntl.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<sys/ioctl.h>

#include<stdio.h>

#include "led_ioctl.h"

#define DEVICE_FILE "/dev/led"

int main(int arg,char **argv)



    int fd = 0 ;

    int cmd = 0;

    int ret = 0;

    unsigned int test = 0b11;

    printf("test is :%x\\n",(test<<3));

    /*解析传递进来的参数*/

    if(arg < 2)

    

        printf("Please input : <cmd>  <0/1>\\n");

        return -1;

    

    /*格式化*/

    cmd = atoi((argv[1]));

    /*设备操作*/

    if((fd  = open(DEVICE_FILE,O_RDWR))< 0)

    

        printf("File open err!\\n");

    

    switch(cmd)

    

        case 0:

        ret = ioctl(fd,TURNOFF_LED);

        break;

        case 1:

        ret = ioctl(fd,TURNON_LED);

        break;

        default:

        printf("Command er!\\n");

        return -1;

    

    close(fd);

以上是关于Linux驱动开发-混杂字符设备驱动模型笔记 4的主要内容,如果未能解决你的问题,请参考以下文章

12.混杂设备驱动模型

Linux混杂设备驱动

LINUX按键驱动程序

Linux混杂字符设备

第四季-专题12-按键驱动程序设计

字符设备驱动模型