0210_1 SFC SPI/QSPI 模式深度分析

FBB_WS63 SFC SPI/QSPI 模式深度分析

📋 目录

  1. [SPI vs QSPI 模式对比](#SPI vs QSPI 模式对比 "#spi-vs-qspi-%E6%A8%A1%E5%BC%8F%E5%AF%B9%E6%AF%94")
  2. [GPIO Pin 映射](#GPIO Pin 映射 "#gpio-pin-%E6%98%A0%E5%B0%84")
  3. 编译配置开关
  4. [GPIO 重新布线修改清单](#GPIO 重新布线修改清单 "#gpio-%E9%87%8D%E6%96%B0%E5%B8%83%E7%BA%BF%E4%BF%AE%E6%94%B9%E6%B8%85%E5%8D%95")
  5. 代码路径汇总

1️⃣ SPI vs QSPI 模式对比

📊 模式概览

特性 SPI 模式 QSPI 模式
通讯模式 标准 SPI 四线 SPI
GPIO pin 数量 4 条 6 条
数据线 MOSI(1线) + MISO(1线) IO0 + IO1 + IO2 + IO3(4线)
传输速度 正常 4x 更快
应用场景 通用 Flash 高速 Flash、存储器
Flash 支持 所有现代 Flash 大多数新型 Flash

🔌 两种模式的 GPIO 需求对比

SPI 模式(标准4线)
scss 复制代码
┌─── SFC 硬件模块 ───┐
│ WS63 SFC 控制器    │
│ (0x48000000)       │
└───────┬────────────┘
        │
        ├─→ GPIO_19 (SFC_CLK)    - 时钟信号,CLK
        ├─→ GPIO_20 (SFC_CSN)    - 片选信号,CS(低有效)
        ├─→ GPIO_21 (SFC_IO0)    - 数据线 0,MOSI(Master Out)
        └─→ GPIO_22 (SFC_IO1)    - 数据线 1,MISO(Master In)
QSPI 模式(四线增强)
scss 复制代码
┌─── SFC 硬件模块 ───┐
│ WS63 SFC 控制器    │
│ (0x48000000)       │
└───────┬────────────┘
        │
        ├─→ GPIO_19 (SFC_CLK)    - 时钟信号
        ├─→ GPIO_20 (SFC_CSN)    - 片选信号
        ├─→ GPIO_21 (SFC_IO0)    - 数据线 0,MOSI
        ├─→ GPIO_22 (SFC_IO1)    - 数据线 1,MISO
        ├─→ GPIO_23 (SFC_IO2)    - 数据线 2,WP(写保护,低有效)
        └─→ GPIO_24 (SFC_IO3)    - 数据线 3,HOLD(保持,低有效)

📌 关键差异说明

项目 SPI 模式 QSPI 模式 说明
CLK GPIO_19 GPIO_19 始终需要(硬固定)
CSN GPIO_20 GPIO_20 始终需要(硬固定)
MOSI(IO0) GPIO_21 GPIO_21 始终需要(硬固定)
MISO(IO1) GPIO_22 GPIO_22 始终需要(硬固定)
WP(IO2) ❌ 不需要 GPIO_23 ⚠️ QSPI 必需
HOLD(IO3) ❌ 不需要 GPIO_24 ⚠️ QSPI 必需
总 Pin 数 4 6 +2 pin

2️⃣ GPIO Pin 映射

🎯 GPIO Pin 定义位置

文件 1src/drivers/chips/ws63/include/platform_core_rom.h

位置:第 50-54 行

c 复制代码
typedef enum {
    GPIO_00 = 0,
    // ... GPIO_01 到 GPIO_18 ...
    GPIO_18 = 18,
    SFC_CLK = 19,      // ✅ Flash 时钟
    SFC_CSN = 20,      // ✅ 片选(CS#)
    SFC_IO0 = 21,      // ✅ MOSI 数据线 0
    SFC_IO1 = 22,      // ✅ MISO 数据线 1
    SFC_IO2 = 23,      // ⚠️  数据线 2(WP,仅 QSPI)
    SFC_IO3 = 24,      // ⚠️  数据线 3(HOLD,仅 QSPI)
    PIN_NONE = 25,
} pin_t;

说明

  • 这些是 enum 枚举定义,映射到具体的 GPIO 号(19-24)
  • GPIO_19-22 是硬件固定分配的 SFC 引脚
  • GPIO_23-24 是可选的 QSPI 扩展引脚
  • 这是硬件级别的固定连接,不能改变

文件 2src/drivers/chips/ws63/porting/soc/soc_porting.c

位置:第 64-79 行

c 复制代码
// PAD 寄存器地址(硬件 Pad Control)
#define PAD_SFC_CLK_CTRL  0x4400d868    // GPIO_19 的 Pad 控制寄存器
#define PAD_SFC_CSN_CTRL  0x4400d86C    // GPIO_20 的 Pad 控制寄存器
#define PAD_SFC_IO0_CTRL  0x4400d870    // GPIO_21 的 Pad 控制寄存器
#define PAD_SFC_IO1_CTRL  0x4400d874    // GPIO_22 的 Pad 控制寄存器
#define PAD_SFC_IO2_CTRL  0x4400d878    // GPIO_23 的 Pad 控制寄存器(QSPI)
#define PAD_SFC_IO3_CTRL  0x4400d87C    // GPIO_24 的 Pad 控制寄存器(QSPI)

// 驱动强度 (Drive Strength) 设置
#define SFC_CLK_DS_VALUE      0x3       // CLK 驱动强度
#define SFC_CSN_DS_VALUE      0x2       // CSN 驱动强度
#define SFC_DATA_DS_VALUE     0x2       // 数据线驱动强度

void config_sfc_ctrl_ds(void)
{
    reg_setbits(PAD_SFC_CLK_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_CLK_DS_VALUE);
    reg_setbits(PAD_SFC_CSN_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_CSN_DS_VALUE);
    reg_setbits(PAD_SFC_IO0_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO1_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO2_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO3_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
}

说明

  • 这是芯片 Pad 控制的硬件寄存器地址
  • 配置了每条线的驱动强度(Drive Strength)
  • 这些地址是芯片级别的固定值(SOC 级别)
  • 不建议修改这些地址,除非硬件重新设计

文件 3src/drivers/drivers/hal/pinmux/ws63/hal_pinctrl_ws63.c

位置:第 20-27 行(基地址定义)、第 109-140 行(pin 配置组)

c 复制代码
#define HAL_IO_CFG_BASE_ADDR            0x4400D000
#define HAL_PIN_GPIO_SEL_START_OFFSET   0x000
#define HAL_PIN_UART_SEL_START_OFFSET   0x03C
#define HAL_PIN_GPIO_CTRL_START_OFFSET  0x800
#define HAL_PIN_SFC_CTRL_START_OFFSET   0x868  // ✅ SFC pin 控制起始地址

#define HAL_PIN_GPIO_SEL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_GPIO_SEL_START_OFFSET)
#define HAL_PIN_UART_SEL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_UART_SEL_START_OFFSET)
#define HAL_PIN_GPIO_CTRL_START_ADDR    (HAL_IO_CFG_BASE_ADDR + HAL_PIN_GPIO_CTRL_START_OFFSET)
#define HAL_PIN_SFC_CTRL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_SFC_CTRL_START_OFFSET)

Pin 配置组(第 109-140 行)

c 复制代码
static hal_pin_config_group_t const g_pin_pull_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        // ... GPIO_00~14 的上拉/下拉配置 ...
    },
    {
        SFC_CLK,                          // GPIO_19
        SFC_IO3,                          // GPIO_24
        HAL_PIN_SFC_CTRL_START_ADDR,      // 0x4400D868
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_PULL_START_BIT,
        HAL_PIN_PULL_BITS_NUM
    }
};

static hal_pin_config_group_t const g_pin_ds_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        // ... GPIO_00~14 的驱动强度配置 ...
    },
    {
        SFC_CLK,                          // GPIO_19
        SFC_IO3,                          // GPIO_24
        HAL_PIN_SFC_CTRL_START_ADDR,      // 0x4400D868
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_DS_START_BIT,
        HAL_PIN_DS_BITS_NUM
    }
};

