linux中spi驱动框架

手把手教你调试Linux SPI驱动:从spi_message到transfer_one的完整流程解析 本文深入解析Linux SPI驱动调试全流程,从spi_message构建到transfer_one硬件交互,详细讲解同步(spi_sync)与异步(spi_async)传输机制。针对数据错位、时钟异常等典型问题,提供逻辑分析仪抓包、内核调试接口等实用工具链,帮助开发者快速定位SPI驱动问题并优化性能。 阅读详情
原

linux中spi驱动框架

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设备驱动层

spi_device对应某个特定的slave

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	0x20
  u8 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 驱动框架- spi-mem 框架 那么问题来了, 为什么要开发新的 SPI 存储器接口?有了这个新的框架, SPI NOR 和SPI NAND 都可以基于相同的SPI控制器驱动进行支持了。m25p80 驱动将被修改成,使用spi-mem 接口,取代具有局限性的spi_flash_read() 接口。目前, 我们仍然有专用的SPI NOR控制器,但是最终是移除他们,并将他们移植为 drivers/spi/ 下 的普通SPI控制器驱动。 阅读详情

相关推荐

RK3568平台开发系列讲解(Linux系统篇)SPI 客户端通信

SPI I/O模型由一组队列消息组成。我们提交一个或多个struct spi_message结构时,这些结构以同步或异步方式处理完成。单个消息由一个或多个struct spi_transfer对象组成,每个对象代表全双工SPI传输。这是驱动程序和设备之间交换数据的两个主要结构。它们都定义在include/linux/spi/spi.h中

内核笔记 948

linux驱动学习笔记(九)SPI

前言 SPI协议是由摩托罗拉公司提出的串行通信协议,是一种高速全双工的通信总线。常见的SPI接口包含四根线,MOSI(主设备输出,从设备输入),MISO(主设备输入,从设备输出)SCLK(时钟,决定通信速率),CS(片选,用于多从机)。所以一根SPI总线也可以挂载多个设备,是用多个片选IO来区分。 时序介绍 1.空闲状态 CS脚拉高时候SPI设备处于空闲状态。 2.起始信号与终止信号 CS脚下降沿时候为起始信号 CS脚上升沿时候为停止信号。 3.数据传输(四种工作模式) (1)CPOL=0,串行时钟空闲状态

weixin_35429431的博客 2004

Linux——Linux驱动之玩转SPI(上)Linux下SPI驱动框架简析及SPI设备驱动代码框架实现步骤

上几篇系列博文总结了如何编写Linux下的I2C驱动,接下来的两篇博文总结下如何编写Linux下的SPI驱动,SPI作为相当常用的串口通信协议之一,我们是一定要掌握的。接下来两篇博文的最终目的是驱动一款常见的SPI接口AD芯片AD7606,可以在应用程序中读取AD转换的数据。本次博文先总结下Linux下SPI框架、SPI设备驱动框架实现步骤、SPI设备与驱动的匹配过程。......

数字世界 万物互联 1059

Linux内核4.14版本——SPI框架(2)——重要的数据结构

目录 1. 简介 2. struct spi_controller 3. struct spi_device 4. 传输相关 4.1 struct spi_message 4.2 struct spi_transfer 1. 简介 SPI子系统中有几个重要的结构体,spi_master、spi_message、spi_transfer等,他们之间的关系如图所示,还有一个spi_device结构体。 2. struct spi_controller 这个结构体比较大,这...

yangguoyu8023的博客 2521

玩转Linux下SPI驱动框架简析及SPI设备驱动代码框架实现步骤

在注册SPI设备驱动时,使用spi_register_driver函数进行注册,而在注销SPI设备驱动时,使用spi_unregister_driver函数进行注销。在Linux系统中,为了实现SPI设备的驱动,我们需要了解Linux下SPI驱动框架的工作原理,并按照相应的步骤实现SPI设备驱动代码框架。然后,通过调用spi_add_device函数将创建的SPI设备注册到SPI主控制器中。spi_master表示SPI主控制器,而spi_device则表示连接到SPI主控制器的具体设备。

Orion_O的博客 317

5分钟搞定阿里云千问大模型API申请:手把手教你获取API Key

本文提供了一份高效的阿里云通义千问大模型API Key获取实战指南。通过清晰的步骤,帮助开发者在五分钟内完成从账号准备、精准导航控制台到创建并验证API Key的全过程,并强调了密钥安全管理和基础调用测试的重要性,助力快速集成AI能力。

ol789012345的博客 1345

Linux驱动开发学习笔记-SPI设备驱动

SPI 驱动框架和 I2C 很类似,都分为主机控制器驱动和设备驱动,主机控制器也就是 SOC的 SPI 控制器接口。1. SPI 主机驱动 Linux 内核使用 spi_master 表示 SPI 主机驱动,spi_master 是个结构体,定义在 include/linux/spi/spi.h 中。 struct spi_master { struct device dev; struct list_head list; ...... s16

weixin_45593094的博客 1655

基于C#的ASP.NET开发的党史学习网站课设

开展党史学习教育,就是要以史为镜、以史明志,把苦难辉煌的过去、日新月异的现在、光明宏大的未来贯通起来,在鉴往知来中砥砺前行,在乱云飞渡中把准航向,在凝心聚力中团结奋斗,共同创造新的历史伟业。登陆按钮与数据库进行连接,逻辑实现是如图3.1.3所示,自己定义一个SQL查询语句,将账号、密码放入SQL查询语句中,用sqlDataReader.HasRows语句进行逐一比较,找出结果,将用户名存入session并调用cookies,如果结果存在就关闭数据库,进行数据跳转,并弹出登陆成功的提示框,并关闭数据库。

m0_62408555的博客 974

Linux SPI驱动框架

Linux SPI总线使用 原文链接:https://blog.youkuaiyun.com/weixin_42397613/article/details/105018016 简介 SPI总线是很常用的总线类型,有好多设备的数据接口都采用了SPI总线,比如ICM20608加速度陀螺仪传感器。在Linux中,SPI设备是采用了Linux惯用的设备模型:driver->bus->device,此总线类型是SPI总线,driver就是我们针对某一SPI设备所编写的设备驱动,使用bus给我们提供的SPI总线操控

宁静致远的博客 3655

Python实战:5分钟搞定N-CMAPSS航空发动机数据集解析(附完整代码)

本文提供了一份针对N-CMAPSS航空发动机数据集的快速解析实战指南。通过Python的h5py库,详细演示了如何读取HDF5文件结构、理解数据分类(如传感器、健康参数、场景描述符)并加载为Pandas DataFrame。文章还澄清了数据集中常见的变量数量疑惑,并给出了从数据加载到构建剩余使用寿命预测模型预处理流水线的完整代码,帮助工程师和研究人员高效入门航空发动机预测性维护分析。

weixin_29057065的博客 422

37、基于铁电场效应晶体管(FeFET)的片上深度神经网络(DNN)直接反馈对齐训练

本文提出了一种基于铁电场效应晶体管(FeFET)的深度神经网络(DNN)训练加速器架构,结合直接反馈对齐(DFA)算法和FeFET的独特物理特性,以解决当前DNN训练中反向传播(BP)算法带来的高计算开销、复杂数据依赖和高能耗问题。通过设计基于FeFET的MVM引擎、低功耗ADC和随机数生成器(RNG),该架构在速度和功率效率方面相比现有基于ReRAM的加速器分别提升了1.3倍和2.5倍。研究为未来高效能AI训练硬件的发展提供了新的思路和实现路径。

wine的专栏 162

Linux SPI驱动框架剖析

转载地址:http://blog.youkuaiyun.com/kunkliu/article/details/72983590Linux SPI驱动框架剖析 http://www.cnblogs.com/lubiao/p/4806146.html (说明:我的开发平台是TQ210,处理器是cotex-A8架构的s5pv210,Linux内核版本:linux-3.10.46。) 一、SPI(Serial Per

kunkliu的博客 2049

基于ESP32的智能无线广播系统开发博客

通过本项目的开发,我们成功地实现了基于ESP32的智能无线广播系统。该系统不仅具备传统广播的功能,还实现了通过Wi-Fi无线传输音频、实时广播和智能控制等多种先进功能。未来,随着技术的进一步发展,我们还可以扩展更多功能,如智能推荐广播内容、支持语音识别和控制等。希望本项目能够为嵌入式开发人员提供一些思路和参考,帮助大家在实际开发中更好地应用ESP32平台,开发出更加智能和实用的无线广播系统。

2201_76125393的博客 423

Linux SPI驱动框架(1)——核心层

概述 linux SPI驱动框架主要分为核心层,控制器驱动层以及设备驱动层。具体结构可参考下图 图中,最下层是硬件空间,SPI总线控制器,总线控制器负责硬件上的数据交互, ...

深海 3391

Android 15.0 系统开机屏幕设置默认横屏显示

在15.0的系统ROM产品定制化开发中,对于产品需求来说,由于是宽屏设备所以产品需要开机默认横屏显示,开机横屏显示这就需要从 两部分来实现,一部分是系统开机动画横屏显示,另一部分是系统屏幕显示横屏显示,从这两方面就可以做到开机默认横屏显示了

安卓兼职framework和app工程师的博客 719

SAP Group Reporting入门指南(8)--业务操作

关于资产负债表类的匹配,系统预设了SGR01和SGR02两个方法,主要区别在于数据的来源范围,SGR01取自ACDOCA和ACDOCU,如果是0F类型的就会直接显示日记账分录(期间是000的除外,这类凭证是年结结转的,系统不再跨年追溯),如果是其他类型就显示合并分录。这里是我觉得SAP还需要优化的地方。基于ICMR的抵消任务中通常将抵销差异细分为交易差异、货币换算差异和其他差异,这在基于重分类抵消任务是无法实现的,基于重分类抵消只知道一个差异总额,很难从合并抵消凭证看出差异的来源,也没有审计线索可言。

bflyfish的博客 275

Linux SPI 驱动分析(1)— 结构框架

目录 1、总线互联拓扑结构 1.1、硬件拓扑 1.2、软件抽象 2、SPI 软件驱动层次 3、数据结构 3.1、spi_controller (spi_master) 3.2、spi_device 3.3、spi_driver 3.4、spi_board_info 3.5、spi_transfer 3.6、spi_message 3.7、数据结构之间的关系 4、对外接口 ...

StephenZhou 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Linux spi驱动框架分析(二)

spi core Linux spi驱动框架分析(一) spi核心(dervers/spi/spi.c)中提供了一组不依赖于硬件平台的接口函数,理解其中的主要函数非常关键,因为spi_master驱动和spi设备驱动之间赖于i2c核心作为纽带。spi核心中提供的主要函数如下。 (1) 为spi_master驱动提供的接口 //分配spi_master结构体 struct spi_master *spi_alloc_master(struct device *dev, unsigned size); //注

m0_46525308的博客 1529

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

linux 添加spi 驱动,linux驱动之spi框架

一、前言前面我们简单的介绍了 I2C总线 的基本框架,本文则将继续讲述另一种常用的 外设总线,即 SPI总线。SPI总线 常用于 传感器或者flash等外设。本文将沿着 SPI总线驱动代码,从整体上梳理一下 SPI框架 的使用及原理。注意:本文将假设读者已经熟悉SPI总线协议,如若有读者不熟悉请自行查阅资料二、正文本节将使用 m25p80 这个驱动文件,m25p80 是常用 flash 的驱动代码...

weixin_30045597的博客 1179

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Linux SPI驱动框架(4)——spi-mem驱动

@[TOC](Linux SPI驱动框架(4)——spi-mem驱动) 前言   spi-mem驱动为SPI存储器生态带来一些一致性,该框架实现了在spi nor设备、spi nand设备、以及常规spi外设上复用spi控制器驱动。 Kernel版本:5.14.9 SPI控制器驱动   传统内核中,spi nor有单独的驱动,芯片厂商根据使用的spi控制器驱动,实现对应的spi-nor驱动。spi-nor驱动只分为driver和core层。但是这种情况下,该spi控制器,就不能再提供给其他外设使用了。以及随

深海 5794

linux驱动系列学习之spi框架源码分析

spi框架分析

zichuanning520的博客 2362

嵌入式Linux SPI驱动 编写SPI驱动框架 OLED模块驱动程序

嵌入式Linux SPI驱动 编写SPI驱动框架 OLED模块驱动程序

你要拥有一个你喜欢并且热爱的人生 8127

Linux SPI 驱动分析(2)— 框架层源码分析

介绍spi驱动架构

不能让自己太安逸,努力奋斗才是真 1457

Linux spi驱动框架分析(四)

系列文章: Linux spi驱动框架分析(一) Linux spi驱动框架分析(二) Linux spi驱动框架分析(三) spi_master的消息队列机制 SPI数据传输可以有两种方式:同步方式和异步方式。所谓同步方式是指数据传输的发起者必须等待本次传输的结束,期间不能做其它事情,用代码来解释就是,调用传输的函数后,直到数据传输完成,函数才会返回。而异步方式则正好相反,数据传输的发起者无需等待传输的结束,数据传输期间还可以做其它事情,用代码来解释就是,调用传输的函数后,函数会立刻返回而不用等待数据传输

m0_46525308的博客 1348
上一篇: csdn如何转载别人的文章
下一篇: spi协议->裸机程序->master驱动程序分析
文心雕龍3
博客等级 码龄8年 5粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值