SPI使用参考


1. 概述

本文主要介绍在Linux Uboot以及Linux User Space下如何使用SPI接口。

表1-1 规格介绍

外设 最高时钟
2路SPI 72MHz

2. SPI控制


2.1. Uboot下使用SPI

2.1.1. SPI Driver分析

Uboot下SPI Driver的源文件路径:boot/drivers/mstar/spi/pioneer3/mspi.c

主要的API函数介绍如下:

API名 功能
MDrv_MSPI_Init 初始化SPI,配置PADMUX
MDrv_MSPI_DCConfig 配置SPI Timing,使用默认配置即可
MDrv_MSPI_SetMode 设置SPI工作模式
MDrv_MSPI_FRAMEConfig 配置SPI传输的数据格式
MDrv_MSPI_SetCLK 设置SPI工作时钟
MDrv_MSPI_ChipSelect SPI片选
MDrv_MSPI_Write SPI写数据
MDrv_MSPI_Read SPI读数据
MDrv_MSPI_DMA_Write SPI使能DMA写数据
MDrv_MSPI_DMA_Read SPI使能DMA读数据
HAL_MSPI_FullDuplex SPI全双工通讯,边写边读
HAL_MSPI_Set3WireMode 配置SPI为3Line模式
HAL_MSPI_SetLSB 配置SPI传输时低位优先,默认高位优先

2.1.2. SPI PADMUX配置

SPI Driver源文件的代码中提供了padmux table,列举了平台支持的SPI PADMUX MODE,用户可对照CheckList表格找到对应的管脚(建议使用demo板推荐的mode)。

若使用MSPI0,默认配置是PINMUX_FOR_SPI0_MODE_4,可通过修改MSPI0_PADMUX_MODE的值,选择不同的PADMUX;若使用MSPI1,默认配置是PINMUX_FOR_SPI1_MODE_5, 可通过修改MSPI1_PADMUX_MODE的值,选择不同的PADMUX。

2.1.3. SPI功能测试

Uboot下提供了测试SPI通讯的源文件以及相关命令,路径:boot/common/cmd_spi.c

用户可参考do_spi函数实现,编写应用代码。

menuconfig中打开下述选项,使能SPI Driver与测试命令。

Command line interface

-> Device access commands
        -> [*] sspi

Device Drivers

-> [*] MStar drivers
    -> [*] SSTAR MSPI

硬件上可将SPI的SDI脚与SDO脚接在一起,如果发送的数据与接收的数据一致,说明SPI通讯正常。Uboot下运行# sspi 1:0.0 1 55测试SPI通讯。

命令解释:sspi [mspi0/mspi1]:[cs].[mode] [size] [data],传输数据格式默认是8bits。


2.2. UserSpace下使用SPI

推荐使用如下mode和腳位,如需修改请根据CheckList表格更改。

Spi Group Mode SPI_CZ SPI_CK SPI_DI(MOSI) SPI_DO(MISO) DEV
SPI 0 4 PAD_KEY10 PAD_KEY11 PAD_KEY12 PAD_KEY13 /dev/spidev0.0
SPI 1 5 PAD_KEY0 PAD_KEY1 PAD_KEY2 PAD_KEY3 /dev/spidev1.0

以下均以SPI1_MODE_5为例,PIN脚为PAD_KEY0 ~ PAD_KEY3。

2.2.1. Kernel中配置dts

打开kernel/arch/arm/boot/dts/pioneer3.dtsi文件,配置spi1设备树,可打开或关闭DMA功能,如下图标记所示。

2.2.2. Kernel中配置padmux

打开kernel/arch/arm/boot/dts/ pioneer3-ssc020a-s01a-demo-padmux.dtsi文件,配置spi脚位的padmux,如果该组脚位被复用为其他功能,需要将其他组注释。

将PIN脚配置为PINMUX_FOR_SPI1_MODE_5,如图:

2.2.3. Kernel中启用SPI功能

menuconfig中配置如下选项,启用SPI功能:

Device Drivers

->  [*] SPI support
    ->  <*> User mode SPI device driver support
->  [*] SStar SoC platform drivers
    ->  <*> SStar MSPI driver

如果SPI功能配置成功,kernel起来后在开发板/dev目录下会找到spidev0.0与spidev1.0两个节点。

2.2.4. UserSpace下测试SPI通讯

提供测试用sample code源文件mspi_main.c

按如下操作编译源文件,生成可执行bin档并测试SPI通讯。

# arm-linux-gnueabihf-gcc -o mspi_main mspi_main.c

将mspi_main文件拷贝到开发板中,shell下运行# ./mspi_main 8 55

命令解释:./mspi_main [bits] [data],该应用设置SPI传输的数据格式[bits],并将获取字符串转换成数据[data],通过SPI_DI(MOSI)脚发送出去,并接收SPI_DO(MISO)脚输入的数据。硬件上将SPI_DI(MOSI)与SPI_DO(MISO)引脚接在一起,如果发送的数据与接收的数据一致,表明SPI通讯正常。

2.2.5. 读寄存器判断SPI配置是否正确

如果SPI通讯异常,首先检查硬件连接是否正确;再检查SPI寄存器配置是否正确。在kernel驱动文件中提供了padmux table并列举了寄存器基地址、偏移地址以及有效位。打开kernel/drivers/sstar/gpio/pioneer3/mhal_pinmux.c文件,找到SPI脚位。

当SPI配置为PINMUX_FOR_SPI1_MODE_5时,对应的寄存器信息如图:

基地址 PADTOP_BANK 0x103C
偏移地址 REG_SPI1_MODE 0x68
有效位 BIT10|BIT8 0x0500

开发板中运行/customer/riu_r 0x103C 0x68读寄存器的值,如果读出的值为0x0500则表明SPI PADMUX寄存器配置正确。注意!!!由于GPIO MODE的优先级更高,如果该组脚位要配置为SPI MODE,则需保证该组脚位为非GPIO MODE。


3. GPIO模拟SPI


3.1. 确定GPIO脚位

SPI是标准的通讯协议,可通过控制GPIO电平变化模拟SPI读写时序,实现数据的读写。首先需要找四个管脚,分别作为CLK、CS、MOSI、MISO。在UserSpace下使用GPIO需要确定硬件管脚对应的GPIO ID号,kernel中提供了相关的头文件,列举了每个管脚对应的ID。如下:

kernel/drivers/sstar/include/pioneer3/gpio.h

以下仍然以PAD_KEY0 ~ PAD_KEY3为例,该组脚位对应的GPIO ID如图:


3.2. 测试GPIO模拟SPI功能

提供测试用sample code源文件mspi_gpio.c

按如下操作编译源文件,生成可执行bin档并测试SPI通讯。

# arm-linux-gnueabihf-gcc -o mspi_gpio mspi_gpio.c

将mspi_gpio文件拷贝到开发板中,shell下运行# ./mspi_gpio 8 55

命令解释:./mspi_gpio [bits] [data],该应用设置SPI传输的数据格式[bits],并将获取字符串转换成数据[data],通过MOSI脚发送出去,并接收MISO脚输入的数据。硬件上将MOSI与MISO引脚接在一起,如果发送的数据与接收的数据一致,表明GPIO模拟SPI通讯功能正常。

说明:sample code主要是介绍GPIO模拟SPI的软件实现方法,使用此方式GPIO模拟SPI读写时钟速率为4K左右,如要提高时钟频率则需使用更快的读写GPIO的方式,详见GPIO使用参考。