// IE(输入使能)配置
static hal_pin_config_group_t const g_pin_ie_map[] = {
    {
        SFC_CLK,      // GPIO_19
        SFC_IO3,      // GPIO_24
        HAL_PIN_SFC_CTRL_START_ADDR,
        // ...
    }
};

// ST(Schmitt Trigger)配置
static hal_pin_config_group_t const g_pin_st_map[] = {
    {
        SFC_CLK,      // GPIO_19
        SFC_IO3,      // GPIO_24
        HAL_PIN_SFC_CTRL_START_ADDR,
        // ...
    }
};

说明

  • 定义了 SFC 的 pin 控制寄存器基地址
  • GPIO_19-24 都统一在 HAL_PIN_SFC_CTRL_START_ADDR 配置组中
  • 配置项包括:上拉/下拉、驱动强度、输入使能、施密特触发器

🔄 GPIO Pin 使用流程

scss 复制代码
┌─────────────────────────────────────────────────────┐
│ 硬启动/烧录(BootLoader)                           │
├─────────────────────────────────────────────────────┤
│ 1. SFC 硬件自动使用 GPIO_19-22(SPI 模式)        │
│ 2. soc_porting.c 配置 Pad 驱动强度                 │
│    └─ config_sfc_ctrl_ds()                         │
└──────────┬──────────────────────────────────────────┘
           │
┌──────────▼──────────────────────────────────────────┐
│ 应用启动(APP 阶段)                               │
├─────────────────────────────────────────────────────┤
│ 1. sfc.c 调用 hal_sfc_init()                       │
│ 2. hal_pinctrl_ws63.c 配置 pin 属性                │
│    └─ 拉高/拉低、驱动强度等                       │
│ 3. SFC 驱动初始化完成                              │
└─────────────────────────────────────────────────────┘

3️⃣ 编译配置开关

📚 Kconfig 配置文件位置

文件 1src/drivers/drivers/Kconfig

位置:第 387-403 行

kconfig 复制代码
config DRIVER_SUPPORT_SFC
    bool
    prompt "SFC"
    default y
    help
        This option means support SFC.

if DRIVER_SUPPORT_SFC
menu "SFC Configuration"
    comment "Config  SFC"
    osource "drivers/drivers/driver/sfc/Kconfig"
    osource "drivers/drivers/hal/sfc/Kconfig"
endmenu
endif

config DRIVER_SUPPORT_SPI
    bool
    prompt "SPI"
    default n
    help
        This option means support SPI.

if DRIVER_SUPPORT_SPI
menu "SPI Configuration"
    comment "Config SPI"
    osource "drivers/drivers/driver/spi/Kconfig"
    osource "drivers/drivers/hal/spi/Kconfig"
endmenu
endif

