I.MX RT1170之FlexSPI(2):LUT表格的组成和FlexSPI结构体配置

从上一节FlexSPI的框图中可知,SEQ_CTL实现了对外部存储器的时序控制。不同的存储器有着不同的时序,这个时序就是由LUT(Look Up Table)指定的。LUT有它自己的寄存器,当我们设置好之后,外部存储器的读、写和擦除等操作就会根据LUT寄存器中配置执行。另外除了配置LUT表格外,还需要配置FlexSPI的一些参数,以适应不同的硬件上的设计和不同的外部存储器。

1 LUT表格的组成

LUT表格的组成如下图所示,一个表格中包含多个Sequence,一个Sequence包含8个Instruction,而Instruction则是由opcodenum_padsoperand三个字段组成。
在这里插入图片描述
(1)opcode
这是由FlexSPI硬件上定义的一些固定的操作码,如读数据操作、空指令、停止指令等都有其对于的操作码。

NameOpcodepurposeTransmit DataBits/Bytes/Cycle Number
CMD_SDR/CMD_DDR0x01/0x21命令代码Operand[7:0]8 bits
RADDR_SDR/RADDR_DDR0x02/0x22行地址Row_address[31:0]由operand[7:0]指定行地址的bits
CADDR_SDR/CADDR_DDR0x03/0x23列地址Column_address[31:0]由operand[7:0]指定列地址的bits
MODE1_SDR/MODE1_DDR0x04/0x24模式序列Operand[0]1 bit
MODE2_SDR/MODE2_DDR0x05/0x25模式序列Operand[1:0]2 bit
MODE4_SDR/MODE4_DDR0x06/0x26模式序列Operand[3:0]4 bit
MODE8_SDR/MODE8_DDR0x07/0x27模式序列Operand[7:0]8 bit
WRITE_SDR/WRITE_DDR0x08/0x28写数据IP TX FIFO or AHB_TX_BUFAHB Burst size or IPCR1[IDATSZ]
READ_SDR/READ_DDR0x09/0x29读数据-AHB Burst size or IPCR1[IDATSZ]
LEARN_SDR/LEARN_DDR0x0A/0x2A读数据/引导位(学习时序)-由operand[7:0]决定
DATSZ_SDR/DATSZ_DDR0x0B/0x2B当前序列读/写数据长度主要用于FPGA,取决于其内部逻辑由operand[7:0]决定
DUMMY_SDR/DUMMY_DDR0x0C/0x2C延时等待-由operand[7:0]决定Dummy的cycle(SCLK)
DUMMY_RWDS_SDR/DUMMY_RWDS_DDR0x0D/0x2DHyperBus设备中用于数据和命令的时钟同步-与operand[7:0]和DQS pin有关
JMP_ON_CS0x1F序列跳转--
STOP0x00停止序列--
  • 对于JMP_ON_CSSTOP来说,它们的num_pads会被忽略;而其它的指令则根据不同的指令指定num_pads

(2)num_pads
与外部存储器通信时用的数据线的个数,取值如下:

#define FLEXSPI_1PAD 0
#define FLEXSPI_2PAD 1
#define FLEXSPI_4PAD 2
#define FLEXSPI_8PAD 3

比如对于八线的HyperRAM来说,传输数据时这个参数就是FLEXSPI_8PAD ,即数据在硬件连接的所有线上传输。但对于某些指令来说,num_pads只需要设置为FLEXSPI_1PAD,如停止指令,它只需要一个数据位即可。

(3)operand
即前面的操作码对应的参数。

2 FlexSPI结构体配置

对于不同的外部存储器来说,有不同的行/列寻址宽度、不同的存储器大小等参数,而这些参数都是在FlexSPI相关结构体中配置。首先我们就以HyperRAM的初始化代码为例,看一下FlexSPI的初始化代码:

flexspi_device_config_t deviceconfig = {
    .flexspiRootClk = 332000000,
    ......//略
};
flexspi_config_t config;
/* Get FLEXSPI default settings and configure the flexspi. */
FLEXSPI_GetDefaultConfig(&config);
FLEXSPI_Init(EXAMPLE_FLEXSPI, &config);
/* Configure RAM settings according to serial RAM feature. */
FLEXSPI_SetFlashConfig(EXAMPLE_FLEXSPI, &deviceconfig, kFLEXSPI_PortA1);
/* Update LUT table. */
FLEXSPI_UpdateLUT(EXAMPLE_FLEXSPI, 0, customLUT, ARRAY_SIZE(customLUT));
/* Do software reset. */
FLEXSPI_SoftwareReset(EXAMPLE_FLEXSPI);

从上面的代码可以知道,在初始化过程中,flexspi_config_tflexspi_device_config_t这两个结构体需要我们进行填充。其中flexspi_config_t主要是对FlexSPI的一些功能的配置,而flexspi_device_config_t则是对特定的存储器的一些时序、参数配置。

2.1 flexspi_config_t

flexspi_config_t结构体的定义如下,各个参数的详细解释我都写在注释中了。

