rt-thread/bsp/phytium/libraries/standalone/doc/reference/driver/fspim.md

9.5 KiB
Raw Blame History

FSPIM 驱动程序

1. 概述

  • SPI 总线是一种4线总线提供了一种高速、高效率的串行通信技术。SPI 通信通常有一个主设备和一个或多个从设备需要至少4根线它们是 MISO主设备数据输入、MOSI主设备数据输出、SCLK时钟、CS片选

  • 其中CS是从芯片是否被主芯片选中的控制信号SCLK提供时钟脉冲SDISDO则基于此脉冲完成数据传输

  • 本驱动程序提供了FT2000/4、D2000平台的SPI主设备功能

  • FT2000/4、D2000上包含 2 个通用 SPI 接口,仅作为通用 SPI 主设备使用,外部最多挂载 4 个 SPI 从设备

2. 功能

  • 驱动相关的源文件如下,
  • drivers/spi/fspim
.
├── fspim.c
├── fspim.h
├── fspim_g.c
├── fspim_hw.c
├── fspim_hw.h
├── fspim_intr.c
├── fspim_options.c
└── fspim_sinit.c
  • FSPIM 常用于读写Nor-flash其应用可以参考以下结构最底层的硬件是 SPI 主机控制器和 Nor-flash, 其上由 FSPIM 驱动和 SFUD 提供 Spi Nor-flash的读写接口面向SPI文件系统如 LittleFS 和 SPIFFS文件系统提供负载均衡、坏块检测和断电保护等特性并为上层应用提供文件创建/读写等接口,使用方法参考4 应用示例

spi_app

3. 配置方法

以下部分将指导您完成 FSPIM 驱动的软件配置:

3.1 使用 SFUD 通用SPI协议框架

  • 使能 CONFIG_USE_FSPIM 和 CONFIG_USE_SFUD 配置
  • 初始化 SFUD 框架
  • 调用 SFUD 提供的 API 读写 SPI 从设备

关于 SFUD 框架的使用,可以参考sfud.md

3.2 不使用 SFUD 通用SPI协议框架

  • 使能 CONFIG_USE_FSPIM 配置
  • 初始 FSPIM 驱动
  • 调用 FSPIM 提供的 API 读写 SPI 从设备,需要按照 SPI 从设备的手册实现相关的命令和协议

4 应用示例

SPI 回环测试

SPI Norflash读写测试

SPI Norflash文件系统测试-LittleFS

SPI Norflash文件系统测试-SPIFFS

4. API参考

4.1 用户数据结构

  • SPIM 驱动配置数据
typedef struct
{
    u32                  instance_id;  /* Device instance id */
    uintptr              base_addr;    /* Device base address */
    u32                  irq_num;      /* Device intrrupt id */
    u32                  irq_prority;  /* Device intrrupt priority */    
    FSpimSlaveDevice     slave_dev_id; /* Slave device id */
    u32                  max_freq_hz;  /* Clock frequency in Hz */
    FSpimTransByte       n_bytes;      /* Bytes in transfer */
    FSpimCpolType        cpol;         /* Polarity of the clock */
    FSpimCphaType        cpha;         /* Phase of the clock */
    boolean              en_test;      /* Enable test mode */
} FSpimConfig;
  • SPIM 驱动控制数据
typedef struct
{
    FSpimConfig         config;      /* Current active configs */
    u32                 is_ready;    /* Device is initialized and ready */
    u32                 length;      /* Data length in transfer */
    const void          *tx_buff;    /* Tx buffer beg */
    void                *rx_buff;    /* Rx buffer beg */
    const void          *tx_buff_end; /* Tx buffer end */
    void                *rx_buff_end; /* Rx buffer end */
    u32                 tx_fifo_len;  /* Depth of tx fifo */
    u32                 rx_fifo_len;  /* Depth of rx fifo */
    FSpimEvtHandler     evt_handler[FSPIM_INTR_EVT_NUM];  /* event handler for interrupt */
    void                *evt_param[FSPIM_INTR_EVT_NUM];   /* parameters ptr of event handler */
} FSpim;
  • SPI 从设备ID最多支持4个从设备
enum
{
    FSPIM_SLAVE_DEV_0 = 0,
    FSPIM_SLAVE_DEV_1,
    FSPIM_SLAVE_DEV_2,
    FSPIM_SLAVE_DEV_3,

    FSPIM_NUM_OF_SLAVE_DEV
};
  • 一次 SPI 传输的数据量,一个字节或者两个字节
enum
{
    FSPIM_1_BYTE = 1,
    FSPIM_2_BYTE = 2,

    FSPIM_MAX_BYTES_NUM
};
  • SPI传输选择接收/发送
enum
{
    FSPIM_TRANS_MODE_RX_TX = 0x0,
    FSPIM_TRANS_MODE_TX_ONLY = 0x1,
    FSPIM_TRANS_MODE_RX_ONLY = 0x2,
    FSPIM_TRANS_MODE_READ_EEPROM = 0x3,

    FSPIM_TRANS_MODE_MAX
};
  • SPI的时钟极性和相位
enum
{
    FSPIM_CPOL_LOW  = 0,
    FSPIM_CPOL_HIGH
};

enum
{
    FSPIM_CPHA_1_EDGE = 0,
    FSPIM_CPHA_2_EDGE
};