说明

  • CONFIG_DRIVER_SUPPORT_SFC - SFC 驱动总开关(默认启用
  • CONFIG_DRIVER_SUPPORT_SPI - 通用 SPI 驱动总开关(默认禁用
  • 关键点:SFC 和 SPI 是分别的驱动,不会直接冲突

文件 2src/drivers/chips/ws63/rom/drivers/drivers/driver/sfc/Kconfig

位置:完整内容

kconfig 复制代码
#===============================================================================
# @brief    Kconfig file.
# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved.
#===============================================================================
config SFC_SUPPORT_DMA
    bool
    prompt "SFC Support DMA"
    default y
    depends on DRIVER_SUPPORT_SFC

config SFC_ALLOW_ERASE_WRITEBACK
    bool
    prompt "Allows Erase at Any Address, needs 4KB RAM at least"
    default n
    depends on DRIVER_SUPPORT_SFC

config SFC_ALREADY_INIT
    bool
    prompt "SFC has been inited, need not to set reg in init/deinit func."
    default n
    depends on DRIVER_SUPPORT_SFC

SFC 相关配置

配置项 说明 默认值 用途
CONFIG_SFC_SUPPORT_DMA 启用 DMA 传输 y(启用) 提高传输速度
CONFIG_SFC_ALLOW_ERASE_WRITEBACK 允许任意地址擦除 n(禁用) 需要额外 4KB RAM
CONFIG_SFC_ALREADY_INIT Skip 初始化 n(禁用) BootLoader 已初始化时

⚠️ 重要

  • 这些配置中没有 QSPI/SPI 模式选择开关
  • QSPI 模式是由 Flash 芯片本身决定的(Flash 支持 QSPI 就自动启用)

文件 3src/application/samples/peripheral/spi/Kconfig

位置:第 49-77 行(SPI Master QSPI 支持)

kconfig 复制代码
config SPI_MASTER_SUPPORT_QSPI
    bool
    prompt "SPI master support QSPI."
    depends on SAMPLE_SUPPORT_SPI_MASTER
    default n

config SPI_MASTER_D3_PIN_MODE
    int
    prompt "Choose QSPI master D3 pin mode."
    depends on SPI_MASTER_SUPPORT_QSPI
    default 1

config SPI_MASTER_D2_PIN_MODE
    int
    prompt "Choose QSPI master D2 pin mode."
    depends on SPI_MASTER_SUPPORT_QSPI
    default 1

config SPI_MASTER_D3_PIN
    int
    prompt "Choose QSPI master D3 pin."
    depends on SPI_MASTER_SUPPORT_QSPI
    default 40

config SPI_MASTER_D2_PIN
    int
    prompt "Choose QSPI master D2 pin."
    depends on SPI_MASTER_SUPPORT_QSPI
    default 41

说明

  • 这是 通用 SPI 模块(不是 SFC)的 QSPI 配置
  • 支持用户自定义 D2/D3 pin(GPIO_40、GPIO_41 等)
  • 这不影响 SFC 的 GPIO_23-24

📊 当前项目配置状态

文件src/build/config/target_config/ws63/menuconfig/acore/ws63_liteos_app.config

位置:第 357-383 行

config 复制代码
#
# SFC Configuration
#

#
# Config  SFC
#
# CONFIG_SFC_SUPPORT_DMA is not set
# CONFIG_SFC_ALLOW_ERASE_WRITEBACK is not set
# CONFIG_SFC_ALREADY_INIT is not set
# CONFIG_SFC_SUPPORT_LPM is not set
# CONFIG_SFC_SUPPORT_SFC_LOCK is not set
# CONFIG_SFC_SUPPORT_DATA_CACHE is not set
# CONFIG_SFC_SUPPORT_RWE_INDEPENDENT is not set
# CONFIG_SFC_SUPPORT_WRITE_PROTECT is not set
# CONFIG_SFC_USE_CUSTOMIZED_DEVICE_INFO is not set
# CONFIG_SFC_DEBUG is not set
# end of SFC Configuration

CONFIG_DRIVER_SUPPORT_SPI=y

#
# SPI Configuration
#

#
# Config SPI
#
# CONFIG_SPI_SUPPORT_MASTER is not set
# CONFIG_SPI_SUPPORT_SLAVE is not set
# CONFIG_SPI_SUPPORT_DMA is not set
# CONFIG_SPI_SUPPORT_INTERRUPT is not set
# CONFIG_SPI_SUPPORT_CONCURRENCY is not set
# CONFIG_SPI_SUPPORT_LOOPBACK is not set
# CONFIG_SPI_SUPPORT_CRC is not set

当前配置分析

arduino 复制代码
✅ 启用的配置:
   └─ CONFIG_DRIVER_SUPPORT_SFC=y         (SFC 驱动启用)
   └─ CONFIG_DRIVER_SUPPORT_SPI=y         (SPI 驱动启用)

❌ 禁用的配置:
   └─ CONFIG_SFC_SUPPORT_DMA              (DMA 禁用 - 仅寄存器模式)
   └─ CONFIG_SPI_SUPPORT_MASTER           (通用 SPI Master 禁用)
   └─ CONFIG_SPI_SUPPORT_SLAVE            (通用 SPI Slave 禁用)
   └─ CONFIG_SPI_SUPPORT_DMA              (SPI DMA 禁用)

⚠️  关键发现:
   • SFC 没有显式的 SPI/QSPI 模式开关
   • QSPI 模式由 Flash 芯片自动检测和启用
   • 当前使用的是寄存器模式(非 DMA),较低效率

🔍 模式配置决策流程

arduino 复制代码
硬件检测 Flash 芯片
        │
        ├─→ 识别 Flash ID
        │   └─ sfc.c line 151
        │       build_cmds(flash_id, ...)
        │
        └─→ 查询 Flash 支持的模式
            └─ flash_config_info.c
                flash_spi_info_t 中的 quad_mode

            ├─ quad_mode != NULL
            │  └─→ 此 Flash 支持 QSPI
            │      ├─ 自动启用 GPIO_23-24
            │      └─ 配置 QSPI 指令
            │
            └─ quad_mode == NULL
               └─→ 此 Flash 仅支持 SPI
                   ├─ 仅使用 GPIO_19-22
                   └─ 配置 SPI 指令

4️⃣ GPIO 重新布线修改清单

⚠️ 硬件GPIO固定性警告

markdown 复制代码
❌ 【不可修改】硬件固定的 GPIO 映射:

    GPIO_19 ←→ SFC_CLK(硬线连接)
    GPIO_20 ←→ SFC_CSN(硬线连接)
    GPIO_21 ←→ SFC_IO0/MOSI(硬线连接)
    GPIO_22 ←→ SFC_IO1/MISO(硬线连接)
    GPIO_23 ←→ SFC_IO2/WP(硬线连接)
    GPIO_24 ←→ SFC_IO3/HOLD(硬线连接)

这些是芯片设计阶段的硬连接,无法通过软件修改。

📝 若硬件重新设计需要修改GPIO

假设新硬件使用了不同的 GPIO 引脚,需要修改以下位置:

1️⃣ platform_core_rom.h

文件位置src/drivers/chips/ws63/include/platform_core_rom.h

原内容(第 50-54 行):

c 复制代码
SFC_CLK = 19,
SFC_CSN = 20,
SFC_IO0 = 21,
SFC_IO1 = 22,
SFC_IO2 = 23,
SFC_IO3 = 24,

修改示例(假设新硬件用不同 GPIO):

c 复制代码
SFC_CLK = 25,    // 改为 GPIO_25
SFC_CSN = 26,    // 改为 GPIO_26
SFC_IO0 = 27,    // 改为 GPIO_27
SFC_IO1 = 28,    // 改为 GPIO_28
SFC_IO2 = 29,    // 改为 GPIO_29(QSPI)
SFC_IO3 = 30,    // 改为 GPIO_30(QSPI)

修改步骤

  1. 确定新的 GPIO 号(需要硬件原理图确认)
  2. 修改 enum 中的数值
  3. 确保新 GPIO 号在有效范围内(0-45 以内)

2️⃣ soc_porting.c(Pad 控制寄存器地址)

文件位置src/drivers/chips/ws63/porting/soc/soc_porting.c

原内容(第 64-67 行):

c 复制代码
#define PAD_SFC_CLK_CTRL   0x4400d868
#define PAD_SFC_CSN_CTRL   0x4400d86C
#define PAD_SFC_IO0_CTRL   0x4400d870
#define PAD_SFC_IO1_CTRL   0x4400d874
#define PAD_SFC_IO2_CTRL   0x4400d878
#define PAD_SFC_IO3_CTRL   0x4400d87C

修改说明

  • 这些寄存器地址来自 WS63 芯片设计文档
  • 每个新 GPIO 号对应新的寄存器地址
  • 需要查阅 WS63 数据手册获取新地址

修改示例(假设新 GPIO 的 Pad 地址):

c 复制代码
#define PAD_SFC_CLK_CTRL   0x4400d880    // 新地址
#define PAD_SFC_CSN_CTRL   0x4400d884
#define PAD_SFC_IO0_CTRL   0x4400d888
#define PAD_SFC_IO1_CTRL   0x4400d88C
#define PAD_SFC_IO2_CTRL   0x4400d890
#define PAD_SFC_IO3_CTRL   0x4400d894

3️⃣ hal_pinctrl_ws63.c

文件位置src/drivers/drivers/hal/pinmux/ws63/hal_pinctrl_ws63.c

原内容(第 109-140 行):

c 复制代码
static hal_pin_config_group_t const g_pin_pull_map[] = {
    {
        GPIO_00,
        GPIO_14,
        // ... GPIO_00~14 ...
    },
    {
        SFC_CLK,    // = 19
        SFC_IO3,    // = 24
        HAL_PIN_SFC_CTRL_START_ADDR,
        // ...
    }
};

修改说明

  • 如果新 GPIO 号仍在连续范围内(如 25-30),只需修改 begin 和 end
  • 如果分散在不同范围,可能需要新增配置组

修改示例(假设新 GPIO 为 25-30):

c 复制代码
{
    SFC_CLK,        // 新定义为 GPIO_25
    SFC_IO3,        // 新定义为 GPIO_30
    HAL_PIN_SFC_CTRL_START_ADDR,  // 使用新的基地址
    HAL_PIN_CONFIG_PER_NUM,
    HAL_PIN_PULL_START_BIT,
    HAL_PIN_PULL_BITS_NUM
}

🚫 Kconfig 中无需修改的内容

bash 复制代码
✅ Kconfig 文件:
   • src/drivers/drivers/Kconfig
   • src/drivers/chips/ws63/rom/drivers/drivers/driver/sfc/Kconfig
   • src/application/samples/peripheral/spi/Kconfig

为什么?
   ├─ GPIO pin 号不在 Kconfig 中硬编码
   ├─ Kconfig 只控制功能启用/禁用开关
   └─ Pin 映射在源代码中定义,不在配置中

✅ 完整修改检查清单

如果只是普通项目(不改硬件GPIO):
复制代码
✅ 检查项:
   ☐ 确认当前 GPIO_19-24 在硬件上连接正确
   ☐ 检查原理图中 Flash pin 的物理连接
   ☐ 验证电源和 GND 连接
   ☐ 确保 Flash 芯片规格书中支持当前固件
   
❌ 无需修改任何代码
如果需要硬件gpio重新布线:
markdown 复制代码
✅ 修改步骤:
   1. 获取硬件原理图
   2. 确定新 GPIO 号和 Pad 寄存器地址
   3. 修改 platform_core_rom.h(GPIO 号)
   4. 修改 soc_porting.c(Pad 控制地址)
   5. 修改 hal_pinctrl_ws63.c(pin 配置范围)
   6. 编译验证
   7. 烧录 BootLoader 执行初始化

🔧 工具需求:
   • WS63 数据手册(获取 Pad 地址)
   • FlashTool 重新烧录 BootLoader
   • 硬件测试工具(示波器、逻辑分析仪)

5️⃣ 代码路径汇总

📁 文件结构图

erlang 复制代码
fbb_ws63-master/
├── src/drivers/
│   ├── chips/ws63/
│   │   ├── include/
│   │   │   ├── platform_core_rom.h                ⭐ GPIO 枚举定义
│   │   │   └── ...
│   │   ├── porting/
│   │   │   ├── soc/
│   │   │   │   └── soc_porting.c                 ⭐ Pad 寄存器地址
│   │   │   ├── sfc/
│   │   │   │   ├── sfc_porting.h                 📋 SFC 配置结构体
│   │   │   │   ├── porting/
│   │   │   │   │   └── sfc_porting.c             ⭐ SFC 寄存器基地址
│   │   │   │   ├── driver/
│   │   │   │   │   └── sfc.c                     💻 SFC 驱动核心
│   │   │   │   └── flash_config/
│   │   │   │       └── flash_config_info.c       📊 Flash 芯片配置
│   │   │   └── ...
│   │   └── ...
│   ├── drivers/
│   │   ├── hal/
│   │   │   ├── pinmux/ws63/
│   │   │   │   └── hal_pinctrl_ws63.c            ⭐ Pin 控制配置
│   │   │   ├── sfc/
│   │   │   │   └── hal_sfc_v150.c               💻 SFC HAL 层
│   │   │   └── ...
│   │   ├── Kconfig                               📝 驱动配置开关
│   │   └── ...
│   └── ...
├── src/application/
│   └── samples/
│       └── peripheral/
│           ├── spi/
│           │   ├── Kconfig                       📝 SPI 配置开关
│           │   └── spi_master_demo.c             📜 SPI Master 示例
│           └── sfc/
│               └── sfc_demo.c                    📜 SFC 使用示例
├── src/build/
│   ├── config/
│   │   └── target_config/ws63/menuconfig/acore/
│   │       ├── ws63_liteos_app.config            ⚙️  APP 配置
│   │       ├── ws63_flashboot.config             ⚙️  BootLoader 配置
│   │       └── ws63_liteos_testsuite.config      ⚙️  测试套件配置
│   └── ...
└── ...

🔑 核心文件详解

# 文件名 路径 功能 修改频率
1 platform_core_rom.h src/drivers/chips/ws63/include/ GPIO 枚举定义(GPIO_19-24) 🔴 极少修改
2 soc_porting.c src/drivers/chips/ws63/porting/soc/ Pad 寄存器地址 & 驱动强度配置 🔴 极少修改
3 hal_pinctrl_ws63.c src/drivers/drivers/hal/pinmux/ws63/ Pin 控制配置映射表 🟡 如果改GPIO
4 sfc_porting.h src/drivers/chips/ws63/porting/sfc/ SFC 配置结构体定义 🟢 可配置
5 sfc_porting.c src/drivers/chips/ws63/porting/sfc/porting/ SFC 寄存器基地址 🔴 固定
6 sfc.c src/drivers/chips/ws63/porting/sfc/driver/ SFC 驱动实现 🟢 按需配置
7 flash_config_info.c src/drivers/chips/ws63/porting/sfc/flash_config/ Flash 芯片数据库 🟢 新芯片需添加
8 hal_sfc_v150.c src/drivers/drivers/hal/sfc/ SFC 硬件抽象层 🔴 极少修改
9 Kconfig src/drivers/drivers/ 驱动功能开关 🟡 按项目需求
10 .config src/build/config/target_config/ws63/ 当前编译配置 🟢 频繁修改

图例

  • 🔴 红色:硬件固定,极少改动
  • 🟡 黄色:特定场景修改
  • 🟢 绿色:常规配置和定制

🔍 功能追踪

"如何启用 QSPI 模式?"追踪
markdown 复制代码
1. 硬件检测阶段
   └─ sfc.c:151
       uapi_sfc_init() 入口
           ↓
       build_cmds(flash_id, ...)
           ↓

2. Flash 芯片查询
   └─ flash_config_info.c
       查询 flash_spi_info_t 数组
       找到匹配的 flash_id
           ↓

3. 模式自动选择
   └─ sfc.c:67
       if (spi_info->quad_mode != NULL)
           ├─ QSPI 支持
           │  ├─ 自动启用 GPIO_23-24
           │  ├─ 加载 QSPI 指令序列
           │  └─ 配置 Quad SPI 模式
           └─ SPI 仅支持
              ├─ 仅使用 GPIO_19-22
              ├─ 加载 SPI 指令
              └─ 配置标准 SPI 模式

4. HAL 层初始化
   └─ hal_sfc_v150.c
       hal_sfc_init()
       根据 quad_mode 参数配置硬件
           ↓

5. 完成
   └─ 驱动自动运行于最优模式

"如何修改 Flash 配置?"追踪
ini 复制代码
1. 找到使用的 Flash 芯片型号
   └─ 硬件原理图 → Flash 芯片手册

2. 检查 flash_config_info.c
   └─ 查找对应的 FLASH_XXX ID 定义
       是否存在该芯片配置

3. 如果已有配置
   └─ sfc.c 会自动使用
   └─ 无需修改代码

4. 如果无该配置
   └─ flash_config_info.c
       仿照现有格式添加该 Flash 配置
           ├─ .chip_id = 0xXXXXXX
           ├─ .read_cmds[] = { ... }
           ├─ .write_cmds[] = { ... }
           ├─ .erase_cmds[] = { ... }
           └─ .quad_mode = &cmd_seq  (如果支持)

5. 重新编译烧录

🎯 快速查找表

我想要配置...

需求 文件 行号 说明
查看 GPIO 定义 platform_core_rom.h 50-54 enum GPIO 编号
改变 GPIO 号 platform_core_rom.h 50-54 修改枚举值
调整驱动强度 soc_porting.c 70-71 SFC_CLK_DS_VALUE 等
启用 DMA Kconfig 配置菜单 CONFIG_SFC_SUPPORT_DMA
添加新 Flash flash_config_info.c 全文 仿照现有条目添加
启用 Quad 模式 自动 - Flash 自动检测
查看 SFC 初始化 sfc.c 145-170 uapi_sfc_init() 函数
查看 Pin 配置 hal_pinctrl_ws63.c 109-140 g_pin_xxx_map 数组
禁用 SFC Kconfig 驱动菜单 CONFIG_DRIVER_SUPPORT_SFC

🎓 总结对比表

SPI vs QSPI 模式:硬件视角

scss 复制代码
┌──────────────┬─────────────────┬─────────────────┐
│ 特性         │ SPI 模式        │ QSPI 模式       │
├──────────────┼─────────────────┼─────────────────┤
│ GPIO pin     │ GPIO_19~22      │ GPIO_19~24      │
│ 总数         │ 4 条            │ 6 条            │
│ CLK          │ GPIO_19         │ GPIO_19         │
│ CSN          │ GPIO_20         │ GPIO_20         │
│ MOSI(IO0)    │ GPIO_21         │ GPIO_21         │
│ MISO(IO1)    │ GPIO_22         │ GPIO_22         │
│ WP(IO2)      │ ❌ 不需要       │ GPIO_23         │
│ HOLD(IO3)    │ ❌ 不需要       │ GPIO_24         │
│ 驱动强度     │ 在 soc_porting.c 中配置 | 同左   │
│ Pad 寄存器   │ 0x4400d868-74   │ 0x4400d868-7C   │
│ 数据线数     │ 1(收) + 1(发)   │ 4 线双向        │
│ 传输速率     │ 基线            │ ~4x 快速        │
│ Pin 配置文件 │ hal_pinctrl_ws63.c (统一)       │
└──────────────┴─────────────────┴─────────────────┘

编译配置:当前项目状态

ini 复制代码
├─ CONFIG_DRIVER_SUPPORT_SFC=y       ✅ SFC 驱动启用
├─ CONFIG_DRIVER_SUPPORT_SPI=y       ✅ 通用 SPI 启用(但无 Master)
├─ CONFIG_SFC_SUPPORT_DMA 未设       ❌ 禁用 DMA(低性能)
│
└─ 当前模式自动检测:
    Flash 支持 QUAD → 自动启用 QSPI(GPIO_19-24)
    Flash 仅支持 SPI → 使用 SPI 模式(GPIO_19-22)

修改需求清单

arduino 复制代码
场景 1:仅使用现有硬件(GPIO_19-24)
   修改文件:无
   重编译:仅需更新 .config(如启用 DMA)
   
场景 2:更换不同 Flash 芯片(同 GPIO)
   修改文件:可能需要 flash_config_info.c
   重编译:仅驱动代码
   
场景 3:重新设计硬件(不同 GPIO)
   修改文件:
      ✏️  platform_core_rom.h(GPIO 枚举)
      ✏️  soc_porting.c(Pad 地址)
      ✏️  hal_pinctrl_ws63.c(Pin 配置)
   重编译:整个驱动 + BootLoader
   烧录:重新初始化硬件

📚 参考资源

资源 位置 用途
WS63 数据手册 (硬件文档) Pad 地址、GPIO 定义
GPIO_LITTLEFS_ANALYSIS.md 项目根目录 GPIO 配置详解
SFC_GPIO_PIN_MAPPING.md AI/ 文件夹 Pin 映射参考
NOR_FLASH_CONFIG_PARAMETER_GUIDE.md AI/ 文件夹 Flash 配置指南

❓ 常见问题解答

Q1:能否改变 GPIO_19-24 的引脚号?

A:不能。这是硬件级别的固定连接。SFC 硬件内部已直接连接到这些 GPIO,改需要重新设计芯片。

Q2:SPI 和 QSPI 是否可以同时启用?

A:在 SFC 驱动中,Flash 自动选择一种模式。但通用 SPI 模块可独立使用不同 GPIO(如 GPIO_40-41),与 SFC 无冲突。

Q3:为什么配置中没有 QSPI 开关?

A:因为 QSPI 模式由 Flash 芯片决定。SFC 驱动自动检测 Flash 是否支持 Quad 模式,无需手动开关。

Q4:修改了 GPIO 定义后编译不过怎么办?

A

  1. 检查新 GPIO 号是否超出有效范围(0-45)
  2. 更新所有涉及的文件(platform_core_rom.h、soc_porting.c、hal_pinctrl_ws63.c)
  3. 清理编译缓存:rm -rf src/build/cmake_build
  4. 重新编译

Q5:GPIO_23-24 可以用于其他功能吗?

A:如果 Flash 不支持 QSPI,这两个 GPIO 理论上可复用。但不建议:

  • 硬件设计通常已连接到 Flash
  • 会使代码维护复杂化
  • 可用的 GPIO 有其他选项(GPIO_0-18, GPIO_25+)

文档更新时间 :2025-02 | FBB_WS63 版本 :最新 | 适用范围:SPI/QSPI 配置


FBB_WS63 SFC GPIO 修改代码示例

🎯 使用场景:假设需要改变 GPIO 映射

假定原硬件使用 GPIO_19-24,现在需要改为 GPIO_25-30(仅作示例)


模板 1:platform_core_rom.h 修改示例

原始代码

文件src/drivers/chips/ws63/include/platform_core_rom.h 行号:45-60

c 复制代码
/**
 * @brief Definition of pin.
 */
typedef enum {
    GPIO_00 = 0,
    GPIO_01 = 1,
    GPIO_02 = 2,
    GPIO_03 = 3,
    GPIO_04 = 4,
    GPIO_05 = 5,
    GPIO_06 = 6,
    GPIO_07 = 7,
    GPIO_08 = 8,
    GPIO_09 = 9,
    GPIO_10 = 10,
    GPIO_11 = 11,
    GPIO_12 = 12,
    GPIO_13 = 13,
    GPIO_14 = 14,
    GPIO_15 = 15,
    GPIO_16 = 16,
    GPIO_17 = 17,
    GPIO_18 = 18,
    SFC_CLK = 19,      // ← 原值
    SFC_CSN = 20,      // ← 原值
    SFC_IO0 = 21,      // ← 原值
    SFC_IO1 = 22,      // ← 原值
    SFC_IO2 = 23,      // ← 原值
    SFC_IO3 = 24,      // ← 原值
    PIN_NONE = 25, // used as invalid/unused PIN number
} pin_t;

修改后的代码

c 复制代码
/**
 * @brief Definition of pin.
 */
typedef enum {
    GPIO_00 = 0,
    GPIO_01 = 1,
    GPIO_02 = 2,
    GPIO_03 = 3,
    GPIO_04 = 4,
    GPIO_05 = 5,
    GPIO_06 = 6,
    GPIO_07 = 7,
    GPIO_08 = 8,
    GPIO_09 = 9,
    GPIO_10 = 10,
    GPIO_11 = 11,
    GPIO_12 = 12,
    GPIO_13 = 13,
    GPIO_14 = 14,
    GPIO_15 = 15,
    GPIO_16 = 16,
    GPIO_17 = 17,
    GPIO_18 = 18,
    GPIO_19 = 19,      // 现在作为普通 GPIO
    GPIO_20 = 20,      // 现在作为普通 GPIO
    GPIO_21 = 21,      // 现在作为普通 GPIO
    GPIO_22 = 22,      // 现在作为普通 GPIO
    GPIO_23 = 23,      // 现在作为普通 GPIO
    GPIO_24 = 24,      // 现在作为普通 GPIO
    SFC_CLK = 25,      // ← 新值(改到 GPIO_25)
    SFC_CSN = 26,      // ← 新值(改到 GPIO_26)
    SFC_IO0 = 27,      // ← 新值(改到 GPIO_27)
    SFC_IO1 = 28,      // ← 新值(改到 GPIO_28)
    SFC_IO2 = 29,      // ← 新值(改到 GPIO_29)
    SFC_IO3 = 30,      // ← 新值(改到 GPIO_30)
    PIN_NONE = 31,     // 更新为 31(之前的 PIN_NONE 值也要顺延)
} pin_t;

#define PIN_MAX_NUMBER PIN_NONE  // 保留这一行

修改要点

复制代码
✏️  改动清单:
   ☐ SFC_CLK 从 19 改为 25
   ☐ SFC_CSN 从 20 改为 26
   ☐ SFC_IO0 从 21 改为 27
   ☐ SFC_IO1 从 22 改为 28
   ☐ SFC_IO2 从 23 改为 29
   ☐ SFC_IO3 从 24 改为 30
   ☐ PIN_NONE 从 25 改为 31
   ☐ 添加 GPIO_19-24 的普通定义(可选)

模板 2:soc_porting.c 修改示例

原始代码

文件src/drivers/chips/ws63/porting/soc/soc_porting.c 行号:64-79

c 复制代码
#define PAD_SFC_CLK_CTRL  0x4400d868    // GPIO_19
#define PAD_SFC_CSN_CTRL  0x4400d86C    // GPIO_20
#define PAD_SFC_IO0_CTRL  0x4400d870    // GPIO_21
#define PAD_SFC_IO1_CTRL  0x4400d874    // GPIO_22
#define PAD_SFC_IO2_CTRL  0x4400d878    // GPIO_23
#define PAD_SFC_IO3_CTRL  0x4400d87C    // GPIO_24

#define SFC_CLK_DS_VALUE  0x3
#define SFC_CSN_DS_VALUE  0x2
#define SFC_DATA_DS_VALUE 0x2

void config_sfc_ctrl_ds(void)
{
    reg_setbits(PAD_SFC_CLK_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_CLK_DS_VALUE);
    reg_setbits(PAD_SFC_CSN_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_CSN_DS_VALUE);
    reg_setbits(PAD_SFC_IO0_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO1_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO2_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO3_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
}

修改后的代码

⚠️ 关键:需要从 WS63 数据手册查询新 GPIO 对应的 Pad 控制寄存器地址

假设新地址从 0x4400d880 开始(按顺序递增 0x4):

c 复制代码
// 新 GPIO 的 Pad 控制寄存器地址(需从芯片手册查询)
// GPIO_25 → GPIO_30 的 Pad 地址(假设)
#define PAD_SFC_CLK_CTRL  0x4400d880    // GPIO_25 对应的 Pad 地址
#define PAD_SFC_CSN_CTRL  0x4400d884    // GPIO_26 对应的 Pad 地址
#define PAD_SFC_IO0_CTRL  0x4400d888    // GPIO_27 对应的 Pad 地址
#define PAD_SFC_IO1_CTRL  0x4400d88C    // GPIO_28 对应的 Pad 地址
#define PAD_SFC_IO2_CTRL  0x4400d890    // GPIO_29 对应的 Pad 地址
#define PAD_SFC_IO3_CTRL  0x4400d894    // GPIO_30 对应的 Pad 地址

// 驱动强度值保持不变(除非需要微调)
#define SFC_CLK_DS_VALUE  0x3           // 时钟强驱动
#define SFC_CSN_DS_VALUE  0x2           // 片选中等驱动
#define SFC_DATA_DS_VALUE 0x2           // 数据线中等驱动

void config_sfc_ctrl_ds(void)
{
    // 配置逻辑完全相同,只是使用了新的寄存器地址
    reg_setbits(PAD_SFC_CLK_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_CLK_DS_VALUE);
    reg_setbits(PAD_SFC_CSN_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_CSN_DS_VALUE);
    reg_setbits(PAD_SFC_IO0_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO1_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO2_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
    reg_setbits(PAD_SFC_IO3_CTRL, 0, POS_4, DTRL_DS_LEN, SFC_DATA_DS_VALUE);
}

修改要点

scss 复制代码
✏️  改动清单:
   ☐ PAD_SFC_CLK_CTRL 地址更新(从芯片手册查表)
   ☐ PAD_SFC_CSN_CTRL 地址更新
   ☐ PAD_SFC_IO0_CTRL 地址更新
   ☐ PAD_SFC_IO1_CTRL 地址更新
   ☐ PAD_SFC_IO2_CTRL 地址更新
   ☐ PAD_SFC_IO3_CTRL 地址更新
   ☐ 驱动强度值保持或微调(可选)
   ☐ config_sfc_ctrl_ds() 函数逻辑不变

⚠️  重要:
   • 所有地址都必须从 WS63 数据手册查询
   • 地址通常是按顺序排列,间隔 0x4 字节
   • 务必确保地址准确无误

模板 3:hal_pinctrl_ws63.c 修改示例

原始代码

文件src/drivers/drivers/hal/pinmux/ws63/hal_pinctrl_ws63.c 行号:93-140

c 复制代码
static hal_pin_config_group_t const g_pin_mode_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_SEL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_GPIO_SEL_START_BIT,
        HAL_PIN_GPIO_SEL_BITS_NUM
    },
    {
        GPIO_15,
        GPIO_18,
        HAL_PIN_UART_SEL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_UART_SEL_START_BIT,
        HAL_PIN_UART_SEL_BITS_NUM
    }
    // ⚠️ 原来没有 SFC_CLK 的条目
};

static hal_pin_config_group_t const g_pin_pull_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_PULL_START_BIT,
        HAL_PIN_PULL_BITS_NUM
    },
    {
        SFC_CLK,        // = 19(原值)
        SFC_IO3,        // = 24(原值)
        HAL_PIN_SFC_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_PULL_START_BIT,
        HAL_PIN_PULL_BITS_NUM
    }
};

