> 文章列表 > 树莓派学习笔记(十三)基于框架编写驱动代码

树莓派学习笔记(十三)基于框架编写驱动代码

树莓派学习笔记(十三)基于框架编写驱动代码

文章目录

  • 一、代码分析:
  • 二、源码

一、代码分析:

  • 内核中由于代码文件多,避免函数名重复,使用static将函数的作用域限制在该文件内

  • 内核的打印函数printk和printf类似

  • file_operations结构体使用符号“ . ”指定参数,省去不需要的参数

  • pin4_drv_init初始化函数:
    MKDEV根据主设备号、次设备号创建设备号
    register_chrdev 注册驱动,将驱动加入到内核驱动链表中
    class_create 创建设备类
    device_create 创建设备文件

  • pin4_drv_exit 删除函数:
    device_destroy 删除设备文件
    class_destroy 删除设备类
    unregister_chrdev 卸载驱动

  • 内核的入口:module_init调用pin4_drv_init初始化函数

二、源码

驱动源码:

#include <linux/fs.h>		 //file_operations声明
#include <linux/module.h>    //module_init  module_exit声明
#include <linux/init.h>      //__init  __exit 宏定义声明
#include <linux/device.h>	 //class  devise声明
#include <linux/uaccess.h>   //copy_from_user 的头文件
#include <linux/types.h>     //设备号  dev_t 类型声明
#include <asm/io.h>          //ioremap iounmap的头文件static struct class *pin4_class;  
static struct device *pin4_class_dev;static dev_t devno;                //设备号
static int major =231;  		   //主设备号
static int minor =0;			   //次设备号
static char *module_name="pin4";   //模块名//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{printk("pin4_open\\n");  //内核的打印函数和printf类似return 0;
}//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{printk("pin4_write\\n"); return 0;
}//led_read函数
static int pin4_read(struct file *file,char __user *buf,size_t count, loff_t *ppos)
{printk("pin4_read\\n"); return 0;
}static struct file_operations pin4_fops = {.owner = THIS_MODULE,.open  = pin4_open,.write = pin4_write,.read  = pin4_read,
};int __init pin4_drv_init(void)   
{int ret;devno = MKDEV(major,minor);  //创建设备号ret   = register_chrdev(major, module_name,&pin4_fops);  //注册驱动  告诉内核,把这个驱动加入到内核驱动的链表中pin4_class=class_create(THIS_MODULE,"myfirstdemo");      //创建设备类pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  //创建设备文件return 0;
}void __exit pin4_drv_exit(void)
{device_destroy(pin4_class,devno);class_destroy(pin4_class);unregister_chrdev(major, module_name);  //卸载驱动}module_init(pin4_drv_init);  //入口
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");

测试程序源码:

  • 测试程序由于要放在树莓派ARM下运行,故需在Ubuntu下使用交叉编译工具进行编译,再通过scp命令传输给树莓派
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{int fd = open("/dev/pin4",O_RDWR);if(fd < 0 ){printf("open failed\\n");error("reason:");}else{printf("open success\\n");}fd = write(fd,'1',1);return 0;
}