typedef struct _flexspi_config
{
	/* 读数据使用的时钟源 */
    flexspi_read_sample_clock_t rxSampleClock; 
    /* 在没有外部驱动时,SCK将以固定频率产生脉冲 */
    bool enableSckFreeRunning;
    /* 使能PORTA和PORTB的数组组合来支持8位访问 */
    bool enableCombination;
    /* 是否使能低功耗Dozeoze模式 */
    bool enableDoze;
 	 /* 将时钟速率减缓一半,减慢传输速度但增大容错率 */
    bool enableHalfSpeedAccess; 
 	 /* 使能SCKB作为SCKA的差分时钟,若使能PORTB的设备无法访问 */
    bool enableSckBDiffOpt;
 	 /* 若使能FLASHA1CRx寄存器的配置会共享给其它的设备 */
    bool enableSameConfigForAll;
    /* 命令执行的超时周期,防止系统卡在等待某个状态上,系统将在ahbGrantTimeoutCyle*1024个串行时钟周期后返回超时 */
    uint16_t seqTimeoutCycle; 
  	/* IP命令执行的超时周期,系统将在ipGrantTimeoutCycle*1024个AHB时钟周期后返回超时 */
    uint8_t ipGrantTimeoutCycle;
  	/* IP发送FIFO大小,与串口watermark类似,只有满了才发 */
    uint8_t txWatermark;
  	/* 接收FIFO大小,只有满了才收 */
    uint8_t rxWatermark;
    struct
    {
   		 /* FlexSPI从AHB总线获取执行命令的访问权限的超时时间 */	 
        uint8_t ahbGrantTimeoutCycle;
   		 /* AHB读写访问超时周期 */
        uint16_t ahbBusTimeoutCycle;
    	/* FlexSPI支持暂停当前命令序列而稍后执行,该值表示在后续恢复命令前等待的空闲周期数 */
        uint8_t resumeWaitCycle;
        /* 使能在每次数据传输完成后清除RX/TX的buffer */
        bool enableClearAHBBufferOpt; 
    	/* 控制是否移除AHB读取突发起始地址对齐限制,若使能,突发读取地址没有字节对齐限制 */
        bool enableReadAddressOpt;
    	/* 使能AHB读取预取功能:在完成当前AHB突发读取后,预先读取一些额外的数据到缓冲区中以加快后续读取,但这会增加功耗 */
        bool enableAHBPrefetch; 
    	/* 是否开启AHB写缓冲访问:在执行写命令后,不等待其执行完毕就返回,允许后续指令继续执行,提高系统的并发性 */
        bool enableAHBBufferable;
    	/* 使能AHB总线缓存读取,若命中则从缓存中读取,但要确保数据的一致性 */
        bool enableAHBCachable;       /*!< Enable AHB bus cachable read access support. */
    } ahbConfig;
} flexspi_config_t;

2.2 flexspi_device_config_t

flexspi_device_config_t结构体的定义如下:

typedef struct _flexspi_device_config
{
    /* FLEXSPI串行根时钟频率 */
    uint32_t flexspiRootClk;
    /* 是否启用第二个串行时钟线:硬件上连了两个时钟线 */
    bool isSck2Enabled;
    /* 外部存储设备的大小,以KB为单位 */
    uint32_t flashSize;
    /* 定义在连续的CS信号之间的时间间隔单位:1或256个串行时钟周期 */
    flexspi_cs_interval_cycle_unit_t CSIntervalUnit;
    /* CS线的保持时间,单位为CSIntervalUnit */
    uint16_t CSInterval;
    /* CS线的保持时间 */
    uint8_t CSHoldTime;
    /* CS线设置时间,即在发送片选信号之前需要等待的时间 */
    uint8_t CSSetupTime;
    /* 在读取数据之后,数据保持有效的时间 */
    uint8_t dataValidTime;
    /* 列地址宽度 */
    uint8_t columnspace;
    /* 是否使用字地址来访问外部设备,有的存储设备支持按字传输 */
    bool enableWordAddress;
    /* AHB写命令的序列ID:对应LUT表格中的顺序 */
    uint8_t AWRSeqIndex;
    /* AHB写命令的数量 */
    uint8_t AWRSeqNumber;
    /* AHB读命令的序列ID:对应LUT表格中的顺序 */
    uint8_t ARDSeqIndex;
    /* AHB读命令的数量 */
    uint8_t ARDSeqNumber;
    /* AHB写等待单位 */
    flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit;
    /* AHB写等待间隔,乘以AHB写等待单位得到AHB写等待周期数,即写完后等待外部存储器处理完数据的时间 */
    uint16_t AHBWriteWaitInterval;
    /* 是否启用写入屏蔽。指示在向外部设备写入数据时是否将FLEXSPI的DQS引脚用作写入屏蔽 */
    bool enableWriteMask;
} flexspi_device_config_t;

AHB读/写命令的数量?
以写命令的数量AWRSeqNumber为例:对于某些存储设备(例如HyperFlash/HyperRam/Serial NAND),Flash编程访问是通过几个命令序列完成,也就是说AHB写命令将触发LUT中AWRSeqIndex开始的AWRSeqNumber个命令序列。

3 总结

本节介绍了LUT表格的组成和FlexSPI配置结构体的各个参数的含义,有了这些基础知识后,我们就可以初始化不同的外部存储器设备了。下一节将举一个例子,通过外部存储器与FlexSPI连接的原理图和外部存储器的时序手册,来看看这些参数是如何初始化的。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tilblackout

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值