static hal_pin_config_group_t const g_pin_ds_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_DS_START_BIT,
        HAL_PIN_DS_BITS_NUM
    },
    {
        SFC_CLK,        // = 19(原值)
        SFC_IO3,        // = 24(原值)
        HAL_PIN_SFC_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_DS_START_BIT,
        HAL_PIN_DS_BITS_NUM
    }
};

#if defined(CONFIG_PINCTRL_SUPPORT_IE)
static hal_pin_config_group_t const g_pin_ie_map[] = {
    {
        GPIO_00,
        GPIO_18,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_IE_START_BIT,
        HAL_PIN_IE_BITS_NUM
    },
    {
        SFC_CLK,        // = 19(原值)
        SFC_IO3,        // = 24(原值)
        HAL_PIN_SFC_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_IE_START_BIT,
        HAL_PIN_IE_BITS_NUM
    }
};
#endif

#if defined(CONFIG_PINCTRL_SUPPORT_ST)
static hal_pin_config_group_t const g_pin_st_map[] = {
    {
        GPIO_00,
        GPIO_18,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_ST_START_BIT,
        HAL_PIN_ST_BITS_NUM
    },
    {
        SFC_CLK,        // = 19(原值)
        SFC_IO3,        // = 24(原值)
        HAL_PIN_SFC_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_ST_START_BIT,
        HAL_PIN_ST_BITS_NUM
    }
};
#endif

