2. 硬件基础:T113 SPI控制器特性、SPI Flash芯片选型与硬件连接原理图分析

在嵌入式系统中,SPI Flash 作为非易失性存储介质,承担着存放 Bootloader、内核镜像、文件系统及用户配置数据的核心角色。全志 T113 处理器内部集成了多路 SPI 控制器,支持多种 SPI Flash 芯片。本章将深入剖析 T113 SPI 控制器的硬件特性、主流 SPI Flash 芯片(W25Q128 / GD25Q128)的选型要点,并结合实际原理图分析硬件连接关系,为后续驱动适配与性能调优奠定坚实的硬件基础。

2.1 全志 T113 SPI 控制器特性

T113 芯片内部集成了 3 个独立的 SPI 控制器(SPI0、SPI1、SPI2),其中 SPI0 通常用于连接系统启动所需的 SPI Flash,SPI1/SPI2 可用于扩展其他 SPI 外设(如 LCD、传感器等)。

关键提示: T113 的 SPI0 控制器支持 Dual/Quad SPI 模式,这是实现高速读写性能的核心硬件基础。在驱动适配时,务必确认硬件设计是否将 Flash 的 IO2/IO3 引脚连接至控制器,否则无法启用 Quad 模式。

2.1.1 SPI 控制器核心参数

参数项 SPI0 SPI1 SPI2
支持模式 Standard SPI / Dual SPI / Quad SPI Standard SPI / Dual SPI Standard SPI / Dual SPI
最大时钟频率 100 MHz 50 MHz 50 MHz
数据位宽 8/16/32-bit 8/16-bit 8/16-bit
FIFO 深度 64 Bytes (Tx/Rx 各 32 Bytes) 32 Bytes 32 Bytes
DMA 支持 支持 (硬件 DMA 请求) 不支持 不支持
片选信号 CS0 (专用) CS0/CS1 (可配置) CS0 (专用)
中断支持 Tx/Rx/Error 中断 Tx/Rx/Error 中断 Tx/Rx/Error 中断

2.1.2 SPI 控制器内部架构

下图展示了 T113 SPI0 控制器的内部功能模块与数据流向,重点突出了 DMA 与 FIFO 的协同工作方式。

T113 SPI0 控制器内部架构图 系统总线 AHB / APB DMA 控制器 Tx FIFO (32B) Rx FIFO (32B) SPI 状态机 SPI 引脚接口 SCLK MOSI (IO0) MISO (IO1) WP# (IO2) HOLD# (IO3) CS# 说明 DMA 控制器可直接与 FIFO 交换数据,无需 CPU 逐字节搬运,大幅降低读写延迟。

2.2 SPI Flash 芯片选型:W25Q128 与 GD25Q128

W25Q128(Winbond)与 GD25Q128(GigaDevice)是目前市场上最主流的 128Mb(16MB)SPI NOR Flash 芯片,两者在引脚、指令集、电气特性上高度兼容,但在部分时序参数和 ID 上存在细微差异。

2.2.1 芯片参数对比

参数项 W25Q128JV GD25Q128E
容量 128Mb (16MB) 128Mb (16MB)
页大小 256 Bytes 256 Bytes
扇区大小 4KB 4KB
块大小 64KB 64KB
最大时钟频率 133 MHz (Standard/Dual/Quad) 120 MHz (Standard/Dual/Quad)
Quad 模式指令 0xEB (Fast Read Quad I/O) 0xEB (Fast Read Quad I/O)
页编程时间 (典型) 0.64 ms 0.7 ms
扇区擦除时间 (典型) 45 ms 50 ms
JEDEC ID 0xEF 0x40 0x18 0xC8 0x40 0x18
工作电压 2.7V - 3.6V 2.7V - 3.6V
工作温度 -40°C ~ +85°C -40°C ~ +85°C
选型警告: 虽然 W25Q128 与 GD25Q128 在硬件上可以互换,但驱动层必须正确识别 JEDEC ID。部分旧版 Linux 内核 SPI-NOR 驱动可能缺少 GD25Q128 的 ID 表项,导致无法正确初始化。在驱动适配时,务必检查内核源码 drivers/mtd/spi-nor/winbond.c 和 drivers/mtd/spi-nor/gigadevice.c 中的 ID 列表。

2.2.2 引脚定义与功能

引脚编号 (WSON8/SOIC8) 引脚名称 功能描述 Quad 模式复用
1 CS# 片选信号 (低电平有效) -
2 DO (IO1) 数据输出 (Standard 模式) IO1 (双向数据线)
3 WP# (IO2) 写保护 (低电平有效) IO2 (双向数据线)
4 GND 地 -
5 DI (IO0) 数据输入 (Standard 模式) IO0 (双向数据线)
6 CLK 时钟输入 -
7 HOLD# (IO3) 保持输入 (低电平暂停传输) IO3 (双向数据线)
8 VCC 电源 (2.7V - 3.6V) -

2.3 硬件连接原理图分析

