当前位置: 首页 > news >正文

FlexSPI 传输结构体解析

本文整理自22. FlexSPI—读写外部SPI NorFlash — [野火]i.MX RT库开发实战指南——基于i.MXRT1052 文档

用作个人学习和分享

一、FlexSPI 传输结构体(flexspi_transfer_t

传输结构体用于描述单次 FlexSPI 数据传输的具体参数,本质是将硬件寄存器配置(如 IPCR0/IPCR1、TX/RX FIFO)封装为软件友好的结构体,配合FLEXSPI_TransferBlocking(阻塞)或FLEXSPI_TransferNonBlocking(非阻塞)函数即可触发传输。其核心作用是 “告诉 FlexSPI:用哪个端口、执行哪个 LUT 指令、传输多少数据、数据存在哪里”。

1. 结构体定义与成员总览

typedef struct _flexspi_transfer {uint32_t deviceAddress;         /*!< 目标设备内部地址 */flexspi_port_t port;            /*!< 操作的FlexSPI端口 */flexspi_command_type_t cmdType; /*!< 传输命令类型 */uint8_t seqIndex;               /*!< LUT中指令序列的ID */uint8_t SeqNumber;              /*!< 要执行的LUT序列数量 */uint32_t *data;                 /*!< 数据缓冲区指针(发送/接收) */size_t dataSize;                /*!< 传输数据的字节数 */
} flexspi_transfer_t;

2. 关键成员

成员名硬件寄存器映射核心功能与使用说明
deviceAddressIPCR0 寄存器 [SFAR] 位目标设备(如 FLASH)的内部地址,仅用于需要地址的操作(如读 FLASH 的 0x1000 地址)。
示例:读 FLASH 地址 0x1000 时,赋值为0x1000;无地址的命令(如复位)赋值为0
port-(端口选择控制逻辑)指定操作的 FlexSPI 物理端口,枚举类型flexspi_port_t取值如下:
kFLEXSPI_PortA1/A2:A 组端口 1/2
kFLEXSPI_PortB1/B2:B 组端口 1/2
注意:需与外部设备(如 FLASH)实际连接的端口一致。
cmdType-(命令类型识别逻辑)定义传输的命令类型,决定data缓冲区是否有效,枚举类型flexspi_command_type_t取值:
kFLEXSPI_Command:纯命令(无数据),忽略data(如 FLASH 复位);
kFLEXSPI_Config:配置设备模式(如设置 FLASH 时序),data长度由 LUT 定义;
kFLEXSPI_Read:读操作,仅data作为接收缓冲区有效;
kFLEXSPI_Write:写操作,仅data作为发送缓冲区有效。
seqIndexIPCR1 寄存器 [ISEQID] 位LUT(查找表)中指令序列的 ID。FlexSPI 通过该值在 LUT 中找到对应的指令(如 “读 FLASH” 序列)。
示例:若 LUT 中索引 0 定义 “读 ID” 序列,seqIndex赋值为0
SeqNumberIPCR1 寄存器 [ISEQNUM] 位要执行的 LUT 指令序列数量。多数场景下为1(执行 1 个序列);若需连续执行多个序列(如 “写使能 + 写数据”),需赋值为对应数量(需提前在 LUT 中定义连续序列)。
dataTX FIFO(发送)/RX FIFO(接收)数据缓冲区指针:
- 写操作:指向要发送的数据数组(数据最终写入 TX FIFO 寄存器);
- 读操作:指向接收数据的数组(数据从 RX FIFO 读取后存入);
- 纯命令 / 配置操作:可设为NULL
注意:缓冲区需为 32 位对齐(FlexSPI FIFO 为 32 位宽度)。
dataSizeIPCR1 寄存器 [IDATSZ] 位传输数据的字节数,16 位寄存器限制(最大 65535 字节)。
示例:读 256 字节数据时,赋值为256;无数据传输时赋值为0

3. 典型使用示例(读 FLASH 数据)

// 1. 定义数据缓冲区(32位对齐)
uint32_t rxBuffer[64] __attribute__((aligned(4))); // 接收256字节(64*4)// 2. 初始化传输结构体
flexspi_transfer_t transfer = {.deviceAddress = 0x1000,          // 读FLASH的0x1000地址.port = kFLEXSPI_PortA1,          // 设备连接A1端口.cmdType = kFLEXSPI_Read,         // 读操作.seqIndex = 1,                    // LUT中索引1为“读数据”序列.SeqNumber = 1,                   // 执行1个序列.data = rxBuffer,                 // 接收缓冲区.dataSize = sizeof(rxBuffer)      // 传输256字节
};// 3. 触发阻塞传输(FlexSPI_BASE为外设基地址)
FLEXSPI_TransferBlocking(FLEXSPI_BASE, &transfer);

二、FlexSPI 外部设备配置结构体(flexspi_device_config_t

外部设备配置结构体用于定义FlexSPI 与外部设备(如 FLASH)的通讯时序与硬件参数,本质是将设备相关的配置寄存器(如 FLSHxxCR0/CR1/CR2、DLLACR)封装,配合FLEXSPI_SetFlashConfig函数写入硬件,确保 FlexSPI 与外部设备的时序匹配(如时钟、CS 建立时间)。

1. 结构体定义与成员总览

typedef struct _flexspi_device_config {uint32_t flexspiRootClk;          /*!< FlexSPI根时钟频率 */bool isSck2Enabled;               /*!< 是否使能SCK2时钟 */uint32_t flashSize;               /*!< FLASH容量(单位:KByte) */flexspi_cs_interval_cycle_unit_t CSIntervalUnit; /*!< CS间隔单位 */uint16_t CSInterval;              /*!< CS间隔周期数 */uint8_t CSHoldTime;               /*!< CS保持时间(根时钟周期) */uint8_t CSSetupTime;              /*!< CS建立时间(根时钟周期) */uint8_t dataValidTime;            /*!< 数据有效时间(单位:ns) */uint8_t columnspace;              /*!< 列地址宽度(单位:bit) */bool enableWordAddress;           /*!< 是否使能4字节地址 */uint8_t AWRSeqIndex;              /*!< AHB写命令的LUT序列ID */uint8_t AWRSeqNumber;             /*!< AHB写命令的序列数量 */uint8_t ARDSeqIndex;              /*!< AHB读命令的LUT序列ID */uint8_t ARDSeqNumber;             /*!< AHB读命令的序列数量 */flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit; /*!< AHB写等待单位 */uint16_t AHBWriteWaitInterval;    /*!< AHB写等待周期数 */bool enableWriteMask;             /*!< 是否使能DQS作为写掩码 */
} flexspi_device_config_t;

2. 关键成员详解(按功能分类)

(1)基础时钟与设备容量配置
成员名硬件寄存器映射核心功能与使用说明
flexspiRootClk-(库函数计算用)FlexSPI 根时钟频率(如 120MHz),不用于设置时钟,仅供库函数计算时序参数(如 CS 建立时间)。
需与实际配置的 FlexSPI 根时钟一致(从 PLL 或外设时钟树获取)。
isSck2Enabled-(SCK2 控制逻辑)是否使能 SCK2 时钟。RT1052 无 SCK2 引脚,固定赋值为false;其他支持 SCK2 的 MCU 按需配置。
flashSizeFLSHxxCR0 [FLSHSZ] 位外部 FLASH 的容量(单位:KByte),单个设备最大 4GB,总容量不超过 4GB。
示例:16MB FLASH 赋值为16*1024 = 16384
(2)CS 信号线时序配置

CS(片选)信号线的时序直接影响设备通讯稳定性,需严格遵循外部设备(如 FLASH)的数据手册。

成员名硬件寄存器映射核心功能与使用说明
CSIntervalUnitFLSHxxCR1[CSINTERVALUNIT]CS 间隔的时间单位,枚举类型flexspi_cs_interval_cycle_unit_t取值:
kFLEXSPI_CsIntervalUnit1SckCycle:1 个 SCK 周期
kFLEXSPI_CsIntervalUnit256SckCycle:256 个 SCK 周期
CSIntervalFLSHxxCR1[CSINTERVAL]CS 线 “无效→有效” 或 “有效→无效” 的最小间隔周期数,单位由CSIntervalUnit定义。
示例:FLASH 要求 CS 间隔≥100ns,若 SCK=100MHz(10ns / 周期),则CSIntervalUnit=1SckCycleCSInterval=10
CSHoldTimeFLSHxxCR1 [TCSH] 位CS 线 “有效→无效” 的保持时间,单位为 FlexSPI 根时钟周期。
示例:根时钟 = 120MHz(~8.3ns / 周期),FLASH 要求 CS 保持≥10ns,赋值为2(2*8.3=16.6ns)。
CSSetupTimeFLSHxxCR1 [TCSS] 位CS 线 “无效→有效” 的建立时间,单位为 FlexSPI 根时钟周期。
配置逻辑同CSHoldTime,需满足设备手册的最小建立时间要求。
(3)数据时序与地址配置
成员名硬件寄存器映射核心功能与使用说明
dataValidTimeDLLACR/DLLBCR 寄存器数据有效时间(单位:ns),用于校准 FlexSPI 的数据采样时序,确保数据稳定采样。
需根据外部设备的 “数据输出延迟” 配置(如 FLASH 数据延迟 5ns,赋值为5)。
columnspaceFLSHxxCR1 [CAS] 位列地址宽度(单位:bit),仅用于 “行 + 列” 地址架构的 FLASH(如某些 NAND FLASH)。
无列地址的 FLASH(如多数 NOR FLASH)赋值为0
enableWordAddressFLSHxxCR1 [WA] 位是否使能4 字节地址(32 位寻址)。若 FLASH 容量超过 16MB(需 32 位地址),赋值为true;否则为false
(4)AHB 命令配置(直接访问 FLASH 映射地址)

AHB 命令允许通过 “访问 MCU 内部映射地址” 直接读写 FLASH(无需传输结构体),需配置 AHB 命令对应的 LUT 序列与等待时间。

成员名硬件寄存器映射核心功能与使用说明
AWRSeqIndexFLSHxxCR2 [AWRSEQID] 位AHB 写命令(如*(uint32_t*)0x60000000 = 0x1234)对应的 LUT 序列 ID。
AWRSeqNumberFLSHxxCR2 [AWRSEQNUM] 位AHB 写命令执行的 LUT 序列数量(通常为1)。
ARDSeqIndexFLSHxxCR2 [ARDSEQID] 位AHB 读命令(如uint32_t val = *(uint32_t*)0x60000000)对应的 LUT 序列 ID。
ARDSeqNumberFLSHxxCR2 [ARDSEQNUM] 位AHB 读命令执行的 LUT 序列数量(通常为1)。
AHBWriteWaitUnitFLSHxxCR2 [AWRWAITUNIT] 位AHB 写等待的时间单位,枚举类型flexspi_ahb_write_wait_unit_t取值(如kFLEXSPI_AhbWriteWaitUnit8AhbCycle表示 8 个 AHB 周期)。
AHBWriteWaitIntervalFLSHxxCR2 [AWRWAIT] 位AHB 写等待的周期数,总等待时间 = AHBWriteWaitInterval * AHBWriteWaitUnit
用于 FLASH 写操作后的等待(FLASH 需时间完成内部编程),需根据设备手册配置(如等待 1ms,AHB=240MHz 时,计算对应周期数)。
(5)其他配置
成员名硬件寄存器映射核心功能与使用说明
enableWriteMaskFLSHCR4 寄存器是否使能 DQS 引脚作为写掩码,仅用于 16 位数据宽度的设备(如某些 16 位 FLASH),用于地址对齐。
8 位设备赋值为false

3. 典型使用示例(配置 16MB NOR FLASH)

// 1. 初始化外部设备配置结构体
flexspi_device_config_t deviceConfig = {.flexspiRootClk = 120000000U,    // FlexSPI根时钟120MHz.isSck2Enabled = false,          // RT1052不使能SCK2.flashSize = 16 * 1024U,         // 16MB FLASH(16*1024 KByte).CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle, // CS间隔单位:1个SCK周期.CSInterval = 10U,               // CS间隔10个SCK周期(SCK=100MHz时100ns).CSHoldTime = 2U,                // CS保持时间2个根时钟周期(~16.6ns).CSSetupTime = 2U,               // CS建立时间2个根时钟周期(~16.6ns).dataValidTime = 5U,             // 数据有效时间5ns.columnspace = 0U,               // NOR FLASH无列地址.enableWordAddress = true,       // 16MB需4字节地址.AWRSeqIndex = 2U,               // AHB写对应LUT序列2.AWRSeqNumber = 1U,              // 执行1个序列.ARDSeqIndex = 3U,               // AHB读对应LUT序列3.ARDSeqNumber = 1U,              // 执行1个序列.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit8AhbCycle, // AHB写等待单位:8个AHB周期.AHBWriteWaitInterval = 30000U,  // 总等待时间:30000*8 = 240000 AHB周期(AHB=240MHz时1ms).enableWriteMask = false         // 8位FLASH不使能写掩码
};// 2. 应用配置到A1端口(FLASH连接A1端口)
FLEXSPI_SetFlashConfig(FLEXSPI_BASE, &deviceConfig, kFLEXSPI_PortA1);

文章转载自:

http://zIJWhqTr.fthcn.cn
http://HXzh0Rii.fthcn.cn
http://89NOrPPz.fthcn.cn
http://ioUooXAi.fthcn.cn
http://6wO9QuD2.fthcn.cn
http://sySIJQ5l.fthcn.cn
http://w9wxd8ry.fthcn.cn
http://m2KEJxVq.fthcn.cn
http://DwXwDKZt.fthcn.cn
http://34elM298.fthcn.cn
http://Evmpe8qb.fthcn.cn
http://d2sMcwiL.fthcn.cn
http://x3n8oen4.fthcn.cn
http://IWWGYfLR.fthcn.cn
http://o71XA858.fthcn.cn
http://pIz1LplR.fthcn.cn
http://yNI6cV9J.fthcn.cn
http://KbZr2Ws8.fthcn.cn
http://sclbnU8U.fthcn.cn
http://rTDKIXnc.fthcn.cn
http://AL2EJMy0.fthcn.cn
http://zs73oLiV.fthcn.cn
http://urxmIqwf.fthcn.cn
http://9QD7WCEz.fthcn.cn
http://bscPHhMI.fthcn.cn
http://mXedBqcs.fthcn.cn
http://FWlG9Rbb.fthcn.cn
http://92Z10oUu.fthcn.cn
http://LNWH3ZYU.fthcn.cn
http://m2mhWYUb.fthcn.cn
http://www.dtcms.com/a/378931.html

相关文章:

  • 简单的GIT操作学习记录
  • K8S的dashboard部署与访问
  • css之一个元素可以同时应用多个动画效果
  • STM32之水质浑浊度传感器模块
  • 【Qt】【C++】虚析构函数及 virtual ~Base() = default
  • 马斯克访谈深度解读:机器人、AI芯片与人类文明的未来
  • 深入理解 CMake 脚本片段:文件查找、字符串替换与条件处理
  • Google Ads广告验证全攻略:如何借助动态住宅IP精准投放?
  • Linux防火墙配置指南:限制特定IP访问并允许其他所有流量
  • 使用动态IP 需要注意什么
  • 2025年- H128-Lc205. 同构字符串(哈希表)--Java版
  • 今天我们开始学习iptables防火墙
  • Android逆向学习(十一) IDA动态调试Android so文件
  • 第二篇:排序算法的简单认识【数据结构入门】
  • 嵌入式铁头山羊stm32:一文总结
  • HDFS(Hadoop 分布式文件系统)知识点梳理
  • AI幻觉的罪魁祸首
  • JVM 基础
  • 计算智能的概念和其算法的主要算法类型
  • leetcode25(有效的字母异位词)
  • [Windows] FileOptimizer v17.1.0_一款文件批量压缩工具
  • 淘宝/天猫按图搜索(拍立淘)item_search_img API接口实战指南
  • Java优选算法——二分查找
  • leetcode380:RandomizedSet - O(1)时间插入删除和获取随机元素(数组+哈希表的巧妙结合)
  • 经典蓝牙的 BR(Basic Rate(基础速率))
  • 牛客周赛 Round 108题解
  • Rocky9.0去堆叠双发arp(支持“ARP 广播双发”)
  • 「京墨」1.15.0 诗词、成语、对联、句子、诗歌…
  • AWS TechFest 2025: 风险模型的转变、流程设计的转型、生成式 AI 从实验走向实施的三大关键要素、评估生成式 AI 用例的适配度
  • 【Blender】二次元人物制作【二】:五官的制作