修改后的代码

假设新的 SFC GPIO 为 GPIO_25-30,仍在连续范围内

c 复制代码
static hal_pin_config_group_t const g_pin_mode_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_SEL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_GPIO_SEL_START_BIT,
        HAL_PIN_GPIO_SEL_BITS_NUM
    },
    {
        GPIO_15,
        GPIO_18,
        HAL_PIN_UART_SEL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_UART_SEL_START_BIT,
        HAL_PIN_UART_SEL_BITS_NUM
    }
    // SFC 的 GPIO_25-30 可能不需要在 mode_map 中配置
};

static hal_pin_config_group_t const g_pin_pull_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_PULL_START_BIT,
        HAL_PIN_PULL_BITS_NUM
    },
    {
        SFC_CLK,        // 现在等于 25(新值从 platform_core_rom.h 自动获得)
        SFC_IO3,        // 现在等于 30(新值从 platform_core_rom.h 自动获得)
        HAL_PIN_SFC_CTRL_START_ADDR,  // 这个地址可能也需要更新
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_PULL_START_BIT,
        HAL_PIN_PULL_BITS_NUM
    }
};

static hal_pin_config_group_t const g_pin_ds_map[] = {
    {
        GPIO_00,
        GPIO_14,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_DS_START_BIT,
        HAL_PIN_DS_BITS_NUM
    },
    {
        SFC_CLK,        // 自动从 enum 获取新值 25
        SFC_IO3,        // 自动从 enum 获取新值 30
        HAL_PIN_SFC_CTRL_START_ADDR,  // 可能需要更新
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_DS_START_BIT,
        HAL_PIN_DS_BITS_NUM
    }
};

