linux中spi驱动框架
linux中spi驱动框架
<span class="tags-box artic-tag-box"><span class="label">标签:</span><a data-track-click="{"mod":"popu_626","con":"linux"}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=linux&t=blog" target="_blank">linux </a><a data-track-click="{"mod":"popu_626","con":"spi驱动"}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=spi驱动&t=blog" target="_blank">spi驱动 </a><span class="article_info_click">更多</span></span><div class="tags-box space"><span class="label">个人分类:</span><a class="tag-link" href="https://blog.csdn.net/andylauren/article/category/6289579" target="_blank">嵌入式系统驱动 </a></div></div><div class="operating"></div></div></div>
</div>
<article><div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post" style="height: 996px; overflow: hidden;"><link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-bb1edad192.css"><div class="htmledit_views">
linux下的SPI总线驱动在driver/spi目录中。
SPI驱动分为三层
SPI核心层 drivers/spi/spi.c 与平台无关
SPI控制器驱动层
SPI设备驱动层
每层的主要结构体和函数
SPI控制器驱动层(include/linux/spi/spi.h)
struct spi_master {struct device dev;s16 bus_num;//控制器对应的SPI总线号u16 num_chipselect;//支持片选数量int (* setup) (struct spi_device *spi);//SPI模式设备,在spi_add_device中调用int (* transfer) (struct spi_device *spi,struct spi_message *mesg);//读写方法的函数,可能会睡眠void (* cleanup) (struct spi_device *spi);//注销时候调用
};
SPI设备驱动层
struct spi_driver {int (* probe) (struct spi_device *spi);//匹配时调用,完成spi_transfer,spi_message,spi_message_init,spi_meassage_add_tail,spi_sync,spi_write_then_read的调用int (* remove) (struct spi_device *spi);void (* shutdown) (struct spi_device *spi);int (* suspend) (struct spi_device *spi, pm_message_t mesg);int (* resume) (struct spi_device *spi);struct device_driver driver;
};
struct spi_device {struct device dev;struct spi_master * master;u32 max_speed_hz;u8 chip_select;u8 mode;
#define SPI_CPHA 0x01
#define SPI_CPOL 0x02
#define SPI_MODE_0 (0|0)
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04
#define SPI_LSB_FIRST 0x08
#define SPI_3WIRE 0x10
#define SPI_LOOP 0x20u8 bits_per_word;int irq;void * controller_state;void * controller_data;const char * modalias;
};
struct spi_transfer {const void * tx_buf;void * rx_buf;unsigned len;dma_addr_t tx_dma;dma_addr_t rx_dma;unsigned cs_change:1;u8 bits_per_word;u16 delay_usecs;u32 speed_hz;struct list_head transfer_list;
};
int spi_register_driver ( struct spi_driver * sdrv);
struct spi_message {struct list_head transfers;struct spi_device * spi;unsigned is_dma_mapped:1;void (* complete) (void *context);void * context;unsigned actual_length;int status;struct list_head queue;void * state;
};
在每次使用spi_message可以使用函数:
void spi_message_init(structspi_message *m);
来初始化。
向spi_message添加transfers可以使用spi_message_add_tail()函数:
void spi_message_add_tail(structspi_transfer *t, struct spi_message *m);
一旦你准备好了spi_message,就可以使用spi_async()来向SPI系统提交了:
int spi_async(struct spi_device *spi,struct spi_message *message);
因为是异步的,一提交就立马返回了,这也就是说需要同步机制(complete就是了)。他确保不会睡眠,可安全的在中断handler或其他不可休眠的代码中调用。稍后会念念他的好的。
使用spi_async()需要注意的是,在complete()未返回前不要轻易访问你一提交的spi_transfer中的buffer。也不能释放SPI系统正在使用的buffer。一旦你的complete返回了,这些buffer就又是你的了。
使用完成回调机制稍显复杂,可以使用SPI系统提供的另一个同步版本:spi_sync():
int spi_sync(struct spi_device *spi,struct spi_message *message);
因为是同步的,spi_sync提交完spi_message后不会立即返回,会一直等待其被处理。一旦返回就可以重新使用buffer了。spi_sync()在drivers/spi/spi.c中实现,其调用了spi_async(),并休眠直至complete返回。
spi_device的板信息用spi_board_info来描述,在init函数调用时会初始化。
struct spi_board_info {char modalias[KOBJ_NAME_LEN];const void * platform_data;void * controller_data;int irq;u32 max_speed_hz;u16 bus_num;u16 chip_select;u8 mode;
};
int __init spi_register_board_info ( struct spi_board_info const * info,unsigned n);
会把spi_board_info注册到链表board_list上。
之后,spi_master注册会调用scan_board_info扫描board_list找到挂接在它上面的spi设备。
然后创建并注册spi_device.
一个结构体spi_board_info对应着一个SPI设备spi_device
struct boardinfo{struct list_head list;struct spi_board_info board_info;
}
static LIST_HEAD(board_list);
static LIST_HEAD(spi_master_list);//初始化一个空链表
#define LIST_HEAD(name)
struct list_head name=LIST_HEAD_INIT(name)
#define LIST_HEAD_INIT(name) {&(name),&(name)}
struct list_head {struct list_head* next,*prev;};
struct device_driver结构体被定义在/include/linux/device.h,原型是:
struct device_driver {const char *name;struct bus_type *bus;
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">module</span> *<span class="hljs-title">owner</span>;</span>
<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *mod_name; <span class="hljs-comment">/* used for built-in modules */</span><span class="hljs-keyword">bool</span> suppress_bind_attrs; <span class="hljs-comment">/* disables bind/unbind via sysfs */</span><span class="hljs-keyword">int</span> (*probe) (struct device *dev);
<span class="hljs-keyword">int</span> (*remove) (struct device *dev);
<span class="hljs-keyword">void</span> (*shutdown) (struct device *dev);
<span class="hljs-keyword">int</span> (*suspend) (struct device *dev, <span class="hljs-keyword">pm_message_t</span> state);
<span class="hljs-keyword">int</span> (*resume) (struct device *dev);
<span class="hljs-keyword">const</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">attribute_group</span> **<span class="hljs-title">groups</span>;</span><span class="hljs-keyword">const</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">dev_pm_ops</span> *<span class="hljs-title">pm</span>;</span><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">driver_private</span> *<span class="hljs-title">p</span>;</span>
};
举例SPI驱动
spi_device设备
spi_board_info
init入口调用,spi_register_board_info(S3C_SPI_devs,ARRAY_SIZE(S3C_SPI_devs));
会把spi_board_info注册到board_list链表上。
之后会创建并注册spi_device
spi_driver驱动
1、声明并设置spi_driver结构体
2、注册spi_register_driver(&spi_driver);
3、实现probe操作,spi_transfer,spi_message的构建
spi_message_init,spi_message_add_tail,spi_sync调用
3.1、定义并设置 spi_transfer结构体
3.2、定义spi_message结构体
3.3、初始化meg,spi_message_init(&meg);
3.4、将st放入message队列spi_message_add_tail(&st,&meg);
3.5、将message与spi_device关联,发送meg,spi_sync(spi_device,&meg);
linux中spi驱动框架相关推荐
- imx6 通过移植XRM117x(SPI转串口)对Linux中的SPI驱动框架进行分析
最近分析了一下Linux 中的SPI驱动框架,将自己的理解总结一下,不足之处还请斧正! 1.SPI通信基础知识 SPI(Serial Peripheral Interface)是一种串行(一次发送1b ...
- 转载:Linux kernel SPI驱动解释
From: http://www.cnblogs.com/liugf05/archive/2012/12/03/2800457.html 下面有两个大的模块: 一个是SPI总线驱动的分析 ...
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
Linux驱动修炼之道-SPI驱动框架源码分析(上) SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设 ...
- Linux SPI驱动框架(2)——控制器驱动层
SPI控制器驱动层 上节中,讲了SPI核心层的东西,这一部分,以全志平台SPI控制器驱动为例,对SPI控制器驱动进行说明. SPI控制器驱动,即SPI硬件控制器对应的驱动,核心部分需要实现硬件SP ...
- Linux SPI驱动框架(3)——设备驱动层
SPI设备驱动层 Linux SPI驱动框架(1)和(2)中分别介绍了SPI框架中核心层,和控制器驱动层.其实实际开发过程中,不是IC原厂工程师比较少会接触控制器驱动层,设备驱动层才是接触比较多的 ...
- i.MX6ULL驱动开发 | 13 - Linux SPI 驱动框架
Linux SPI 驱动框架分为两部分: SPI总线控制器驱动:SOC的 SPI 控制器外设驱动 SPI设备驱动:基于SPI总线控制器驱动编写,针对具体的SPI从机设备 一.SPI总线控制器驱动 基于 ...
- Linux SPI驱动框架(1)——核心层
概述 linux SPI驱动框架主要分为核心层,控制器驱动层以及设备驱动层.具体结构可参考下图 图中,最下层是硬件空间,SPI总线控制器,总线控制器负责硬件上的数据交互.内核空间中,需要有对应 ...
- SPI驱动框架源码分析
SPI驱动框架源码分析 2013-04-12 16:13:08 分类: LINUX SPI驱动框架源码分析 SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设 ...
- windows linux 融合,Windows和Linux的设备驱动框架的对比融合研究
摘要:把驱动框架分为三层,针对各层在Windows和Linux中的实现方法的不同,对Windows和Linux的设备驱动框架进行对比研究.从接口函数,应用程序访问驱动程序的路径,驱动程序具体实现及安装 ...
最新文章
- TCP/IP详解--第十五章
- 数据库表设计、 数据库分层、myslq水平拆分、oracle表分区
- JAVA程序中 + 号的使用
- .net动态控件的使用(listview ,treeview,tabControl)
- js怎么图表在html中显示,使用Charts.js在HTML5中创建图表
- 1024 许个愿吧,万一实现了呢?
- php代码 intval( ),php intval的测试代码发现问题_PHP教程
- Unity3D方向键控制人物移动的代码
- 从嵌入式系统到无线模组 周立功单片机欲站在物联网的风口
- 计算字符串相似度算法——Levenshtein
- GnomeSort 又是一个O(n2),不过,只用一次循环……
- qdu yzm10与大富翁的故事 (01背包+输出路径)
- 2022必看花展 IFEX昆明国际花卉园艺展,新展期11月11-13日
- 共享租赁汽车,必将重新设计中国汽车产业链游戏规则
- “完数”问题 求1000以内的完数
- sql语句查询某字段中包含某值(模糊查找)
- 计算机病毒语音,新病毒:让被感染的计算机发出语音提醒
- 无线交换机故障分析排查
- JMeter测试文档
- 【流式细胞仪软件】上海道宁为您带来FCS Express,让您轻松缩小流式细胞术和结果之间的差距