字符设备驱动学习
作为驱动必须有一个设备号向系统申请
int register_chrdev(unsigned int major,const char * name,sonst struct file_operations * fops)
segment1 主设备号:
设备号(32位)==主设备号(12bit)+次设备号(20bit)
主设备号:表示一类设备如 camera
次设备号:表示一类设备中的某一个
给定参数方式
1,动态参数1直接填0
2. 静态参数给定一个int值
segment2 描述一个设备信息
/proc/devices列举出所有到已经注册的设备
segment3:文件操作对象 提供的open,read write
返回值 可自己去看,正确的返回0
释放资源
void unregister_chrdev(unsigned int major,const char * name,sonst struct file_operations * fops)
**```
3创建设备节点**
1手动创建节点
mknod /dev/设备名 类型 主设备号 次设备号
缺点:/dev/目录中文件都是在内存中,断电后消失
2自动创建
struct class *class_create(owner,name)
参数1:this_module
参数2:字符串名字,自定义
返回一个指针
class_create(owner,name)
创件一个设备文件
struct device *device_create(struct class *class,struct device *parent,dev_t devt,void * drvdat,const char * fmt,...)
参数1:class结构体,clsss_create条用之后返回值
参数2:表示父结构体,一般为null
参数3:设备号类型 dev_t
dev_t devt
#define MAJOR(dev) {(unsigned int) ((dev)>>MINORBITS)}
#define MINOR(dev) {(unsigned int) ((dev)&MINORBITS)}
#define MKDEV(ma,mi)(((ma)<<MINORBITS)|(mi))
参数4: 私有数据一般为null
参数5和6:表示可变参数,字符串,表示设备节点的名字
销毁动作:device_destory()
全局变量静态指针:static struct class *devcls
:struct device *dev
步骤和规范
1、实现模块的加载和卸载入口函数
module_init()
module_exit()
2、在模块加载入口函数中
a、申请主设备号(内核中用于区分和管理不同的字符设备)
register_chrdev(dev_major,"char_dev_test",&my_fops);
b、创建设备节点为与用户提供一个可操作到文件接口open()
struct class *class_create(THIS_MODULE,"chr_cls")
struct device *device_create(devcls,NULL,MKDEV(dev_major,0),NULL,"chr2")
c、硬件初始化
1、地址映射
2、中断到申请
3、实现到硬件的寄存器到初始话
//需配置gpio功能为输出
e、实现file_operations
const struct file_operations my_fops={
.open = chr_drv_open,
}