#if defined(CONFIG_PINCTRL_SUPPORT_IE)
static hal_pin_config_group_t const g_pin_ie_map[] = {
    {
        GPIO_00,
        GPIO_18,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_IE_START_BIT,
        HAL_PIN_IE_BITS_NUM
    },
    {
        SFC_CLK,        // 自动获取新值 25
        SFC_IO3,        // 自动获取新值 30
        HAL_PIN_SFC_CTRL_START_ADDR,  // 可能需要更新
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_IE_START_BIT,
        HAL_PIN_IE_BITS_NUM
    }
};
#endif

#if defined(CONFIG_PINCTRL_SUPPORT_ST)
static hal_pin_config_group_t const g_pin_st_map[] = {
    {
        GPIO_00,
        GPIO_18,
        HAL_PIN_GPIO_CTRL_START_ADDR,
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_ST_START_BIT,
        HAL_PIN_ST_BITS_NUM
    },
    {
        SFC_CLK,        // 自动获取新值 25
        SFC_IO3,        // 自动获取新值 30
        HAL_PIN_SFC_CTRL_START_ADDR,  // 可能需要更新
        HAL_PIN_CONFIG_PER_NUM,
        HAL_PIN_ST_START_BIT,
        HAL_PIN_ST_BITS_NUM
    }
};
#endif

修改说明

关键要点

arduino 复制代码
☑️  自动适配:
   • 由于使用了 SFC_CLK 和 SFC_IO3 的枚举名
   • platform_core_rom.h 改了后自动应用
   • hal_pinctrl_ws63.c 中用枚举名的地方自动更新

❌ 需要手动改的:
   • HAL_PIN_SFC_CTRL_START_ADDR
   • 所有 GPIO 配置组的数据结构范围

✏️  改动方式:
   方案 A(最简单):
      • 只改 platform_core_rom.h 中的 enum
      • 如果新 GPIO 范围仍然连续,其他文件可能无需改
      
   方案 B(彻底):
      • 改 platform_core_rom.h(enum)
      • 改 soc_porting.c(Pad 地址)
      • 改 hal_pinctrl_ws63.c(配置组)
      • 改 HAL_PIN_SFC_CTRL_START_OFFSET 基地址

模板 4:HAL_PIN_SFC_CTRL_START_OFFSET 基地址更新

原始定义

文件src/drivers/drivers/hal/pinmux/ws63/hal_pinctrl_ws63.c 行号:20-27

c 复制代码
#define HAL_IO_CFG_BASE_ADDR            0x4400D000
#define HAL_PIN_GPIO_SEL_START_OFFSET   0x000
#define HAL_PIN_UART_SEL_START_OFFSET   0x03C
#define HAL_PIN_GPIO_CTRL_START_OFFSET  0x800
#define HAL_PIN_SFC_CTRL_START_OFFSET   0x868    // ← 原值(用于 GPIO_19-24)

#define HAL_PIN_GPIO_SEL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_GPIO_SEL_START_OFFSET)
#define HAL_PIN_UART_SEL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_UART_SEL_START_OFFSET)
#define HAL_PIN_GPIO_CTRL_START_ADDR    (HAL_IO_CFG_BASE_ADDR + HAL_PIN_GPIO_CTRL_START_OFFSET)
#define HAL_PIN_SFC_CTRL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_SFC_CTRL_START_OFFSET)

修改后(如果 GPIO 改到 25-30)

c 复制代码
#define HAL_IO_CFG_BASE_ADDR            0x4400D000
#define HAL_PIN_GPIO_SEL_START_OFFSET   0x000
#define HAL_PIN_UART_SEL_START_OFFSET   0x03C
#define HAL_PIN_GPIO_CTRL_START_OFFSET  0x800
#define HAL_PIN_SFC_CTRL_START_OFFSET   0x880    // ← 新值(从芯片手册查询)

#define HAL_PIN_GPIO_SEL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_GPIO_SEL_START_OFFSET)
#define HAL_PIN_UART_SEL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_UART_SEL_START_OFFSET)
#define HAL_PIN_GPIO_CTRL_START_ADDR    (HAL_IO_CFG_BASE_ADDR + HAL_PIN_GPIO_CTRL_START_OFFSET)
#define HAL_PIN_SFC_CTRL_START_ADDR     (HAL_IO_CFG_BASE_ADDR + HAL_PIN_SFC_CTRL_START_OFFSET)

模板 5:flash_config_info.c 添加新 Flash

场景:添加新的 Flash 芯片(如 GD25Q256)

原有 Flash 条目示例

c 复制代码
#define FLASH_GD25Q32           0x1640C8

// ... 在某个数组中 ...
{
    .chip_id = FLASH_GD25Q32,
    .chip_size = 0x400000,                // 4MB
    .read_cmds = {
        {
            .cmd = 0x0B, .cmd_support = 1,
            .addr_len = SPI_ADDR_LEN_24, .addr_support = 1,
            .dummy_cycles = 1,
            .cmd_type = STANDARD_READ, .size = 0x04
        },
        // ... 其他读命令 ...
    },
    .read_cmd_num = 3,
    .write_cmds = { ... },
    .write_cmd_num = 2,
    .erase_cmds = { ... },
    .erase_cmd_num = 4,
    .quad_mode = &gd25_quad_mode_cmd,      // QSPI 支持
},

新增 Flash GD25Q256

c 复制代码
// 1. 首先添加 Flash ID 定义(在宏定义部分)
#define FLASH_GD25Q256          0x1940C8    // 256Mbit

// 2. 定义 QSPI 模式的使能命令(如果支持 Quad)
static flash_cmd_execute_t gd25q256_quad_mode_cmd = {
    {
        .cmd = 0x35,                        // 写状态寄存器 2
        .cmd_support = 1,
        .addr_support = 0,
        .dummy_cycles = 0,
        .cmd_type = FLASH_CMD_WRITE,
        .size = 1,
    },
    {
        .cmd = 0x15,                        // 读状态寄存器 2
        .cmd_support = 1,
        .addr_support = 0,
        .dummy_cycles = 0,
        .cmd_type = FLASH_CMD_READ,
        .size = 1,
    },
    {
        .cmd_support = 0,                   // 其他命令可选
    }
};

// 3. 在 Flash 配置数组中追加新条目
{
    .chip_id = FLASH_GD25Q256,
    .chip_size = 0x2000000,                 // 32MB(256Mbit)
    .read_cmds = {
        {
            .cmd = 0x0B,                    // Standard Read
            .cmd_support = 1,
            .addr_len = SPI_ADDR_LEN_24,
            .addr_support = 1,
            .dummy_cycles = 1,
            .cmd_type = STANDARD_READ,
            .size = 0x04
        },
        {
            .cmd = 0x3B,                    // Fast Read
            .cmd_support = 1,
            .addr_len = SPI_ADDR_LEN_24,
            .addr_support = 1,
            .dummy_cycles = 1,
            .cmd_type = STANDARD_READ,
            .size = 0x04
        },
        {
            .cmd = 0xEB,                    // Quad Fast Read
            .cmd_support = 1,
            .addr_len = SPI_ADDR_LEN_24,
            .addr_support = 1,
            .dummy_cycles = 3,
            .cmd_type = QUAD_READ,
            .size = 0x04
        },
    },
    .read_cmd_num = 3,
    .write_cmds = {
        {
            .cmd = 0x02,                    // Page Program
            .cmd_support = 1,
            .addr_len = SPI_ADDR_LEN_24,
            .addr_support = 1,
            .dummy_cycles = 0,
            .cmd_type = PAGE_PROGRAM,
            .size = 256
        },
        {
            .cmd = 0x32,                    // Quad Page Program
            .cmd_support = 1,
            .addr_len = SPI_ADDR_LEN_24,
            .addr_support = 1,
            .dummy_cycles = 0,
            .cmd_type = PAGE_PROGRAM,
            .size = 256
        },
    },
    .write_cmd_num = 2,
    .erase_cmds = {
        {
            .cmd = 0x20,                    // Sector Erase (4KB)
            .cmd_support = 1,
            .addr_support = 1,
            .cmd_type = ERASE_SECTOR,
            .size = 0x1000
        },
        {
            .cmd = 0x52,                    // 32KB Erase
            .cmd_support = 1,
            .addr_support = 1,
            .cmd_type = ERASE_32K,
            .size = 0x8000
        },
        {
            .cmd = 0xD8,                    // 64KB Erase (Block)
            .cmd_support = 1,
            .addr_support = 1,
            .cmd_type = ERASE_BLOCK,
            .size = 0x10000
        },
        {
            .cmd = 0xC7,                    // Chip Erase
            .cmd_support = 1,
            .addr_support = 0,
            .cmd_type = ERASE_CHIP,
            .size = 0x2000000                // 全容量
        },
    },
    .erase_cmd_num = 4,
    .quad_mode = &gd25q256_quad_mode_cmd,   // 支持 QSPI
},

修改清单

arduino 复制代码
☑️  添加 Flash 的步骤:
   1. 从 Flash 数据手册获取:
      □ Flash ID(3 字节)
      □ 容量(byte)
      □ 各种读命令的 opcode
      □ 编程命令 opcode
      □ 擦除命令 opcode(通常 4 种)
      □ QSPI 使能序列(如支持)
      
   2. 修改 flash_config_info.c:
      □ 添加 #define FLASH_XXXXX ID
      □ 如果支持 QSPI,定义 quad_mode 结构
      □ 创建 flash_spi_info_t 条目
      □ 填充读/写/擦命令数组
      
   3. 编译验证:
      □ 固件编译成功
      □ 烧录并测试 Flash 识别
      □ 验证 SPI 模式读写
      □ 验证 QSPI 模式读写(如支持)

模板 6:编译配置修改

启用 DMA 模式

文件ws63_liteos_app.config 修改

diff 复制代码
  #
  # SFC Configuration
  #
  
  #
  # Config  SFC
  #
- # CONFIG_SFC_SUPPORT_DMA is not set
+ CONFIG_SFC_SUPPORT_DMA=y
  # CONFIG_SFC_ALLOW_ERASE_WRITEBACK is not set
  # CONFIG_SFC_ALREADY_INIT is not set

启用通用 SPI Master

文件ws63_liteos_app.config 修改

diff 复制代码
  CONFIG_DRIVER_SUPPORT_SPI=y
  
  #
  # SPI Configuration
  #
  
  #
  # Config SPI
  #
- # CONFIG_SPI_SUPPORT_MASTER is not set
+ CONFIG_SPI_SUPPORT_MASTER=y

🔍 编译验证步骤

步骤 1:清理旧编译

bash 复制代码
cd fbb_ws63-master
rm -rf src/build/cmake_build
rm -rf src/build/output

步骤 2:重新编译

bash 复制代码
cd src
python build.py

步骤 3:检查编译错误

arduino 复制代码
常见错误:
  • "undefined reference to SFC_CLK" 
    → 检查 platform_core_rom.h enum 定义
  
  • "SFC initialization failed"
    → 检查 Pad 寄存器地址是否正确
  
  • "Flash not detected"
    → 检查 GPIO 硬件连接
    → 检查 flash_config_info.c Flash ID

步骤 4:烧录和测试

bash 复制代码
# 烧录新固件
./flashtool --boot src/build/output/bin/out.bin

# 通过串口观察 SFC 初始化日志
# 应看到类似:
#   SFC: Identifying flash...
#   SFC: Flash ID = 0x1640C8
#   SFC: QSPI mode enabled
#   SFC: Initialization success

⚠️ 常见陷阱

陷阱 1:忘记同时改多个文件

复制代码
❌ 错误做法:
   只改 platform_core_rom.h,没改 soc_porting.c

✅ 正确做法:
   同时改:
   • platform_core_rom.h(GPIO 号)
   • soc_porting.c(Pad 地址)
   • hal_pinctrl_ws63.c(配置范围)

陷阱 2:Pad 寄存器地址假设

ini 复制代码
❌ 错误做法:
   简单地加偏移:0x4400d868 + 8 = 0x4400d870
   (实际可能不是线性关系)

✅ 正确做法:
   从 WS63 数据手册查表获取准确地址

陷阱 3:Flash ID 匹配失败

arduino 复制代码
❌ 错误现象:
   Flash ID = 0xFFFFFF
   
✅ 排查步骤:
   1. 用逻辑分析仪捕获 SPI 通信
   2. 检查 GPIO_19-22 波形
   3. 用 Flash 数据手册验证 read ID 命令
   4. 检查 flash_config_info.c 中是否有该 ID

陷阱 4:QSPI 模式无法启用

markdown 复制代码
❌ 错误现象:
   始终运行在 SPI 而非 QSPI 模式
   
✅ 排查步骤:
   1. 确认 Flash 数据手册支持 QSPI
   2. 检查 flash_config_info.c 中 quad_mode 指针是否为 NULL
   3. 验证 GPIO_23-24 的连接(仅 QSPI 用)
   4. 检查 QSPI 使能命令是否正确

📚 参考资源

资源 说明
WS63 数据手册 Pad 地址查表、GPIO 功能
Flash 数据手册 命令集、QSPI 支持、ID
GPIO_LITTLEFS_ANALYSIS.md GPIO 配置原理
SFC_GPIO_PIN_MAPPING.md Pin 映射完整表

示例文档完成 | 用于学习和参考 | 实际使用需按硬件定制

相关推荐
mCell10 小时前
如何零成本搭建个人站点
前端·程序员·github
mCell11 小时前
为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞
前端·设计模式·agent
恋猫de小郭11 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
少云清12 小时前
【安全测试】2_客户端脚本安全测试 _XSS和CSRF
前端·xss·csrf
银烛木12 小时前
黑马程序员前端h5+css3
前端·css·css3
m0_6070766012 小时前
CSS3 转换,快手前端面试经验,隔壁都馋哭了
前端·面试·css3
听海边涛声12 小时前
CSS3 图片模糊处理
前端·css·css3
IT、木易12 小时前
css3 backdrop-filter 在移动端 Safari 上导致渲染性能急剧下降的优化方案有哪些?
前端·css3·safari
0思必得012 小时前
[Web自动化] Selenium无头模式
前端·爬虫·selenium·自动化·web自动化
anOnion12 小时前
构建无障碍组件之Dialog Pattern
前端·html·交互设计