6.5 Linux 驱动开发 总线设备驱动模型
platform:linux中的一种虚拟总线。一个现实的linux设备和驱动通常都需要挂接在一种总线上(方便管理),例如PCI、USB、I2C、SPI等,但是对于在Soc系统中集成的独立外设控制器、挂接在Soc内存空间的外设等却不能依附于上述总线,这时候linux就发明了一种虚拟总线,来管理这一类的设备(没有实体的硬件总线电路)。
platform设备驱动模型中,分为设备、驱动、总线3个实体,分别称为 platform_device、paltform_driver和 platform 总线,总线负责将设备和驱动进行绑定。在系统每注册一个设备时,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动时,会寻找与之匹配的设备,而匹配的过程则由总线完成。
完整示例:
#define NAME_DEV "dtsled"
#define LEDOFF 0 /* 关灯 */
#define LEDON 1 /* 开灯 */
struct dev
{
dev_t devid;
int major;
int minor;
struct class *class;
struct device *device; /* 设备 */
struct cdev cdev;
struct device_node *nd; /* 设备节点 */
unsigned gpio; /* led 所使用的 GPIO 编号 */
};
//例:
struct dev dev;
static int dev_open(struct inode *inode, struct file *filp)
{
filp->private_data = &dev;
return 0;
}
static int dev_release(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t dev_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static ssize_t dev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
int retvalue;
unsigned char databuf[1];
unsigned char stat;
struct dev *dev = filp->private_data;
retvalue = copy_from_user(databuf, buf, cnt);
if(retvalue < 0) {
printk("kernel write failed!\r\n");
return 0;
}
stat = databuf[0]; /* 获取状态值 */
if(stat == LEDON) {
gpio_set_value(dev->gpio, 0); /* 打开 LED 灯 */
} else if(stat == LEDOFF) {
gpio_set_value(dev->gpio, 1); /* 关闭 LED 灯 */
}
return 0;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = dev_open,
.release = dev_release,
.read = dev_read,
.write = dev_write,
};
static int dev_probe(struct platform_device *pdev)
{
int ret = 0;
/* 获取设备树中的属性数据 */
/* 1、获取设备节点:gpioled */
dev.n
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
C++/嵌入式开发 秋招面经 文章被收录于专栏
一名985硕,在25年秋招中斩获多个C++/嵌入式开发Offer。本专栏将分享我的面经,涵盖C/C++、操作系统、计算机网络、ARM体系与架构、Linux应用/驱动开发、Qt、通信协议及开发工具链等核心内容。
查看9道真题和解析