普通字符设备驱动宏观分析
在内核中,一个字符型设备驱动有许多种实现方式,这里介绍的是最为“质朴”的实现方式
其本质是:通过读写/dev内的设备文件,来间接访问file_operations结构体内的函数,从而实现操作硬件
代码的基本结构可以分为:
- 头文件
- file_operations内硬件操作函数的具体实现
- file_operations结构体(实现硬件操作的核心)
- 模块加载、卸载函数(内部实现新建、注册一个字符设备体以及创建设备文件)
- 模块相关的信息(不重要)
整体关系:
/*
* 第一部分:头文件
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <plat/map-base.h>
#include <plat/map-s5p.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#define MYNAME "mydevice"
#define MYDEV_CNT 3
/*这里的xxxx是我们给command分配的设备类型字段,详见后文有关ioctl部分*/
#define SET_DEV_SPEED _IO(xxxx,0)
#define SET_DEV_LEN _IO(xxxx,0)
/*
* 第二部分:file_operations内硬件操作函数的具体实现
*/
static int mydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case SET_DEV_SPEED:
/*设置根据参数arg,设置寄存器*/
break;
case SET_DEV_LEN: