接上一篇
iMX RT FlexSPI 时序及驱动程序参数设置解析 (一)
本次介绍FlexSpi程序设置中的问题。
FlexSPI外接设备描述
官方的FlexSPI驱动程序中对外接设备定义了一个结构体:flexspi_device_config_t,注意这个结构体和SPI flash启动时设置FDCB的结构体不同,官方搞了两套代码。
/*! @brief External device configuration items. */
typedef struct _flexspi_device_config
{
uint32_t flexspiRootClk; /*!< FLEXSPI serial root clock. */
bool isSck2Enabled; /*!< FLEXSPI use SCK2. */
uint32_t flashSize; /*!< Flash size in KByte. */
flexspi_cs_interval_cycle_unit_t CSIntervalUnit; /*!< CS interval unit, 1 or 256 cycle. */
uint16_t CSInterval; /*!< CS line assert interval, mutiply CS interval unit to
get the CS line assert interval cycles. */
uint8_t CSHoldTime; /*!< CS line hold time. */
uint8_t CSSetupTime; /*!< CS line setup time. */
uint8_t dataValidTime; /*!< Data valid time for external device. */
uint8_t columnspace; /*!< Column space size. */
bool enableWordAddress; /*!< If enable word address.*/
uint8_t AWRSeqIndex; /*!< Sequence ID for AHB write command. */
uint8_t AWRSeqNumber; /*!< Sequence number for AHB write command. */
uint8_t ARDSeqIndex; /*!< Sequence ID for AHB read command. */
uint8_t ARDSeqNumber; /*!< Sequence number for AHB read command. */
flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit; /*!< AHB write wait unit. */
uint16_t AHBWriteWaitInterval; /*!< AHB write wait interval, mutiply AHB write interval
unit to get the AHB write wait cycles. */
bool enableWriteMask; /*!< Enable/Disable FLEXSPI drive DQS pin as write mask
when writing to external device. */
} flexspi_device_config_t;
结构体中成员的作用含义
flexspiRootClk 就是基础时钟的频率,单位为Hz,这里只是供计算延迟使用,并不会影响RT芯片实际的FlexSPI基础时钟。
isSck2Enabled 使能SCK2输出,每个FlexSPI控制器提供了两个SCK端口;
flashSize 外设器件的空间大小,单位是KB,和片选信号有关,见FlexSPI的连接 和 地址空间分配 手册1655页;
CSIntervalUnit CS片选信号间隔单位,枚举类型,这个参数设置和手册描述不同
CSInterval CS片选信号间隔时钟个数。
CSHoldTime 最后一个SCK时钟到CS上升沿 的 serial root clock 时钟个数。
CSSetupTime CS下降沿到第一个SCK时钟的 serial root clock 时钟个数。
dataValidTime DLL设置相关,单位是0.1ns, SCK边沿到数据边沿的时间,DLL延迟线一个单元延迟是75~225pS
columnspace 列地址宽度 bit
enableWordAddress 字寻址,4字节对齐
AWRSeqIndex AHB 写方式 LUT表索引,用AHB方式读的时候FlexSPI自动调用的指令在LUT中的索引
AWRSeqNumber AHB写执行的指令序列个数
ARDSeqIndex AHB读指令索引
ARDSeqNumber AHB读执行的指令个数
AHBWriteWaitUnit AHB写入后等待的时间单位,枚举型 默认配置 AHB时钟频率为528MHz,2个周期约3.8ns
AHBWriteWaitInterval AHB写入命令后等待的 周期 ( AHBWriteWaitInterval * AHBWriteWaitUnit ) 使用AHB命令时FlexSPI不会查询外部设备的状态,所以加上这个固定的延时保证外部设备的逻辑执行完成
enableWriteMask 设置FlexSPI写外部设备时,是否驱动DQS引脚作为写脉冲。
关于LUT的说明看 iMX TR1052芯片FlexSPI接口的使用 这一篇。 野火的iMX RT库开发指南中也有详细解读。
如果外接的是Flash或RAM芯片,需要按照芯片手册的时序和命令进行设置,如果外接的是FPGA器件,那命令都可以自定义。当然参考RAM的指令也是可以的。
设置结构体生效
设备的结构体配置完成后可以调用
FLEXSPI_SetFlashConfig(EXAMPLE_FLEXSPI, &deviceconfig, kFLEXSPI_PortA2);
函数将参数写入片内寄存器。最后一个参数 kFLEXSPI_PortA2 是表明这个设备接入到哪个FlexSPI端口,
当然前提是引脚都配置正确了
FlexSPI时钟设置
flexSPI有 serial root clock和SCK两个时钟,不要搞混,看上一篇 iMX RT FlexSPI 时序及驱动程序参数设置解析 (一) 。
SCK是与外部芯片通信连接用的时钟,serial root clock是RT芯片内的逻辑时钟。
借用野火例程里边的注释说明,时钟结构见上一篇文章。
const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
/* 初始化USB1PLL,即PLL3,loopDivider=0,
所以USB1PLL=PLL3 = 24*20 = 480MHz */
CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
/* 设置PLL3 PFD0频率为:PLL3*18/24 = 360MHZ. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 24);
/* 选择PLL3 PFD0作为flexspi时钟源
00b derive clock from semc_clk_root_pre
01b derive clock from pll3_sw_clk
10b derive clock from PLL2 PFD2
11b derive clock from PLL3 PFD0 */
CLOCK_SetMux(kCLOCK_FlexspiMux, 0x3);
/* 设置flexspiDiv分频因子,得到FLEXSPI_CLK_ROOT = PLL3 PFD0/(flexspiDiv+1) = 120M. */
CLOCK_SetDiv(kCLOCK_FlexspiDiv, 2);
FlexSPI设置
和外部设备描述一样,官方驱动程序也是提供了一个结构体,来描述FlexSPI的各种设置 :flexspi_config_t
/*! @brief FLEXSPI configuration structure. */
typedef struct _flexspi_config
{
flexspi_read_sample_clock_t rxSampleClock; /*!< Sample Clock source selection for Flash Reading. */
bool enableSckFreeRunning; /*!< Enable/disable SCK output free-running. */
bool enableCombination; /*!< Enable/disable combining PORT A and B Data Pins
(SIOA[3:0] and SIOB[3:0]) to support Flash Octal mode. */
bool enableDoze; /*!< Enable/disable doze mode support. */
bool enableHalfSpeedAccess; /*!< Enable/disable divide by 2 of the clock for half
speed commands. */
bool enableSckBDiffOpt; /*!< Enable/disable SCKB pad use as SCKA differential clock
output, when enable, Port B flash access is not available. */
bool enableSameConfigForAll; /*!< Enable/disable same configuration for all connected devices
when enabled, same configuration in FLASHA1CRx is applied to all. */
uint16_t seqTimeoutCycle; /*!< Timeout wait cycle for command sequence execution,
timeout after ahbGrantTimeoutCyle*1024 serial root clock cycles. */
uint8_t ipGrantTimeoutCycle; /*!< Timeout wait cycle for IP command grant, timeout after
ipGrantTimeoutCycle*1024 AHB clock cycles. */
uint8_t txWatermark; /*!< FLEXSPI IP transmit watermark value. */
uint8_t rxWatermark; /*!< FLEXSPI receive watermark value. */
struct
{
bool enableAHBWriteIpTxFifo; /*!< Enable AHB bus write access to IP TX FIFO. */
bool enableAHBWriteIpRxFifo; /*!< Enable AHB bus write access to IP RX FIFO. */
uint8_t ahbGrantTimeoutCycle; /*!< Timeout wait cycle for AHB command grant,
timeout after ahbGrantTimeoutCyle*1024 AHB clock cycles. */
uint16_t ahbBusTimeoutCycle; /*!< Timeout wait cycle for AHB read/write access,
timeout after ahbBusTimeoutCycle*1024 AHB clock cycles. */
uint8_t resumeWaitCycle; /*!< Wait cycle for idle state before suspended command sequence
resume, timeout after ahbBusTimeoutCycle AHB clock cycles. */
flexspi_ahbBuffer_config_t buffer[FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT]; /*!< AHB buffer size. */
bool enableClearAHBBufferOpt; /*!< Enable/disable automatically clean AHB RX Buffer and TX Buffer
when FLEXSPI returns STOP mode ACK. */
bool enableReadAddressOpt; /*!< Enable/disable remove AHB read burst start address alignment limitation.
when eanble, there is no AHB read burst start address alignment limitation. */
bool enableAHBPrefetch; /*!< Enable/disable AHB read prefetch feature, when enabled, FLEXSPI
will fetch more data than current AHB burst. */
bool enableAHBBufferable; /*!< Enable/disable AHB bufferable write access support, when enabled,
FLEXSPI return before waiting for command excution finished. */
bool enableAHBCachable; /*!< Enable AHB bus cachable read access support. */
} ahbConfig;
} flexspi_config_t;
参考野火说明
rxSampleClock
枚举类型,选择读时序的时候数据采样信号源常用的有三个,见上一篇中 27.5.14 FlexSPI输入时序;
enableSckFreeRunning
使能SCK时钟自由输出,不受CS时序控制;
enableCombination
绑定功能,使能后PortA的4Bit和PortB的4Bit绑定,形成8Bit并行输出模式;
enableDoze
使能 Doze 模式,使能了 doze 模式后,即使 RT1052 芯片处于低功耗 stop 运行状态时 FlexSPI 也能正常工作。
enableHalfSpeedAccess
配置是否使能对 SCK 时钟进行 2 分频以降低访问速率;
enableSckBDiffOpt
配置是否把 SCKB 用作 SCKA 的差分时钟,使用 2 线差分的形式可以提高抗干扰的能力,不过此时 PORT B 就不能再用于 FLASH 的时钟信号,也就是无法使用了;
enableSameConfigForAll
配置是否使能所有连接的设备都用同样的配置,如果使能的话, FLASHA1CRx 寄存器的配置会被应用到所有的设备。
seqTimeoutCycle
设置命令序列执行的等待超时周期, 设置结果为 seqTimeoutCycle*1024 个 FlexSPI 根时钟周期后超时,超时后可产生中断且会忽略 AHB 命令。 若本成员设置为 0 则不使用本功能;
ipGrantTimeoutCycle
配置 IP 命令授予等待超时周期, 即触发 IP 命令后,若命令仲裁器在 ipGrantTimeoutCycle*1024 个 AHB 时钟周期后还不允许执行该命令,则可触发中断。 注意本功能仅支持调试模式,使用时直接设置为默认值即可,且不能设置为 0!
txWatermark
配置 IP 发送的水印值,单位为字节。当IP_TX_FIFO 的空余的程度大于或等于该水印值时,可触发 IPTXWE 中断,同时也可触发 DMA 请求从而往 IP_TX_FIFO 填充要传输的数据。
rxWatermark
配置接收的水印值,单位为字节。 当IP_RX_FIFO 接收的数据超过该水印值时,可触发 IPRXWA 中断,同时也可触发DMA 请求把数据从 IP_RX_FIFO 转移出去。
ahbConfig 是一个和AHB总线配置相关的结构体
enableAHBWriteIpTxFifo
配置是否使能 AHB 总线通过映射地址(0x7F800000-0x11000400) 对 IP_TX_FIFO 的写访问。使能后,可通过 AHB 总线映射的地址向 IP_TX_FIFO 写入内容,此时通过 IP 总线写入 IP_TX_FIFO 的操作(即直接向寄存器进行写入操作) 会被忽略,但不会出现错误标志;若不使能,可通过 IP 总线写入 IP_TX_FIFO, 此时通过 AHB 总线的写入操作会被忽略,且会产生错误标志;
enableAHBWriteIpRxFifo
配置是否使能 AHB 总线通过映射地址(0x7FC00000 -0x10000200) 对 IP_RX_FIFO 的读访问。 与enableAHBWriteIpTxFifo 的类似,用于控制使用 AHB 还是 IP 进行读操作。
ahbGrantTimeoutCycle
与 ipGrantTimeoutCycle 成员类似,ahbGrantTimeoutCycle 用于配置 AHB 命令授予等待超时周期, 即触发 AHB 命令后,若命令仲裁器在在 ahbGrantTimeoutCyle*1024 个 AHB 时钟周期后还不允许执行该命令,会触发中断。 注意本功能同样仅支持调试模式,使用时直接设置为默认值即可,且不能设置为 0!
ahbBusTimeoutCycle
配置 AHB 读写访问超时周期, 在超过ahbBusTimeoutCycle*1024 个 AHB 时钟周期后, 仍没接收到数据或没发送出数据则表示访问超时,触发时可产生 AHBBUSTIMEOUT 中断。
resumeWaitCycle
配置在暂停命令序列恢复之前, 等待空闲状态的周期, 等待超过 resumeWaitCycle 个 AHB 时钟后超时。
buffer 是一个结构体 flexspi_ahbBuffer_config_t
typedef struct _flexspi_ahbBuffer_config
{
uint8_t priority; /*!< This priority for AHB Master Read which this AHB RX Buffer is assigned. */
uint8_t masterIndex; /*!< AHB Master ID the AHB RX Buffer is assigned. */
uint16_t bufferSize; /*!< AHB buffer size in byte. */
bool enablePrefetch; /*!< AHB Read Prefetch Enable for current AHB RX Buffer corresponding Master, allows
prefetch disable/enable seperately for each master. */
} flexspi_ahbBuffer_config_t;
配置 AHB 缓冲区的一些信息,它包含的配置参数分别为缓冲区的优先级、主索引号以及缓冲区的大小这些信息;
enableClearAHBBufferOpt
配置是否使能自动清除 AHB RX 和 TX 缓冲的功能,使能后, 当 FLEXSPI 退出停止模式时自动清除。
enableAHBPrefetch
配置是否使能 AHB 预读取特性,当使能时,FLEXSPI 会读取比当前 AHB 突发读取方式更多的数据,提高效率。
enableAHBBufferable
配置是否使能 AHB 缓冲写访问的功能,当使能时, FLEXSPI 会在命令执行完成前就返回,否则会等待至 AHB 总线准备好并把数据传输至外部设备且命令执行完成后才返回。
enableAHBCachable
配置是否使能 AHB 总线缓冲读访问的功能。
在应用初始化配置结构体时,通常先直接调用库函数FLEXSPI_GetDefaultConfig(); 赋予常用默认配置,然后再针对性地把初始化配置结构体修改成自己需要的内容
和FPGA连接的话其实需要关心的是时序和AHB访问方式,后面会着重看AHB相关的内容。关于AHB访问和IP访问,可以看看前面几篇内容。
未完,下篇继续