SPI驱动框架
- 概述
- 详细讲解
论述
为什要写这个博客呢,主要有两个原因:第一,记录自己对SPI驱动的理解;第二,网上很多讲解SPI驱动都是自上而下地讲解,比较难理解,现在我将从下而上地进行详细讲解。在阅读驱动程序是不能够从上而下读的,而是应该找到入口函数,一一连接起来。
大部分的驱动都是这三个步骤:注册设备,注册驱动,生成设备节点。
详细讲解
模块加载和模块卸载
module_init(spi_init);//spi_init只是函数名,无特殊意义
module_exit(spi_exit);//spi_exit只是函数名,无特殊意义
加载模块和卸载模块将会进入驱动注册函数和驱动卸载函数
spi_init和spi_exit函数(驱动注册和驱动卸载)
static void spi_init(void)
{
spi_register_driver(spi_driver);//注册驱动,spi_driver是spi类型驱动专有结构体
return 0;
}
static void spi_exit(void)
{
spi_spi_unregister_driver(spi_driver);//驱动卸载,spi_driver是spi类型驱动专有结构体
return 0;
}
spi_driver结构体
spi_driver是很重要的结构体,spi驱动的.name将spi_device联系起来,spi驱动里的probe函数和remove函数将驱动和设备节点联系起来,至此,设备\、驱动、节点三者联系了起来。
struct spi_driver
{
const struct spi_device_id *id_table,
int (*probe)(struct spi_device *spi),
int (*remove)(struct spi_device *spi),
void (*shutdown)(struct spi_device *spi),
int (*suspend)(struct spi_device *spi,pm_message_t mesg),
int (*resume)(struct spi_device *spi),
struct device_driver driver;
};
例子
struct spi_driver spi
{
driver = {
.name = "设备名",//这步将驱动和设备建立起了关系
.owner = THIS_MODULE,//THIS_MODULE
},
.probe = probe, //和设备节点联系起来
.remove = remove,
}
probe函数和remove函数(设备节点生成和摧毁)
int probe(struct spi_device *spi)
{
my_spi = spi;
misc_register(miscdevice); //字符设备节点注册
return 0;
}
static int rc522_remove(struct spi_device *spi)
{
misc_deregister(&miscdevice); //字符设备节点卸载
return 0;
}
miscdevice结构体
在miscdevice结构体我们将生成设备节点名字并通过file_operation结构体为上层函数调用提供函数接口。
struct miscdevice {
int minor,
const char *name,
const struct file_operations *fops,
struct list_head list,
struct device *parent,
struct device *this_device,
const struct attribute_group **groups,
const char *nodename,
umode_t mode,
};
例子
static struct miscdevice()//字符设备节点结构体
{
.minor = MISC_DYNAMIC_MINOR,
.fops = &file_operation,//提供上层接口函数
.name = "设备节点名称",
}
file_operation结构体
file_operation结构体主要功能是为上层程序提供接口函数。
struct file_operations {
struct module *owner;
loff_t(*llseek) (struct file *, loff_t, int);
ssize_t(*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t(*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
ssize_t(*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t(*aio_write) (struct kiocb *, const char __user *, size_t,
loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int,
unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
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);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t(*readv) (struct file *, const struct iovec *, unsigned long,
loff_t *);
ssize_t(*writev) (struct file *, const struct iovec *, unsigned long,
loff_t *);
ssize_t(*sendfile) (struct file *, loff_t *, size_t, read_actor_t,
void __user *);
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);
};
例子
static struct file_operations
{
.owner = THIS_MODULE,
.open = open,
.write = write,
.read = read, //提供上层接口
};
接口函数
int open(struct inode *inode,struct file *filp)
{
return 0;
}
static ssize_t write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}
static ssize_t read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}