这两天被设备文件快搞疯了,也怪自己学东西一知半解吧,弄了几天总算能把设备注册理清楚一点点了。就以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函数何时被调用相关推荐

  1. Linux内核自带SPI设备驱动测试程序分析:spidev_test.c

        在Linux系统中,SPI 的用户模式设备接口的驱动源码位于 drivers/spi/spidev.c,在应用层生成 /dev/spidev* 的节点,可以通过 read. write 达到与 ...

  2. linux 设备驱动阻塞,深入浅出:Linux设备驱动中的阻塞和非阻塞I/O

    今天写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说就是对I/O操作的两种不同的方式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式. 一.基本概念: 阻塞操作 ...

  3. Linux设备驱动中的阻塞与非阻塞I/O

    阻塞和非阻塞I/O是设备访问的两种不同模式,驱动程序可以灵活的支持用户空间对设备的这两种访问方式 本例子讲述了这两者的区别 并实现I/O的等待队列机制, 并进行了用户空间的验证 基本概念: 1> ...

  4. Linux 设备驱动中的阻塞与非阻塞 I/O

    阻塞操作是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作.被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足.而非阻塞操作的进程在不能进行设备操作时 ...

  5. 二十、SPI设备驱动及应用(一)

    先给出Linux SPI子系统的体系结构图: SPI子系统体系结构 下面开始分析SPI子系统. Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的 ...

  6. Linux kernel SPI源码分析之SPI设备驱动源码分析(linux kernel 5.18)

    SPI基础支持此处不再赘述,直接分析linux中的SPI驱动源码. 1.SPI设备驱动架构图 2.源码分析 本次分析基于kernel5.18,linux/drivers/spi/spidev.c 设备 ...

  7. linux spi屏驱动程序,65 linux spi设备驱动之spi LCD屏驱动

    SPI的控制器驱动由平台设备与平台驱动来实现. 驱动后用spi_master对象来描述.在设备驱动中就可以通过函数spi_write, spi_read, spi_w8r16, spi_w8r8等函数 ...

  8. Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用

    关与设备树的概念,我们在Exynos4412 内核移植(六)-- 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用 Device Tree是一种描述硬件的数据结构,设备树源(De ...

  9. Linux SPI设备驱动

    实现了SPI OLED外设驱动,OLED型号为SH1106. 1.主机驱动与外设驱动分离 Linux中的I2C.SPI.USB等总线驱动,都采用了主机(控制器)驱动与外设(设备)驱动分离的思想.主机端 ...

最新文章

  1. Linux 命令 top 学习总结
  2. python——元素列表基础
  3. 67.数据库系统的三级模式
  4. python如何爬虫股票数据_简单爬虫:东方财富网股票数据爬取(python_017)
  5. 天然气阶梯是按年还是按月_按年算账 多退少补 你的年度个税应该是怎么算?...
  6. Android aidl在Framework的使用
  7. oracle删除orcl库_oracle删除数据文件
  8. python字典{:4}_升级您的Python技能:检查字典
  9. (05)Verilog HDL时序逻辑:always
  10. ios沙箱模式开启_iOS我眼中的沙盒机制
  11. mysql升级到8.0.17_windows10更换mysql8.0.17详细教程
  12. InstallShield教程-打包.NET程序
  13. arduino霍尔编码器蓝牙小车代码
  14. java 字符替换_java string中的替换字符串
  15. matlab中arccotx,微积分计算公式的推导过程
  16. 微软同步备份工具SyncToy,值得使用
  17. 大类资产配置(三)市场择时能力模型T-M
  18. C语言,函数没有return,返回类型就是void的么?
  19. Redis学习笔记(B站狂神说)(自己总结方便复习)
  20. Docker实现Canal MySQL增量日志订阅消费环境搭建

热门文章

  1. exe4j下载和使用(超详细)
  2. Java项目:springboot个人理财系统
  3. CrossLight.ApSys
  4. 【Shell】3万字图文讲解带你快速掌握shell脚本编程
  5. 中国乳化粉行业市场供需与战略研究报告
  6. “软件教父”又开始整理模式了!
  7. 资源的释放方式try-catch-finally, try-catch-resource
  8. java 枚举获取key_Java枚举根据key获取value
  9. smartform打印机设置SPAD
  10. maven项目统一管理版本号方案