定制网站平台的安全设计爱站站长工具
文章目录
- 1.协议:芯片和芯片间通讯,4个pin,M(master)I(input)
- 2.spi总线的验证方法:如下测得返回也是1
- 3.spi控制器驱动:波形是由spi控制器拉出,dev节点进行数据发送和接收
- 3.1 platform_get_resource:获取pdev resource(probe函数传入pdev,设备树中所有节点被转换为platform_device,设备树中reg和interrupts属性转为resource,reg是索引0,interrupts是1)
- 4.设备驱动模型:platform_driver和platform_device都需要注册,注册时都会和对方比较(通过platform_bus_type的match函数比较),如果match函数返回成功,则匹配上调用probe
- 5.spi设备树处理过程:compatible属性找到spi_master驱动(如spi-gpio.c),spi_master驱动probe里会of_register_spi_device(struct spi_device , of_find_property读设备树属性填充spi_device,最后spi_add_device注册spi_device)
- 6.spidev的使用(spi用户态api):spidev.c访问spi_device进而访问spi_master里传输函数访问硬件
- 7.使用spidev操作SPI_DAC模块:转为模拟信号
- 8.衍生协议:Dual/Quad SPI(只针对SPI Flash而言,不是针对所有SPI外设)
1.协议:芯片和芯片间通讯,4个pin,M(master)I(input)
主设备总是生成时钟,其速度可达80Mhz,实际没有速度限制(也远比I2C快),ss线(片选同一时刻只有一个有效,保证数据不干扰)也由主设备管理。
eeprom有1024位存储空间即128(如下8x8x2)
个字节(不是FF十进制255个字节),每个字节都有属于自己的地址,那怎么读取这1024位数据呢?最直接的办法就是给每一位都外接一根线,显然不现实,spi只需4根线
就可读写1024bit数据了,一般ss为低电平有效,但是看93c46手册高电平有效。
如下7位地址码不同的排列组合就有2的7次方=128种,正好访问存储器的128个字节。把高低电平通过mosi引脚发出去,数据就能成功写入?不是,因为spi是串行同步通信
,数据线要和时钟线
配合。
SS片选信号被拉高后,从设备开始生效。芯片资料上有2个特殊寄存器配置位:CPOL(极性:sck空闲时时钟信号高还是低电平,1高,数据传输从跳变沿开始)。
CPHA(相位:sck的1个周期2个跳变沿,0从第1个跳变沿采样,1从第2…)。
如下就是spi的4中模式:
如下控制寄存器设置极性和相位,状态寄存器表示数据已经发送完成或使能中断,波特率寄存器是设置时钟频率,数据寄存器是写入数据并一位一位发送出去,同时从DI引脚上采样数据。
2.spi总线的验证方法:如下测得返回也是1
如下clk空闲时为高且在第二个跳变沿采样即上升沿采样。第三条线上数据如下,10进制为49即数字1。
如下三个管脚用的是spi3,所以配置spi3。
下面dtsi描述的就是spi控制器,控制器也是驱动,pinctrl描述gpio配置。
如下看手册里Address Mapping:所有的寄存器的基地址如fe640000。
如下添加设备。
3.spi控制器驱动:波形是由spi控制器拉出,dev节点进行数据发送和接收
如下获取设备树的reg,再做ioremap(因为寄存器地址kernel没法直接访问)。如下rs就是自己定义的结构体,最后会赋值给ctrl。
如下还是在probe函数中,如下第一行的函数调用platform_get_resource(dev,IORESOURCE_IRQ,num)。
如下第一行是不是休眠唤醒,pdev->id是3,mode_bit默认0。
3.1 platform_get_resource:获取pdev resource(probe函数传入pdev,设备树中所有节点被转换为platform_device,设备树中reg和interrupts属性转为resource,reg是索引0,interrupts是1)
如下源码num_resource就是上面的reg和interrupt的2个资源。
如下因为从pdev拿出resource(内存区域,中断等)。
4.设备驱动模型:platform_driver和platform_device都需要注册,注册时都会和对方比较(通过platform_bus_type的match函数比较),如果match函数返回成功,则匹配上调用probe
5.spi设备树处理过程:compatible属性找到spi_master驱动(如spi-gpio.c),spi_master驱动probe里会of_register_spi_device(struct spi_device , of_find_property读设备树属性填充spi_device,最后spi_add_device注册spi_device)
如下是spi_master(不是spi_slave)必须有的属性。
如下bits_per_word不是来自设备树,应用程序发起传输可设置这个值,表示每次传输的bit数。spi_device结构体里有master父节点,所以可用spi_master的传输函数。
6.spidev的使用(spi用户态api):spidev.c访问spi_device进而访问spi_master里传输函数访问硬件
minor次设备号来自位图中第一个未被占用的号码,片选chip_select来自设备树,表示是这个spi_master下的第几个设备。device_create去创建/dev/spi…节点。
open时候如何根据minor…实现在spidev_open函数如下,devt含有主次设备号,要和打开的设备节点的主次设备号(inode->i_rdev)比较,相等的话就是找到了这个设备,找到后分配发送和接收缓冲区,flip->private_data=spidev将spidev即spidev_data存入打开文件的私有数据里,read时候直接取出,就不需要重新找到这spi设备。
内核提供测试程序:tools/spi/spidev_fdx.c:spidev_fdx -r 100 /dev/spidevB.D。main函数中调用do_read -> read
,驱动中.read=spidev_read,spidev_read调用如下spidev_sync_read(同步,等待结果),读完后再copy_to_user拷贝回用户空间,write同理。
不同上面do_read方式,如下用ioctl实现同时读写,读和写的长度是一样的,注释了xfer[1]。
7.使用spidev操作SPI_DAC模块:转为模拟信号
数据可以通过DOUT传给下一个芯片,也可以传给master如下图。
同时写和读,只能用ioctl,先传输tx_buf[0](存入高字节数据),后传输tx_buf[1](存入低字节数据)。如下dac_test.c。
如下底板原理图,第四组gpio的第26个引脚。
pulse duration脉冲持续时间。一个周期包含高低电平。
insmod spidev.ko,出现/dev/spidev0.0节点。
将dac_test.c第64行右移2位,如下就是600。
如下spi->modalias就是设备树中compatible。
8.衍生协议:Dual/Quad SPI(只针对SPI Flash而言,不是针对所有SPI外设)
Dual SPI
:上面讲的是standard spi全双工(同时发送和接收),对于SPI Flash,全双工并不常用(bmc主设备MOSI发送数据,flash从设备不需要MISO返回数据),因此扩展了mosi和miso的用法,让它们工作在半双工(2根线同时发或收),用以加倍数据传输。发送一个命令字节进入dual mode,这样MOSI复用成SIO0(serial io0),MISO复用成SIO1(serial io1),这样一个时钟周期内就能传输2个bit数据。
Quad SPI
:在Dual SPI的基础上增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit。