跳转至

SSI

SSI 驱动 | 无 sample

学习目标

  • 理解 SSI(Synchronous Serial Interface)与 SPI 的关系——简化版 SPI,专为寄存器级外设通信设计
  • 掌握 4 种地址/数据组合模式:addr16_data16、addr32_data16、addr32_data32
  • 理解 SSI 的典型应用场景——RF 前端、电源管理芯片等寄存器级外设

基本概念

SSI 做什么

SSI 是简化版同步串行接口。标准 SPI 需要配置 CPOL、CPHA、帧格式、位宽等诸多参数,而 SSI 省略这些——直接按"地址 + 数据"模式与外部寄存器级外设通信。每次操作分为两段:先发地址,再读/写数据。适合 RF CMOS 前端、PMIC 等只需寄存器读写的芯片。

flowchart LR
    M[WS63 MCU] -->|SSI 主机| S[SSI 控制器]
    S -->|SCLK + SDIO + SEN| D[外设芯片]
    D -->|寄存器数据| S
    S -->|data 指针| M

SSI vs SPI

对比项 SSI SPI
帧格式 固定:地址段 + 数据段 可配置 CPOL/CPHA
配置复杂度 极低——只需 init 高——多项参数
适用场景 寄存器级外设(RF/PMIC) 通用——Flash/LCD/Sensor
地址宽度 16-bit / 32-bit 由协议决定
数据宽度 16-bit / 32-bit 8~32 bit 任意

4 种读写模式

模式 地址宽度 数据宽度 典型外设
addr16_data16 16-bit 16-bit 常见 RF 前端寄存器
addr32_data16 32-bit 16-bit 大地址空间 16-bit 寄存器
addr32_data32 32-bit 32-bit 大地址空间 32-bit 寄存器

涉及 API

API 用途 头文件
uapi_ssi_init(void) 初始化 SSI 控制器 ssi.h
uapi_ssi_deinit(void) 去初始化 ssi.h
uapi_ssi_read_addr16_data16(uint16_t addr, uint16_t *data) 16b 地址读 16b 数据 ssi.h
uapi_ssi_write_addr16_data16(uint16_t addr, uint16_t value) 16b 地址写 16b 数据 ssi.h
uapi_ssi_read_addr32_data16(uint32_t addr, uint16_t *data) 32b 地址读 16b 数据 ssi.h
uapi_ssi_write_addr32_data16(uint32_t addr, uint16_t value) 32b 地址写 16b 数据 ssi.h
uapi_ssi_read_addr32_data32(uint32_t addr, uint32_t *data) 32b 地址读 32b 数据 ssi.h
uapi_ssi_write_addr32_data32(uint32_t addr, uint32_t value) 32b 地址写 32b 数据 ssi.h

所有读写接口返回 errcode_t——调用后应检查返回值,ERRCODE_SUCC 表示操作成功。

案例说明

做什么

通过 SSI 以 addr16_data16 模式读写外部芯片的寄存器:读取 ID 寄存器验证通信正常,修改配置寄存器,回读确认写入成功。

规格与功能

规格项 说明
模式 addr16_data16(16-bit 地址 + 16-bit 数据)
外设地址 0x00(ID 寄存器)、0x10(配置寄存器)
验证方法 读 → 修改 → 写 → 回读 → 比对

程序运行流程:init → read ID 寄存器 → 修改配置 → write 配置 → 回读确认 → deinit。

案例流程

sequenceDiagram
    participant M as WS63 MCU
    participant S as SSI 控制器
    participant D as 外设芯片

    M->>S: uapi_ssi_init
    M->>S: read_addr16_data16 addr=0x00
    S->>D: 发送地址0x00
    D->>S: 返回ID值
    S->>M: data = 0x1234

    M->>M: 验证ID正确

    M->>S: read_addr16_data16 addr=0x10
    S->>D: 发送地址0x10
    D->>S: 返回当前配置
    S->>M: data = 0x0001

    M->>M: 修改bit3=1
    M->>S: write_addr16_data16 addr=0x10 val=0x0009
    S->>D: 写入配置

    M->>S: read_addr16_data16 addr=0x10
    S->>D: 回读
    D->>S: 返回0x0009
    S->>M: 确认写入成功

    M->>S: uapi_ssi_deinit

案例操作指导

第一步:编译

fbb build ws63-liteos-app

第二步:烧录和验证

WS63 通过 SSI 引脚连接到目标外设(SCLK、SDIO、SEN)。烧录后串口输出读取的寄存器值,验证 ID 寄存器匹配预期后继续。

第三步:预期输出

SSI: read ID reg[0x00] = 0x1234
SSI: read CFG reg[0x10] = 0x0001
SSI: write CFG reg[0x10] = 0x0009
SSI: verify CFG reg[0x10] = 0x0009  OK

关键配置

参数 说明
地址宽度 16-bit / 32-bit 选错则外设不响应
数据宽度 16-bit / 32-bit 需与外设寄存器宽度匹配
返回值检查 必须 总线错误时 data 无效
适用范围 协议栈内部 应用层通常通过 BSP 调用,不直接调 SSI

地址宽度选择

外设寄存器数量 推荐模式
<= 65536 个 16-bit 寄存器 addr16_data16
> 65536 个 16-bit 寄存器 addr32_data16
32-bit 寄存器 addr32_data32

代码详解

概念性代码,基于 SDK 头文件 ssi.h 中的 API 签名。

#include "ssi.h"
#include "errcode.h"
#include "osal_printk.h"
#include "app_init.h"

#define RF_ID_REG       0x00    /* ID 寄存器 */
#define RF_CFG_REG      0x10    /* 配置寄存器 */
#define RF_ID_EXPECTED  0x1234  /* 期望的 ID 值 */
#define RF_CFG_BIT3     0x0008  /* 配置 bit3 掩码 */

static void ssi_entry(void)
{
    errcode_t ret;
    uint16_t id_val = 0;
    uint16_t cfg_val = 0;

    /* 初始化 SSI 控制器 */
    uapi_ssi_init();

    /* ---- 1. 读 ID 寄存器验证通信 ---- */
    ret = uapi_ssi_read_addr16_data16(RF_ID_REG, &id_val);
    if (ret != ERRCODE_SUCC) {
        osal_printk("SSI: read ID failed, ret=%d\n", ret);
        goto deinit;
    }
    osal_printk("SSI: read ID reg[0x%02X] = 0x%04X\n", RF_ID_REG, id_val);

    if (id_val != RF_ID_EXPECTED) {
        osal_printk("SSI: ID mismatch, expected 0x%04X\n", RF_ID_EXPECTED);
        goto deinit;
    }

    /* ---- 2. 读配置寄存器 ---- */
    ret = uapi_ssi_read_addr16_data16(RF_CFG_REG, &cfg_val);
    if (ret != ERRCODE_SUCC) {
        osal_printk("SSI: read CFG failed, ret=%d\n", ret);
        goto deinit;
    }
    osal_printk("SSI: read CFG reg[0x%02X] = 0x%04X\n", RF_CFG_REG, cfg_val);

    /* ---- 3. 修改 bit3 并写入 ---- */
    cfg_val |= RF_CFG_BIT3;
    ret = uapi_ssi_write_addr16_data16(RF_CFG_REG, cfg_val);
    if (ret != ERRCODE_SUCC) {
        osal_printk("SSI: write CFG failed, ret=%d\n", ret);
        goto deinit;
    }
    osal_printk("SSI: write CFG reg[0x%02X] = 0x%04X\n", RF_CFG_REG, cfg_val);

    /* ---- 4. 回读确认 ---- */
    uint16_t verify_val = 0;
    ret = uapi_ssi_read_addr16_data16(RF_CFG_REG, &verify_val);
    if (ret == ERRCODE_SUCC && verify_val == cfg_val) {
        osal_printk("SSI: verify OK\n");
    } else {
        osal_printk("SSI: verify FAIL, read=0x%04X expected=0x%04X\n",
                    verify_val, cfg_val);
    }

deinit:
    uapi_ssi_deinit();
}

app_run(ssi_entry);

SSI 的 4 种读写模式互斥——硬件上同一时刻只能使用一种模式。如需切换,先 deinitinit 后重新选择模式。应用层通常不直接调用 SSI 接口——协议栈通过 BSP 封装使用。