linux中断调用spi函数,Linux下若没有SPI控制器,GPIO火速来救主!

6cc32eeeb5f1157f2afa38ce6a229857.png

[导读] 干过单片机的盆友或许都拿IO口对着时序模拟过SPI主控制器,在做嵌入式Linux设备开发时,发现SPI对应的脚都被用了,或者被当成别的用途了,这时候咋办?你或许会说我翻IO口写个字符驱动不就完了么?当然你可以这么做,然而并没有必要。自己写也挺麻烦且未必稳。憋慌!且看本文分解~

SPI什么鬼?

SPI(Serial Peripheral Interface) 是一种嵌入式系统中应用广泛的同步串行通信、主从架构式总线接口。80年代由摩托罗拉开发,已成为事实标准。

要理解啥是SPI,先上图,一图胜千言:

7150e5d888320f5131f3bd7d610551cd.png

常见的SPI接口有这样几个引脚:

SCLK: 串行时钟,总是主端负责输出(Master)。总是由主端控制该信号,从端为输入采样。

MOSI:主出从入(Master Output Slave Input)。总是由主端控制该信号,从端为输入采样。

MISO:主入从出(Master Input Slave Output)。总是由从端控制该信号,主端为输入采样。

:从选择信号(Slave Select)。总是由主端控制该信号,从端为输入采样。

常见的两种总线连接方式,

方式一:独立片选

3e859fc0a129e6aece58459463fb1140.png

每个从设备都有独立的片选引脚 ,主机同一时间段内,与一个从设备进行通信,也即选中一个从设备,其他线并接共用

方式二:菊花链

11a7348c2dba663dedd37c47dce0ccf2.png

SCK/CS共用,数据线入出环形链接,bit流在SCK时钟作用下击鼓传花,逐次移位传递。

Linux下SPI框架

一图胜千言,看看我画的图吧:

d115b6b775d11b3cf9a2b323c64df68f.png

spi.c 实现了SPI core的公共抽象,SPI core负责抽象所有控制器具有的功能代码,并同时为spi protocol驱动程序提供接口,例如spi_message,spi_transfer,spi_async等。

SPI controller:SPI控制器层实现不同芯片SPI控制器的差异性具体实现,完成数据的bit级别的收发具体实现,并最终控制其对应的总线。

SPI devie:实现设备驱动,负责从控制器收发数据,并实现应用协议的解析等。

SPI外设控制:逻辑电路层,负责底层的IO电路级控制。

SPI从设备:挂载在具体的SPI总线上的芯片,比如传感器、FLASH存储设备等。

GPIO SPI Master?

前面说自己拿GPIO对着SPI首发时序波形去实现SPI字符设备有点重新造砖的嫌疑,且造出的砖兼容性、稳定性往往都差强人意。辣么,Linux下不这么干,可以怎么干呢?

首先用下面命令打开内核配置界面,来瞅瞅:

make menuconfig

稍等那么一会儿,熟悉的界面就出来了:

33ebcf73e283d0ef0baf2b62fe7f812e.png

进入Device Drivers:

89317941d5087d01751807bbe150e0c9.png

进入到SPI support,按Y选择:

GPIO-based bitbanging SPI Master,这便是GPIO SPI主控制器的配置项

User mode SPI device driver support,这便是spidev设备驱动的配置项

08cdbef0bb23c404085aaef7f28f3c25.png

完事之后,一顿退出保存配置,记得保存配置,并配了半天没存哈。

设备树配置

前面配置好了GPIO主控制器以及spidev设备驱动,然而如果直接编译,将内核部署到目标板上运行你发现啥也没有。那么还有做什么呢?你需要根据你的板子的情况配置哪些GPIO为SPI主控制对应的引脚!比如我用的ZYNQ,我这样配:

spi {

compatible = "spi-gpio";

#address-cells = <0x1>;

ranges;

sck-gpios = ;

miso-gpios = ;

mosi-gpios = ;

cs-gpios = ;

num-chipselects = <1>;

/* 从设备clients */

device_0@0 {

compatible = "spidev";

reg = <0>;

spi-max-frequency = <500000>;

#address-cells = <1>;

#size-cells = <1>;

spi-rx-bus-width = <1>;

spi-tx-bus-width = <1>;

bits-per-word = <8>;

};

};

主控制器设备树:

compatible = "spi-gpio",这里兼容性表示使用GPIO的主控制器。编译时会自动编译spi-gpio.c

sck-gpios/miso-gpios/mosi-gpios/cs-gpios:为SPI对应的4个脚的配置,后面的则根据目标板进行设置。

num-chipselects:设置有几个片选

从设备设备树:

compatible = "spidev",这里设置spidev对应spidev.c的实现,当然你完全可以自己写个设备驱动,但是对于大部分应用而言没有必要,直接在用户空间实现应用协议不香么?

reg = <0>,括号里如果有多个从设备则依次增加

spi-max-frequency,设定spi频率,这里假定设置为500k

spi-rx-bus-width/spi-tx-bus-width,这里可选,如果是quad等设备则需要设置

bits-per-word:表示一个字节多少位

另外spi-cpol/spi-cpha,则根据设备的SPI模式进行相应配置

spi-3wire:如果对应的设备是3线SPI设备,则可将该属性加上。

部署测试

设备树配置好后,编译加载到目标板上,此时在/dev下就会出现相应的设备 ,比如这样:

7ea6aa63dff9a6cf545d82e6fcfc43be.png

我配了好几个spidev,所以出现这么几个设备。

至于怎么从用户空间测试这些驱动,就是基本的文件open/read/write操作了,这里就不赘述了。

总结一下

本文梳理了一下在SPI受限的情况下,Linux中GPIO用做SPI控制器的方法及实现,不用敲一行代码就妥了。把该驱的芯片就驱起来了。这里一个小的tips:

当面临要写驱动的时候,先查查是否已经有现成的实现,鼓捣鼓捣就能用岂不是妙!

Linux发展至今,为啥能如此广泛应用,从这里也可见一斑。你大部分想到的需求,都基本给你造好了。拿来就用,一用就对!他不香么?

7010f8278a58a6f15e66bb9672e812be.png

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值