在 T113 参考设计中,SPI0 控制器通过 6 根信号线(CS#、CLK、MOSI、MISO、WP#、HOLD#)与 SPI Flash 芯片连接。其中 WP# 和 HOLD# 在 Quad 模式下被复用为 IO2 和 IO3 数据线。

2.3.1 典型连接原理图

T113 SPI0 与 SPI Flash 硬件连接原理图 全志 T113 SPI0 控制器 PB2 (CS0) PB3 (CLK) PB4 (MOSI/IO0) PB5 (MISO/IO1) PB6 (WP#/IO2) PB7 (HOLD#/IO3) CS# CLK MOSI (IO0) MISO (IO1) WP# (IO2) HOLD# (IO3) SPI Flash W25Q128 / GD25Q128 CS# (1) CLK (6) DI/IO0 (5) DO/IO1 (2) WP#/IO2 (3) HOLD#/IO3 (7) 电源网络 VCC: 3.3V GND: 0V 硬件设计要点 WP# 和 HOLD# 引脚必须连接上拉电阻 (10kΩ) 至 VCC,确保在 Standard 模式下 Flash 正常工作。

2.3.2 原理图关键设计要点

  1. 上拉电阻配置: CS#、WP#、HOLD# 引脚必须外接 10kΩ 上拉电阻至 VCC,防止浮空导致误操作。
  2. 去耦电容: VCC 引脚附近需放置 0.1μF 陶瓷电容,靠近芯片引脚放置,滤除高频噪声。
  3. 信号线长度匹配: 在高速模式(≥50MHz)下,CLK 与数据线(MOSI/MISO)的走线长度差应控制在 5mm 以内,避免时序偏移。
  4. Quad 模式布线: 若计划启用 Quad 模式,WP# 和 HOLD# 的走线必须与其他数据线等长,且远离高频干扰源(如 DDR 走线)。
  5. 地平面完整性: SPI Flash 下方应保持完整的地平面,减少信号回流路径阻抗。

2.4 硬件初始化流程与寄存器映射

在驱动开发中,理解 SPI 控制器的寄存器映射是编写底层操作函数的前提。T113 SPI0 控制器的寄存器基地址为 0x05010000,以下列出关键寄存器。

2.4.1 SPI0 关键寄存器列表

偏移地址 寄存器名称 描述 复位值
0x00 SPI_CTL 控制寄存器(使能、模式选择、时钟分频) 0x00000000
0x04 SPI_CLK_CTL 时钟控制寄存器(分频系数、极性、相位) 0x00000000
0x08 SPI_FIFO_CTL FIFO 控制寄存器(阈值、复位) 0x00000000
0x0C SPI_FIFO_STA FIFO 状态寄存器(空/满标志、数据计数) 0x00000000
0x10 SPI_TXD 发送数据寄存器 0x00000000
0x14 SPI_RXD 接收数据寄存器 0x00000000
0x18 SPI_DMA_CTL DMA 控制寄存器(使能、请求类型) 0x00000000
0x1C SPI_INT_CTL 中断控制寄存器(使能、清除) 0x00000000

2.4.2 硬件初始化代码示例

以下代码展示了在裸机或 U-Boot 阶段初始化 SPI0 控制器的基本流程,包括时钟使能、引脚复用配置、控制器模式设置。

/* SPI0 寄存器基地址 */
#define SPI0_BASE           0x05010000
#define SPI_CTL             (SPI0_BASE + 0x00)
#define SPI_CLK_CTL         (SPI0_BASE + 0x04)
#define SPI_FIFO_CTL        (SPI0_BASE + 0x08)

/* 时钟分频:AHB 时钟 200MHz,目标 SPI 时钟 50MHz,分频系数 = 4 */
#define SPI_CLK_DIV         4

void spi0_hardware_init(void)
{
    unsigned int tmp;

    /* 1. 使能 SPI0 模块时钟(以 CCU 寄存器为例) */
    *(volatile unsigned int *)(0x02001000 + 0x2C) |= (1 << 0);

    /* 2. 配置 PB2-PB7 为 SPI0 功能(复用功能 2) */
    *(volatile unsigned int *)(0x02000060) = (*(volatile unsigned int *)(0x02000060) & ~(0xFF << 8)) | (0x22 << 8);
    *(volatile unsigned int *)(0x02000064) = (*(volatile unsigned int *)(0x02000064) & ~(0xFF << 0)) | (0x22 << 0);

    /* 3. 复位 SPI 控制器 */
    tmp = *(volatile unsigned int *)SPI_CTL;
    tmp |= (1 << 1);  /* 软件复位 */
    *(volatile unsigned int *)SPI_CTL = tmp;
    while (*(volatile unsigned int *)SPI_CTL & (1 << 1));

    /* 4. 配置时钟分频:Master 模式,CPOL=0, CPHA=0 */
    *(volatile unsigned int *)SPI_CLK_CTL = (SPI_CLK_DIV & 0x3F) | (0 << 6) | (0 << 7);

    /* 5. 使能 SPI 控制器 */
    tmp = *(volatile unsigned int *)SPI_CTL;
    tmp |= (1 << 0);  /* SPI 使能 */
    *(volatile unsigned int *)SPI_CTL = tmp;

    /* 6. 清空 FIFO */
    *(volatile unsigned int *)SPI_FIFO_CTL |= (1 << 4) | (1 << 5);
}
实践要点: 在 Linux 内核中,上述初始化流程由 SPI 子系统框架自动完成,驱动开发者只需在设备树中正确配置 pinctrl、clock-frequency 和 spi-max-frequency 属性。但在 U-Boot SPL 阶段,通常需要手动实现上述寄存器操作。

2.5 本章小结