SPI protocol驱动编写实例
内核版本:3.9.5
Linux中SPI驱动有俩个部分组成:controller驱动,直接和底层硬件打交道,protocol驱动,针对特定的设备,也是我们要做的.
这里只考虑SPI protocol驱动
在主线内核中有一个通用的字符型驱动范例spidev.本文不讨论spidev,而是探讨如何编写一个自定义SPI设备驱动.
为何要编写一个自定义驱动:
- 可以掌控性能;
- 无需给内核打补丁.SPI框架完整支持在可加载内核模块中进行驱动设置.这也就允许我们在内核源码树外进行编写代码;
Kernel Configuration
关掉SPIDEV选项以支持自定义的驱动
Device Drivers-->
SPI support-->
*** SPI Protocol Masters ***
<> User mode SPIdevice driver support
为使linuxSPI系统识别你的驱动,需要做两步准备.
1. 在特定的SPI总线(一个master就是一条总线)上注册SPI slave设备.可以是内核初始化的时候亦或是在你的驱动代码中动态的进行.设备名称在这步中必须指定;
2. 注册SPI protocol驱动.使用的名字必须和步骤1中的一致,这样kernel就可以将它们链接在一起了;
两个步骤可以以任意次序进行,但是得知道当他们完成之后,SPI框架就可以响应你驱动中的probe()调用了.你将得到一个spi_device用来和SPI系统进行交互了.一旦你的probe函数调用成功,你就可以开始使用SPI总线了.
静态注册SPI设备涵盖在spidev中了.
动态主册SPI设备的步骤如下:
1. 得到管理总线的spi_master控制器指针(句柄);
2. 为总线分配spi_device结构;
3. 验证没有其他的设备已经在这条总线bus.cs上注册过了;
4. 使用设备特定的值(speed,datasize,etc)来填充spi_device;
5. 将新的spi_device添加到总线;
有个范例代码:
static int __init add_spike_device_to_bus(void)
{
struct spi_master *spi_master;
struct spi_device *spi_device;
struct device *pdev;
char buff[];
int status = ; spi_master = spi_busnum_to_master(SPI_BUS);
if (!spi_master) {
printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n",
SPI_BUS);
printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n");
return -;
} spi_device = spi_alloc_device(spi_master);
if (!spi_device) {
put_device(&spi_master->dev);
printk(KERN_ALERT "spi_alloc_device() failed\n");
return -;
} /* specify a chip select line */
spi_device->chip_select = SPI_BUS_CS1; /* Check whether this SPI bus.cs is already claimed */
snprintf(buff, sizeof(buff), "%s.%u",
dev_name(&spi_device->master->dev),
spi_device->chip_select); pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);
if (pdev) {
/* We are not going to use this spi_device, so free it */
spi_dev_put(spi_device); /*
* There is already a device configured for this bus.cs combination.
* It's okay if it's us. This happens if we previously loaded then
* unloaded our driver.
* If it is not us, we complain and fail.
*/
if (pdev->driver && pdev->driver->name &&
strcmp(this_driver_name, pdev->driver->name)) {
printk(KERN_ALERT
"Driver [%s] already registered for %s\n",
pdev->driver->name, buff);
status = -;
}
} else {
spi_device->max_speed_hz = SPI_BUS_SPEED;
spi_device->mode = SPI_MODE_0;
spi_device->bits_per_word = ;
spi_device->irq = -;
spi_device->controller_state = NULL;
spi_device->controller_data = NULL;
strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE);
status = spi_add_device(spi_device); if (status < ) {
spi_dev_put(spi_device);
printk(KERN_ALERT "spi_add_device() failed: %d\n",
status);
}
} put_device(&spi_master->dev); return status;
}
稍微有点复杂,这是个完整的样板.你完全可以只更改spi_device中指定域来服务你自己的驱动.
注册spi_driver,首先要用驱动名字还有些回调函数来初始化他.至少你得提供一个probe()函数,让他能够找到他的另一半spi_device.
范例:
static struct spi_driver spike_driver = {
.driver = {
.name =this_driver_name,
.owner =THIS_MODULE,
},
.probe =spike_probe,
.remove =spike_remove,
};
具体的也可参考linux/spi/spi.h文件
接着就可一在某个地方调用spi_register_driver()进行注册了.
spi_register_driver(&spike_driver);
本文转自:http://blog.csdn.net/wuhzossibility/article/details/7831652
SPI protocol驱动编写实例的更多相关文章
- Linux驱动:SPI驱动编写要点
题外话:面对成功和失败,一个人有没有“冠军之心”,直接影响他的表现. 几周前剖析了Linux SPI 驱动框架,算是明白个所以然,对于这么一个庞大的框架,并不是每一行代码都要自己去敲,因为前人已经把这 ...
- linux内核SPI总线驱动分析(一)(转)
linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析 (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...
- Linux内核中SPI总线驱动分析
本文主要有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程): 另一个是SPI总线驱动的编写(不用研究具体的实现过程). 1 SPI概述 SPI是英语Serial Peripheral ...
- linux驱动开发—基于Device tree机制的驱动编写
前言Device Tree是一种用来描述硬件的数据结构,类似板级描述语言,起源于OpenFirmware(OF).在目前广泛使用的Linux kernel 2.6.x版本中,对于不同平台.不同硬件,往 ...
- Linux驱动:I2C驱动编写要点
继续上一篇博文没讲完的内容“针对 RepStart 型i2c设备的驱动模型”,其中涉及的内容有:i2c_client 的注册.i2c_driver 的注册.驱动程序的编写. 一.i2c 设备的注册分析 ...
- v4l2驱动编写篇【转】
转自:http://blog.csdn.net/michaelcao1980/article/details/53008418 大部分所需的信息都在这里.作为一个驱动作者,当挖掘头文件的时候,你可能也 ...
- IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试
IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试 目的不是为了编写TSC2007驱动,是为了学习IIC驱动的编写,读一下TSC2007的ADC数据进行练习,, Linux主机驱动和外设驱 ...
- linux块设备驱动之实例
1.注册:向内核注册个块设备驱动,其实就是用主设备号告诉内核这个代表块设备驱动 sbull_major = register_blkdev(sbull_major, "sbull&quo ...
- liunx中字符驱动编写的简单模板
下面是关于字符驱动两个程序,主要是说明驱动编写的思想,理解驱动是怎么一步一步被实现的. 驱动的第一个实现程序,是相对于裸机编程的,主要是体会一下驱动编程思想: cdev.h: 所包含的头文件 #ifn ...
随机推荐
- 如何组织一个同时面向 UWP/WPF/.Net Core 控制台的 C# 项目解决方案
希望写一个小型工具,给自己和需要的人.考虑到代码尽可能的复用,我准备采用 .Net Standard 来编写大多数核心代码,并基于 .Net Core 编写跨平台控制台入口,用 WPF 编写桌面端 U ...
- windows下gvim中文乱码解决方案
网罗了一些网上的解决windows下gvim中文乱码的解决方案,都试了一遍,可惜都不能完全解决我的所有问题,最后我综合一下网上的两种方案,得到了最后完全解决我的中文乱码问题的方案,配置很简单,就是把下 ...
- Flask第二篇——服务器相关
web服务器.应用服务器和web应用框架 web服务器:负责处理http请求.响应静态文件,常见的有Apache,Nginx以及微软的IIS 应用服务器:负责处理逻辑的服务器.比如php.python ...
- HAL层编写规范
andriod HAL模块也有一个通用的入口地址,这个入口地址就是HAL_MODULE_INFO_SYM变量,通过它,我们可以访问到HAL模块中的所有想要外部访问到的方法. 在Linux系统中,后缀 ...
- elixir jenkins 集成构建方式配置
备注: 主要问题是环境变量配置的问题,解决方法是使用软连接进行解决 1. 下载软件包 wget https://github.com/elixir-lang/elixir/releases/ ...
- 7个GIF动图帮你瞬间理解三角函数
7个GIF动图帮你瞬间理解三角函数 蝌蚪五线谱 百家号04-2120:53 图片来源:IMGUR 三角函数是数学中研究三角形的一个分支,专门阐述三角形的角度和对应边的关系. 有趣的是,定义边角关系的三 ...
- Web Service简介(一)
这篇博文,我们对Web Service进行一个简单的介绍和认识,作为Web Service的入门.在学习之前,你需要对HTML和XML有基本的了解,Web Service并不难,而且非常的简单. 什么 ...
- nginx虚拟机的配置
user nginx nginx;worker_processes 1;pid /data/var/run/nginx/nginx.pid;worker_rlimit_nofile 51200; ev ...
- ubuntu :安装一个方便的终端工具,Guake Terminal
前言: 刚刚用ubuntu不久,就想找点新鲜玩意儿,提高linux能力,当然啦,我喜欢折腾,今天就碰到Guake Terminal这个玩意儿,它的功能很简单,就是一个终端,按F12就出现,再按就隐藏, ...
- Metaweblog博客分发体验
在8月份OpenLiveWriter 这篇文章使用博客客户端撰写做了metaweblog的个人服务,支持通过OpenLiveWriter发博客到本站(OurJS),然后再分发到其他博客平台(目前就os ...