4.2 错误码定义

  • 模块错误码编号0x1060000
  • [0x0] FSPIM_SUCCESS : fspim success
  • [0x1060000] FSPIM_SUCCESS : fspim success
  • [0x1060001] FSPIM_ERR_INVAL_STATE : fspim invalid state
  • [0x1060002] FSPIM_ERR_NOT_READY : fspim driver not ready
  • [0x1060003] FSPIM_ERR_INVAL_PARAM : fspim invalid input parameters
  • [0x1060004] FSPIM_ERR_BUS_BUSY : fspim bus is busy
  • [0x1060005] FSPIM_ERR_NOT_SUPPORT : fspim not support operation
  • [0x1060006] FSPIM_ERR_TIMEOUT : fspim wait timeout

4.3 用户API接口

FSpimLookupConfig

  • 获取FSPIM驱动的默认配置参数
const FSpimConfig *FSpimLookupConfig(u32 instance_id)

Note:

  • 用户可以通过此接口获取驱动默认配置的副本,进行修改后,作为FSpimCfgInitialize函数的入参使用

Input:

  • u32 instance_id, 选择的FSPIM控制器实例号

Return:

  • const FSpimConfig *, 返回的默认驱动配置返回NULL表示失败

FSpimCfgInitialize

  • 完成FSPIM驱动实例的初始化使之可以使用
FError FSpimCfgInitialize(FSpim *instance_p, const FSpimConfig *cofig_p);

Note:

  • 此函数会重置FSPIM控制器和FSPIM控制数据

Input:

  • FSpim *instance_p, FSPIM驱动控制数据

  • const FSpimConfig *input_config_p, FSPIM驱动配置数据

Return:

  • FError, 驱动初始化的错误码信息FSPIM_SUCCESS 表示初始化成功,其它返回值表示初始化失败

FSpimDeInitialize

  • 完成FSPIM驱动实例去初始化之后不能使用
void FSpimDeInitialize(FSpim *instance_p)

Note:

  • 此函数会重置FSPIM控制数据

Input:

  • FSpim *instance_p, FSPIM驱动控制数据

Return:

FSpimTransferPollFifo

  • 先发送后接收数据 (阻塞处理)利用Fifo进行处理
FError FSpimTransferPollFifo(FSpim *instance_p, const void *tx_buf, void *rx_buf, fsize_t len);

Note:

  • 使用此函数前需要确保FSPIM驱动初始化成功
  • 从函数不会使用中断会按照TX FIFO的深度进行传输每次发送填满TX FIFO后触发发送/接收动作

Input:

  • FSpim *instance_p, FSPIM驱动控制数据

  • const void *tx_buf, 写缓冲区可以为空为空时表示只关注读数据此时驱动会发送0xff读数据

  • void *rx_buf, 读缓冲区, 可以为空为空时表示值关注写数据此时SPI总线上返回的数据会被抛弃

  • fsize_t len, 进行传输的长度如果tx_buf或者rx_buf不为空则两个buf的长度必须为len

Return:

  • FError, 驱动初始化的错误码信息FSPIM_SUCCESS 表示数据交换成功,其它返回值表示交换失败

FSpimTransferByInterrupt

  • 先发送后接收数据 (中断处理)利用Fifo进行处理
FError FSpimTransferByInterrupt(FSpim *instance_p, const void *tx_buf, void *rx_buf, fsize_t len);

Note:

  • 使用此函数前需要确保FSPIM驱动初始化成功
  • 此函数会安装TX FIFO的深度进行传输每次发送填满TX FIFO后在中断中处理发送/接收动作用户需要注册FSPIM_INTR_EVT_RX_DONE事件传输过程中用户处理其它任务等待传输完成后从tx_buf和rx_buf中读数据

Input:

  • FSpim *instance_p, FSPIM驱动控制数据

  • const void *tx_buf, 写缓冲区可以为空为空时表示只关注读数据此时驱动会发送0xff读数据

  • void *rx_buf, 读缓冲区, 可以为空为空时表示值关注写数据此时SPI总线上返回的数据会被抛弃

  • fsize_t len, 进行传输的长度如果tx_buf或者rx_buf不为空则两个buf的长度必须为len

Return:

  • FError, 驱动初始化的错误码信息FSPIM_SUCCESS 表示数据交换成功,其它返回值表示交换失败

FSpimInterruptHandler

  • SPIM中断处理函数
void FSpimInterruptHandler(s32 vector, void *param);

Note:

  • 此函数给用户注册在中断处理模块中,从而在中断触发时进行处理
  • 使用此函数前,用户需要打开部分中断屏蔽位

Input:

  • s32 vector, 中断向量号,此处不关心此参数

  • void *param, 中断输入参数, 指向FSPIM的驱动控制实例

Return:

FSpimRegisterIntrruptHandler

  • SPIM中断事件注册函数
void FSpimRegisterIntrruptHandler(FSpim *instance_p, u32 evt, FSpimEvtHandler handler, void *param)

Note:

  • 此函数与FSpimInterruptHandler配套使用为中断处理注册事件回调函数

Input:

  • FSpim *instance_p, FSPIM驱动控制数据

  • u32 evt, 中断事件号码参考FSPIM_INTR_EVT_NUM

  • FSpimEvtHandler handler, 中断事件回调函数

  • void *param, 中断事件回调函数的入参,取决于中断事件回调函数的实现

Return:

FSpimErrorToMessage

  • 获取FSPIM驱动错误码
const char *FSpimErrorToMessage(FError error);

Note:

Input:

  • FError error, FSPIM模块错误码

Return:

const char *, FSPIM模块错误码对应的信息

FSpimSetChipSelection

  • 获取FSPIM驱动错误码
void FSpimSetChipSelection(FSpim *instance_p, boolean on);

Note:

Input:

  • {FSpim} *instance_p, 驱动控制数据
  • {boolean} on, TRUE: 片选打开, FALSE: 片选关闭

Return: