
[导读] 干过单片机的盆友或许都拿IO口对着时序模拟过SPI主控制器,在做嵌入式Linux设备开发时,发现SPI对应的脚都被用了,或者被当成别的用途了,这时候咋办?你或许会说我翻IO口写个字符驱动不就完了么?当然你可以这么做,然而并没有必要。自己写也挺麻烦且未必稳。憋慌!且看本文分解~SPI什么鬼? SPI(Serial Peripheral Interface) 是一种嵌入式系统中应用广泛的同步串行通信、主从架构式总线接口。80年代由摩托罗拉开发,已成为事实标准。 要理解啥是SPI,先上图,一图胜千言: ![]() 常见的SPI接口有这样几个引脚:
常见的两种总线连接方式, 方式一:独立片选, K$ w* d# |# g$ l6 e# z& b
方式二:菊花链) R& U9 R: {' e) t' U# s1 n
SCK/CS共用,数据线入出环形链接,bit流在SCK时钟作用下击鼓传花,逐次移位传递。 一图胜千言,看看我画的图吧: ![]()
前面说自己拿GPIO对着SPI收发时序波形去实现SPI字符设备有点重新造砖的嫌疑,且造出的砖兼容性、稳定性往往都差强人意。辣么,Linux下不这么干,可以怎么干呢? 首先用下面命令打开内核配置界面,来瞅瞅: make menuconfig/ |5 p( |/ X( q稍等那么一会儿,熟悉的界面就出来了: ![]() 进入Device Drivers: ![]() 进入到SPI support,按Y选择:
![]() 完事之后,一顿退出保存配置,记得保存配置,别配置了半天没存哈。) b1 b- { h3 K/ W; I0 B 前面配置好了GPIO主控制器以及spidev设备驱动,然而如果直接编译,将内核部署到目标板上运行你发现啥也没有。那么还要做什么呢?你需要根据你的板子的情况配置哪些GPIO为SPI主控制对应的引脚!比如我用的ZYNQ,我这样配: spi {compatible = "spi-gpio";! ~+ `: C+ x/ v #address-cells = <0x1>;% N+ y' p/ b' V- j" h+ a) _1 u) H ranges;6 k1 p2 S, e- ]& R- E sck-gpios = <&gpio0 7 0>; miso-gpios = <&gpio0 11 0>;9 v# G# l! _ u8 _ mosi-gpios = <&gpio0 10 0>;: J0 \* ~ s# c' u cs-gpios = <&gpio0 12 0>;1 C4 {. N! n4 i num-chipselects = <1>; /* 从设备clients */1 q" J# O) S) z# f( E device_0@0 { compatible = "spidev";6 i9 Y/ V; I8 z% m/ u' Q' E reg = <0>;, o% [/ X" t( _2 E' ]! l3 D1 d spi-max-frequency = <500000>;' N8 c. ~/ ^& R5 U+ P9 o: i% z) ?! Y( F #address-cells = <1>;7 {+ L8 K& ^8 E4 L9 U' t: y1 W2 ?8 ` #size-cells = <1>; spi-rx-bus-width = <1>;/ H5 r6 D! F W; s7 U1 o spi-tx-bus-width = <1>; bits-per-word = <8>; }; }; - L5 y4 ]) [8 i6 p 主控制器设备树:
从设备设备树:
设备树配置好后,编译加载到目标板上,此时在/dev下就会出现相应的设备 ,比如这样: ![]() 我配了好几个spidev,所以出现这么几个设备。 至于怎么从用户空间测试这些驱动,就是基本的文件open/read/write操作了,这里就不赘述了。 总结一下本文梳理了一下在SPI受限的情况下,Linux中GPIO用做SPI控制器的方法及实现,不用敲一行代码就妥了。把该驱的芯片就驱起来了。这里一个小的tips:
Linux发展至今,为啥能如此广泛应用,从这里也可见一斑。你大部分想到的需求,都基本给你造好了。拿来就用,一用就对!他不香么? |