导航:首页 > 操作系统 > linuxspi设备驱动

linuxspi设备驱动

发布时间:2022-05-21 14:02:42

❶ 怎么写linux的spi设备驱动

回复
1#
我也是新手,不过调通了SPI,
在SPI
驱动里面是分为
设备
总线
驱动的。。这个你要搞清楚。你所说的几个文件就是在这个层次关系里面的代码,如果你只是简单的使用SPI,内核自带的spidev.c就已经能够满足要求了。。我就这么用的。。。你可以参照内核里面的例程来分析分析。
另外,你也可以试着写一个裸驱试试。。。

❷ Linux下的SPI驱动怎么用谁有linux SPI使用的例子比如驱动一个小模块的程序。我想看

你所指的spidev.c是SPI的用户模式设备接口的驱动,可以通过应用程序去操作/dev/spidev*达到与硬件设备的SPI通信,对于操作SPI NOR FLASH,更多是注册为MTD设备,详细可参考drivers/mtd/device/m25p80.c,里面已经有相关实现。
但无论如何,前提是你的内核里已经有SPI控制器的驱动,否则如何通信呢。代码一般在drivers/spi/里。
那是应该是给spi设备驱动范本吧,可以籍此写自己的spi设备驱动,没有设备节点就自己创建个嘛。或者在驱动中添加创建设备节点的函数。

❸ 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
<pre name="code" class="cpp">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);
mole_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下spi驱动里的spi_write_then_read函数该怎么使用

水平不行,不一定对,仅供参考哈。
如果只是从AD里读数据的话,用spi_read就可以了,定义一个8位的缓冲区和一个16位的缓冲区。然后把读到的2个8bit的数据组合成1个16bit的数据。每次读到的数据量通过该函数的参数设定。
如果是想实现全双工,可以使用spi_write_then_read
读是一样的,写的话自己先把16位数据转换成2个8bit的数据,存放在一个8bit的缓冲区,作为该函数的参数。

❺ Linux 主机驱动与外设驱动分离

Linux中的SPI、IPC、USB等子系统都利用了典型的把主机驱动和外设驱动分离的想法,让主机端只负责产生总线上的传输波形,而外设端只是通过标准的API来让主机端以适当的波形访问自身。因此这里面就涉及了4个软件模块:
1)主机端的驱动。根据具体的IC、SPI、USB等控制器的硬件手册,操作具体的IPC、SPI、USB等控制器,产生总线的各种波形。
2)连接主机和外设的纽带。外设不直接调用主机端的驱动来产生波形,而是调一个标准的API。由这个标准的API把这个波形的传输请求间接“转发”给了具体的主机端驱动。当然,在这里,最好把关于波形的描述也以某种数据结构标准化。
3)外设端的驱动。外设接在I-C、SPI、USB这样的总线上,但是它们本身可以是触摸屏、网卡、声卡或者任意一种类型的设备。我们在相关的i2c_driver、spi_driver、usb_driver这种xxx_driver的probe () 函数中去注册它具体的类型。当这些外设要求IP℃、SPI、USB等去访问它的时候,它调用“连接主机和外设的纽带”模块的标准API。
4)板级逻辑。板级逻辑用来描述主机和外设是如何互联的,它相当于一个“路由表”。假设板子上有多个SPI控制器和多个SPI外设,那究竟谁接在谁上面管理互联关系,既不是主机端的责任,也不是外设端的责任,这属于板级逻辑的责任。这部分通常出现在arch/arm/mach-xxx下面或者arch/arm/bootldts下面。
什么叫良好的软件设计一言以蔽之,让正确的代码出现在正确的位置。不要在错误的时间、错误的地点,编写一段错误的代码。在LKML中,关于代码出现在错误的位置,常见的台词是代码“out of place"。
Linux通过上述的设计方法,把一堆杂乱不友好的代码变成了4个轻量级的小模块,每个模块都各得其所。每个模块都觉得很“爽”,站在主机端想一想,它其实也是很“爽”的,因为它的职责本来就是产生波形,而现在我们就让它只产生波形不干别的;站在外设端想一想,它也变得一身轻松。

