linux probe函数调用,linux spi设备驱动中probe函数何时被调用
这两天被设备文件快搞疯了,也怪自己学东西一知半解吧,弄了几天总算能把设备注册理清楚一点点了。就以spi子设备的注册为例总结一下,免得自己忘记。
首先以注册一个spidev的设备为例:
static struct spi_board_info imx5_spi_printer_device[] __initdata =
{
{
.modalias = "spidev",
.max_speed_hz = 8000000,
.bus_num = 1,
.chip_select = 1,
.mode = spi_mode_0,
},
};
spi_register_board_info(imx5_spi_printer_device,array_size(imx5_spi_printer_device));
在mx5_loco.c文件中添加上面结构体spi_board_info,modalias必须指定已有的一个驱动,至于bus_num和chip_select,如果你不知道bus_num是多少,可以在你的父驱动中打印出来,这里的bus_num一定要和父类的bus_num一致,否则是无法生成设备文件的。如果spi一直没有时钟信号,很有可能是bus_num不对。
这样系统起来之后就会在/dev目录下出现一个名为spidev1.1的设备文件,读写这个文件就可以实现spi的操作
还有下面这种情况:
static struct spi_board_info prt_spi_device[] __initdata = {
{
.modalias = "hotprt",
.max_speed_hz = 12500000, /* max spi clock (sck) speed in hz */
.bus_num = 1,
.chip_select = 1,
// .mode = spi_mode_0,
.platform_data = 0,
},
};
spi_register_board_info(prt_spi_device, array_size(prt_spi_device));
我自己实现了一个spi的驱动,然后需要创建一个设备文件,设备文件的创建是在probe中完成。
static struct spi_driver prt_driver = {
.driver = {
.name = "hotprt",
.bus = &spi_bus_type,
.owner = this_module,
},
.probe = prt_probe,
.remove = __devexit_p(prt_remove),
};
spi_register_driver(&prt_driver);
但是我开始一直触发不了probe,于是找啊找,总算知道probe的调用过程了,如下:
int spi_register_driver(struct spi_driver *sdrv)
{
sdrv->driver.bus = &spi_bus_type;
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe;
if (sdrv->remove)
sdrv->driver.remove = spi_drv_remove;
if (sdrv->shutdown)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
然后调用driver_register
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
bug_on(!drv->bus->p);
if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(kern_warning "driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);
other = driver_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(kern_err "error: driver '%s' is already registered, "
"aborting...\n", drv->name);
return -ebusy;
}
ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}
直接看bus_add_driver
klist_init(&priv->klist_devices, null, null);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, null,
"%s", drv->name);
if (error)
goto out_unregister;
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if (error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
module_add_driver(drv->owner, drv);
这里只截取一部分,最后调用的是driver_attach
int driver_attach(struct device_driver * drv)
{
return bus_for_each_dev(drv->bus, null, drv, __driver_attach);
}
真正起作用的是__driver_attach:
static int __driver_attach(struct device * dev, void * data)
{
。。。
if (!dev->driver)
driver_probe_device(drv, dev);
。。。
}
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
。。。
//1.先是判断bus是否match:
if (drv->bus->match && !drv->bus->match(dev, drv))
goto done;
//2.再具体执行probe:
ret = really_probe(dev, drv);
。。。
}
really_probe才是我们要找的函数:
static int really_probe(struct device *dev, struct device_driver *drv)
{
。。。
//1.先是调用的驱动所属总线的probe函数:
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
//2.再调用你的驱动中的probe函数:
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
。。。
}
其中,drv->probe(dev),才是真正调用你的驱动实现的具体的probe函数。至此probe函数被调用。
在板文件中添加spi_board_info,并在板文件
linux probe函数调用,linux spi设备驱动中probe函数何时被调用相关推荐
- Linux内核自带SPI设备驱动测试程序分析:spidev_test.c
在Linux系统中,SPI 的用户模式设备接口的驱动源码位于 drivers/spi/spidev.c,在应用层生成 /dev/spidev* 的节点,可以通过 read. write 达到与 ...
- linux 设备驱动阻塞,深入浅出:Linux设备驱动中的阻塞和非阻塞I/O
今天写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说就是对I/O操作的两种不同的方式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式. 一.基本概念: 阻塞操作 ...
- Linux设备驱动中的阻塞与非阻塞I/O
阻塞和非阻塞I/O是设备访问的两种不同模式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式 本例子讲述了这两者的区别 并实现I/O的等待队列机制, 并进行了用户空间的验证 基本概念: 1> ...
- Linux 设备驱动中的阻塞与非阻塞 I/O
阻塞操作是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作.被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足.而非阻塞操作的进程在不能进行设备操作时 ...
- 二十、SPI设备驱动及应用(一)
先给出Linux SPI子系统的体系结构图: SPI子系统体系结构 下面开始分析SPI子系统. Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的 ...
- Linux kernel SPI源码分析之SPI设备驱动源码分析(linux kernel 5.18)
SPI基础支持此处不再赘述,直接分析linux中的SPI驱动源码. 1.SPI设备驱动架构图 2.源码分析 本次分析基于kernel5.18,linux/drivers/spi/spidev.c 设备 ...
- linux spi屏驱动程序,65 linux spi设备驱动之spi LCD屏驱动
SPI的控制器驱动由平台设备与平台驱动来实现. 驱动后用spi_master对象来描述.在设备驱动中就可以通过函数spi_write, spi_read, spi_w8r16, spi_w8r8等函数 ...
- Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用
关与设备树的概念,我们在Exynos4412 内核移植(六)-- 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用 Device Tree是一种描述硬件的数据结构,设备树源(De ...
- Linux SPI设备驱动
实现了SPI OLED外设驱动,OLED型号为SH1106. 1.主机驱动与外设驱动分离 Linux中的I2C.SPI.USB等总线驱动,都采用了主机(控制器)驱动与外设(设备)驱动分离的思想.主机端 ...
最新文章
- Linux 命令 top 学习总结
- python——元素列表基础
- 67.数据库系统的三级模式
- python如何爬虫股票数据_简单爬虫:东方财富网股票数据爬取(python_017)
- 天然气阶梯是按年还是按月_按年算账 多退少补 你的年度个税应该是怎么算?...
- Android aidl在Framework的使用
- oracle删除orcl库_oracle删除数据文件
- python字典{:4}_升级您的Python技能:检查字典
- (05)Verilog HDL时序逻辑:always
- ios沙箱模式开启_iOS我眼中的沙盒机制
- mysql升级到8.0.17_windows10更换mysql8.0.17详细教程
- InstallShield教程-打包.NET程序
- arduino霍尔编码器蓝牙小车代码
- java 字符替换_java string中的替换字符串
- matlab中arccotx,微积分计算公式的推导过程
- 微软同步备份工具SyncToy,值得使用
- 大类资产配置(三)市场择时能力模型T-M
- C语言,函数没有return,返回类型就是void的么?
- Redis学习笔记(B站狂神说)(自己总结方便复习)
- Docker实现Canal MySQL增量日志订阅消费环境搭建