本文介绍,基于USB2.0高速USB转接芯片CH347,配合厂商提供的USB转MPHSI(Multi Protocol High-Speed Serial Interface)Master总线驱动(CH34X-MPHSI-Master)为系统扩展SPI总线的用法,除此之外,还可以扩展I2C总线和GPIO等资源。
驱动软件正常工作后,会在系统下创建新的SPI Master,拥有独立的bus num,原SPI器件的设备驱动可直接通过DTS配置文件或者sysfs节点挂载到该总线上,原有设备驱动无需任何修改。
项目地址:GitHub - WCHSoftGroup/ch34x_mphsi_master_linux
PIN脚 | SPI功能脚 | GPIO复用脚 |
---|---|---|
13 | SCS0 | - |
7 | SCS1 | - |
14 | SCK | - |
16 | MOSI | - |
15 | MISO | - |
PIN脚 | SPI功能脚 | GPIO复用脚 |
---|---|---|
5 | SCS0 | gpio2 |
9 | SCS1 | gpio5 |
6 | SCK | gpio0 |
8 | MOSI | - |
7 | MISO | gpio1 |
SPI接口特性:
SPI模式0/1/2/3
SPI时钟频率60MHz~218.75KHz
MSB/LSB传输
8位/16位传输
2路片选
片选高/低有效
本文基于树莓派4B平台,使用CH347F/T芯片通过树莓派的USB接口扩展SPI总线接口,介绍不同SPI设备的应用实例。
驱动程序默认未开启 spidev 设备创建,如需要使用 /dev/spidev*,在 ch34x_mphsi_master_spi.c 文件中要开放 SPIDEV 宏定义,即修改成:
- #define SPIDEV
- //#undef SPIDEV
- root@raspberrypi:/home/wch/ch34x_mphsi_master_linux_V1.1/driver # make
- make -C /lib/modules/6.1.21-v8+/build M=/home/wch/ch34x_mphsi_master_linux_V1.1/driver modules
- make[1]: 进入目录“/usr/src/linux-headers-6.1.21-v8+”
- CC [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_usb.o
- CC [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_spi.o
- CC [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_i2c.o
- CC [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master_gpio.o
- LD [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master.o
- MODPOST /home/wch/ch34x_mphsi_master_linux_V1.1/driver/Module.symvers
- CC [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master.mod.o
- LD [M] /home/wch/ch34x_mphsi_master_linux_V1.1/driver/ch34x_mphsi_master.ko
- make[1]: 离开目录“/usr/src/linux-headers-6.1.21-v8+”
- root@raspberrypi:/home/wch/ch34x_mphsi_master_linux_V1.1/driver # make load
- insmod ch34x_mphsi_master.ko
将CH347F/T 设备通过USB连接至树莓派,查看系统日志,可看到扩展的SPI总线号为SPI bus 7
- [ 218.193644] ch34x_mphsi_master: loading out-of-tree module taints kernel.
- [ 218.194619] mphsi-ch34x 1-1.2:1.2: ch34x_cfg_probe: output SPI slave with CS0
- [ 218.194633] mphsi-ch34x 1-1.2:1.2: ch34x_cfg_probe: output SPI slave with CS1
- [ 218.195050] mphsi-ch34x 1-1.2:1.2: ch34x_spi_probe: SPI master connected to SPI bus 7
- [ 218.195323] mphsi-ch34x 1-1.2:1.2: ch34x_mphsi_i2c_probe: I2C master connected to I2C bus 22
- [ 218.195645] mphsi-ch34x 1-1.2:1.2: ch34x_mphsi_gpio_probe: registered GPIOs from 501 to 503
- [ 218.195663] mphsi-ch34x 1-1.2:1.2: ch34x_usb_probe: USB to SPI/I2C/GPIO adapter ch34x now attached.
- [ 218.195778] usbcore: registered new interface driver mphsi-ch34x
本节介绍通过CH347的SPI接口操作W25Q16模块,相关资料:LibDriver W25QXX,是LibDriver推出的W25QXX全功能驱动,该驱动提供Flash读取,Flash写入等功能并且它符合MISRA标准)
获得资料包后,进入w25qxx-master/project/raspberrypi4b目录,根据README编译得到可执行文件w25qxx.
注:
需进入w25qxx-master\project\raspberrypi4b\driver\src目录,修改raspberrypi4b_driver_w25qxx_interface.c文件,替换成CH347驱动创建的/dev/spi7.0节点设备。
#define SPI_DEVICE_NAME "/dev/spidev0.0" 修改为:
#define SPI_DEVICE_NAME "/dev/spidev7.0"
根据README运行可执行文件
寄存器测试
- root@raspberrypi:/home/wch/w25qxx-master/project/raspberrypi4b/build # ./w25qxx -t reg --type=W25Q16 --interface=spi
- w25qxx: chip is Winbond W25QXX.
- w25qxx: manufacturer is Winbond.
- w25qxx: interface is SPI QSPI.
- w25qxx: driver version is 1.0.
- w25qxx: min supply voltage is 2.7V.
- w25qxx: max supply voltage is 3.6V.
- w25qxx: max current is 25.00mA.
- w25qxx: max temperature is 85.0C.
- w25qxx: min temperature is -40.0C.
- w25qxx: start register test.
- w25qxx: w25qxx_set_type/w25qxx_get_type test.
- w25qxx: set type W25Q80.
- w25qxx: check chip type ok.
- w25qxx: set type W25Q16.
- w25qxx: check chip type ok.
- w25qxx: set type W25Q32.
- w25qxx: check chip type ok.
- w25qxx: set type W25Q64.
- w25qxx: check chip type ok.
- w25qxx: set type W25Q128.
- w25qxx: check chip type ok.
- w25qxx: set type W25Q256.
- w25qxx: check chip type ok.
- w25qxx: w25qxx_set_interface/w25qxx_get_interface test.
- w25qxx: set interface SPI.
- w25qxx: check chip interface ok.
- w25qxx: set interface QSPI.
- w25qxx: check chip interface ok.
- w25qxx: w25qxx_get_manufacturer_device_id test.
- w25qxx: manufacturer is 0xEF, device id is 0x14.
- w25qxx: w25qxx_get_jedec_id test.
- w25qxx: manufacturer is 0xEF, device id is 0x40 0x15.
- w25qxx: w25qxx_get_unique_id test.
- w25qxx: unique id 0xE6 0x61 0x74 0xA2 0x43 0x3E 0xA0 0x2B.
- w25qxx: w25qxx_set_status1/w25qxx_get_status1 test.
- w25qxx: status1 is 0x00.
- w25qxx: w25qxx_set_status2/w25qxx_get_status2 test.
- w25qxx: status2 is 0x02.
- w25qxx: w25qxx_set_status3/w25qxx_get_status3 test.
- w25qxx: status3 is 0x60.
- w25qxx: w25qxx_enable_write test.
- w25qxx: check enable write ok.
- w25qxx: w25qxx_disable_write test.
- w25qxx: check disable write ok.
- w25qxx: w25qxx_enable_write test.
- w25qxx: check enable sr write ok.
- w25qxx: w25qxx_erase_program_suspend test.
- w25qxx: check erase program suspend ok.
- w25qxx: w25qxx_erase_program_suspend test.
- w25qxx: check erase program resume ok.
- w25qxx: w25qxx_global_block_lock test.
- w25qxx: check global block lock ok.
- w25qxx: w25qxx_global_block_unlock test.
- w25qxx: check global block unlock ok.
- w25qxx: w25qxx_individual_block_lock test.
- w25qxx: check individual block lock ok.
- w25qxx: w25qxx_read_block_lock test.
- w25qxx: check read block lock ok with 1.
- w25qxx: w25qxx_individual_block_unlock test.
- w25qxx: check individual block unlock ok.
- w25qxx: w25qxx_set_burst_with_wrap test.
- w25qxx: check set burst with wrap ok.
- w25qxx: w25qxx_power_down test.
- w25qxx: w25qxx_release_power_down test.
- w25qxx: w25qxx_enable_reset test.
- w25qxx: w25qxx_reset_device test.
- w25qxx: finish register test.
读写FLASH测试
- root@raspberrypi:/home/wch/w25qxx-master/project/raspberrypi4b/build # ./w25qxx -e write --type=W25Q16 --interface=spi --addr=0x000000 --data=0x08
- w25qxx: addr 0 write data 8.
- root@raspberrypi:/home/wch/w25qxx-master/project/raspberrypi4b/build # ./w25qxx -e read --type=W25Q16 --interface=spi --addr=0x000000
- w25qxx: addr 0 is 8.
SSD1306是一款带控制器的用于OLED点阵图形显示系统的单片CMOS OLED/PLED驱动器。它由128个SEG(列输出)和64个COM(行输出)组成。该芯片专为共阴极OLED面板设计。
参考资料链接:
加载OLED驱动程序
root@raspberrypi:~ # insmod oled_drv.ko
使用sysfs或dts绑定将此spi设备驱动挂载到ch347创建的spi总线
配置driver_override,用于匹配设备和驱动
root@raspberrypi:~ # echo oled_drv > /sys/class/spi_master/spi7/spi7.0/driver_override
此处echo的名称应与驱动中name一致,示例:
- static struct spi_driver spidev_spi_driver = {
- .driver = {
- .name = "oled_drv",
- ...
- }
- ...
- }
解除spidev7.0与原有spidev驱动的绑定
root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/spidev/unbind
进行spi7.0和oled驱动的绑定
root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/oled_drv/bind
进入/sys/bus/spi/drivers/oled_drv目录,可以看到driver指向了对应的device
- root@raspberrypi:/sys/bus/spi/drivers/oled_drv # ls -l spi7.0
- lrwxrwxrwx 1 root root 0 7月 24 16:56 spi7.0 -> ../../../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.1/1-1.1:1.2/spi_master/spi7/spi7.0
或进入/sys/bus/spi/devices/spi7.0目录。可以看到device和driver匹配成功
- root@raspberrypi:/sys/bus/spi/devices/spi7.0 # ls -l driver
- lrwxrwxrwx 1 root root 0 7月 24 17:02 driver -> ../../../../../../../../../../../../../../bus/spi/drivers/oled_drv
运行应用程序
./test_app /dev/spi_oled
查看OLED模块显示内容
TLC5615 为德州仪器公司推出的具有串行接口的数模转换器,输入采用三线SPI串行信号,其输出为电压模拟信号,最大输出电压是基准电压值的两倍,配置简单不需要配置过多的寄存器,仅需使用单5V的电源即可工作。
参考资料 TLC5615 数据表、产品信息和支持 | 德州仪器 TI.com.cn
引脚如图
CH347模块的MOSI连接DIN,作为串行信号输入;OUT脚用于输出模拟电压信号;REFIN为外接参考电压2.048V。
加载TLC5615驱动程序
root@raspberrypi:~ # insmod tlc5615_drv.ko
配置driver_override,用于匹配设备和驱动
root@raspberrypi:~ # echo tlc5615_drv > /sys/class/spi_master/spi7/spi7.0/driver_override
解除spidev7.0与原有spidev驱动的绑定
root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/spidev/unbind
进行spi7.0和tlc5615驱动的绑定
root@raspberrypi:~ # echo spi7.0 > /sys/bus/spi/drivers/tlc5615_drv/bind
分别查看/sys/bus/spi/drivers/tlc5615_drv/spi7.0文件和/sys/bus/spi/devices/spi7.0/driver文件,可以看到device和driver匹配成功。
- root@raspberrypi:~ # ls /sys/bus/spi/drivers/tlc5615_drv/spi7.0 -l
- lrwxrwxrwx 1 root root 0 7月 25 19:01 /sys/bus/spi/drivers/tlc5615_drv/spi7.0 -> ../../../../devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.1/1-1.1:1.2/spi_master/spi7/spi7.0
- root@raspberrypi:~ #
- root@raspberrypi:~ #
- root@raspberrypi:~ # ls /sys/bus/spi/devices/spi7.0/driver -l
- lrwxrwxrwx 1 root root 0 7月 25 19:02 /sys/bus/spi/devices/spi7.0/driver -> ../../../../../../../../../../../../../../bus/spi/drivers/tlc5615_drv
- root@raspberrypi:~ #
驱动加载成功后运行应用程序测量OUT引脚输出电压,OUT脚输出电压 = 2 * VREFIN * n / 1024 = 2 * 2.048 * n / 1024,其中,n为DIN输入的原始值。