❻ 请问linux驱动怎么调用底层的驱动啊 比如说已有SPI总线驱动,现要为一个SPI设备写驱动,怎么调用底层驱动

spi总线驱动在linux中是采用了分层设计和分隔设计的思想,spi控制器的驱动和核心层的通用api内核已经写完了,你只要写外设驱动就好,具体你可以去看一下你的spi_s3c24xx.c这个驱动是基于platfoem写的,里面含有如何调用核心api。

❼ 怎样用linux提供的spi驱动

内核版本2.6.30。编进内核的SPI驱动,通过看代码我明白了,大致过程是这样: 1、先创建一个spi_board_info结构描述spi设备信息,调用spi_register_board_info将这个结构添加到board_list中。 2、然后调用spi_register_master注册SPI控制器驱动,...

❽ linux下的SPI使用方法是怎样的

如果linux中已经提供了驱动,并且在/dev/目录下已经提供了相应的设备文件节点。那么可以和串口一样直接打开设置读写。如果内核中有驱动,但是没有生成设备文件节点,那么只要知道设备的主次设备号,可以使用mknode建立设备文件节点,然后直接来使用。如果没有驱动就需要自己添加设备驱动了。这个也分两种情况,看你外设怎么和你的板子连接的。如果接到板子上的spi控制器上,可以直接编写通过控制器来控制外设的驱动,这种情况一般生产主控芯片的厂家都已经提供了驱动。如果没有接到spi控制器上,而是通过gpio连接的外设,你编写的驱动就需要自己来模拟spi协议来控制外设。

❾ 请教linux的SPI驱动问题

内核版本2.6.30。编进内核的SPI驱动,通过看代码我明白了,大致过程是这样:
1、先创建一个spi_board_info结构描述spi设备信息,调用spi_register_board_info将这个结构添加到board_list中。
2、然后调用spi_register_master注册SPI控制器驱动,此时会调用scan_boardinfo扫描board_list,根据spi_board_info调用spi_new_device生成spi_device结构,用spi_add_device添加设备。
3、调用spi_register_driver注册spi_driver,通过与device匹配驱动设备。

❿ 如何在linux下实现一个I2C与SPI的从机驱动

最简情况下:
I2C:SDA数据线、SCL时钟线。
SPI:DI输入线、DO输出线、CS片选先、CLK时钟线。
可能不能写到一个驱动中。

但是好在一般很少用到这么简单的情况,厂家会对其扩展和改进。

比如 W25Q128FB/W25R128FV 系列闪存,支持 SPI、Dual SPI、Quad SPI 和 QPI。就拿 Quad SPI 来说,有 6 个引脚:

Quad SPI:D0-D3 输入输出线、CS片选先、CLK时钟线。

其中 输入为一位串行输入 D0,输出为四位串行输出 D0-D3。(四位仍少于一个字节,可姑且称为串行)

Winbond华邦 这么做是为了加快闪存读取速度(四位串行相比一位串行提高了四倍)。

因此关键在于 要进行怎样的 IO。至于是否将二者写到一个驱动看来并不重要。

阅读全文

与linuxspi设备驱动相关的资料

热点内容
单片机有4个8位的io口 浏览:895
win10rar解压缩软件 浏览:164
plc教程pdf 浏览:665
pythonshell清屏命令 浏览:278
检测到加密狗注册服务器失败 浏览:203
解压后手机如何安装 浏览:518
极客学院app为什么下架 浏览:13
图片批量压缩绿色版 浏览:651
东北程序员帅哥 浏览:707
加密封条风噪小 浏览:974
安阳少儿编程市场 浏览:499
云服务器建设原理 浏览:259
javajunit4for 浏览:847
华为服务器如何进阵列卡配置 浏览:435
apache服务器ip地址访问 浏览:720
如何买到安卓手机预装软件 浏览:537
冤罪百度云不要压缩 浏览:88
苏州云存储服务器 浏览:177
解压收纳原声 浏览:387
java注册验证 浏览:377