驱动笔记——LED

LED驱动代码托管在 gitee
https://gitee.com/maziot-samsung/jz2440v3.drivers/blob/master/leds/myleds.c


字符设备的核心就是 file_operations 结构体,不管是现在的LED驱动还是什么驱动,不管是最普通的写法还是总线设备驱动模型。只要他是一个字符设备,那他的核心就一定是 file_operations 结构体。


作为一个驱动程序,我们应该从入口函数开始看,入口函数就是被 module_init() 修饰过的函数,出口函数同理
在入口函数里面首先调用了ioremap函数,此函数是将物理地址映射成虚拟地址,这样我们就可以像操作内存中的地址一样操作物理地址,参数为 ioremap(起始地址,映射长度) 然后就是向内核注册一个字符设备,也就是 file_operations 结构体 最后分创建类和设备。

ioremap不讲就是一个映射,STM32中GPIOA就是等于0x80000080一样,只不过STM32标准库做好了映射,而Linux需要调用函数来映射而已

file_operations (非常重要)

struct file_operations { 
  struct module *owner;//拥有该结构的模块的指针,一般为THIS_MODULES  
   loff_t (*llseek) (struct file *, loff_t, int);//用来修改文件当前的读写位置  
   ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//从设备中同步读取数据      ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//向设备发送数据  
   ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的读取操作   
   ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一个异步的写入操作   
  int (*readdir) (struct file *, void *, filldir_t);//仅用于读取目录,对于设备文件,该字段为NULL   
   unsigned int (*poll) (struct file *, struct poll_table_struct *); //轮询函数,判断目前是否可以进行非阻塞的读写或写入   
  int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //执行设备I/O控制命令   
  long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系统,将使用此种函数指针代替ioctl  
  long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系统上,32位的ioctl调用将使用此函数指针代替   
  int (*mmap) (struct file *, struct vm_area_struct *); //用于请求将设备内存映射到进程地址空间  
  int (*open) (struct inode *, struct file *); //打开   
  int (*flush) (struct file *, fl_owner_t id);   
  int (*release) (struct inode *, struct file *); //关闭   
  int (*fsync) (struct file *, struct dentry *, int datasync); //刷新待处理的数据   
  int (*aio_fsync) (struct kiocb *, int datasync); //异步刷新待处理的数据   
  int (*fasync) (int, struct file *, int); //通知设备FASYNC标志发生变化   
  int (*lock) (struct file *, int, struct file_lock *);   
  ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);   
  unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);   
  int (*check_flags)(int);   
  int (*flock) (struct file *, int, struct file_lock *);  
  ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);  
  ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);   
  int (*setlease)(struct file *, long, struct file_lock **);   
};

结构体中包含非常多的函数指针,并不是每个驱动程序都要有所有的函数指针,此LED驱动程序就只用了open read write三个而已。给函数指针赋值,当应用程序调用read write的时候实际上就会调用你赋值的那个函数了。

register_chrdev来注册,参数为register_chrdev(主设备号,名字,结构体指针),值得注意一下的是当主设备号为0时系统自动分配一个暂时没用的数字作为书设备号。名字不重要。结构体指针才是关键,目的是为了可以找到驱动程序的read write函数。

class_create先创建一个类。然后再用class_device_create创建类下面的设备。怎么理解呢?
先从设备讲起吧,我们这是个LED的驱动。一个LED灯就是一个设备,但是他们都属于LED这个类

出口函数和入口函数恰好相反,有注册就有注销 unregister_chrdev 有创建类就有消除类 class_destroy 有创建设备就有消除设备class_device_unregister 有映射就有取消映射 iounmap

到这里驱动程序的框架差不多就写好了,接下来就是填充结构体里面的函数指针来具体实现open read wirte

open:

当应用程序调用open时传到驱动程序就会调用这个open,open很简单,只需要将GPIO初始化就行,比如设置为输入还是输出等。

read:

read函数是应用程序想要知道当前设备状态,就去读,需要把当前状态发送给应用程序,首先根据主设备号通过MINOR宏取得此设备号以进一步取得设备led1、led2... 然后获取相应的状态值。由于3个LED的状态值保存于一个变量,我们需要读出具体某一个的状态,因此需要对leds_status进行读操作,读的时候先获得原子锁,以防读取了一个错误的状态最后通过copy_to_user将状态值发送给应用程序

write:

通过copy_from_user获得应用程序发过来的数据,通过MINOR获得需要操作的设备,最后将引脚电平拉高或者拉低

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355