如何在MCXN947板的FlexSPI接口接HyperRAM

描述

概述

MCXN947芯片是一款高度集成的微控制器,具有强大的处理能力、丰富的外设支持和高级安全特性,适用于多种复杂应用。其中有个非常重要的外设为FlexSPI。

FlexSPI是一种可扩展的串行外设接口,主要用于连接固态存储设备,如QuadSPI NOR Flash、QuadSPI NAND Flash、HyperRAM等。FlexSPI是一种全面的、灵活的、高性能的解决方案,可以配置成不同的模式以适应不同的存储设备。

NXP FRDM-MCXN947板是一款基于MCXN947设备的低成本设计与评估板。NXP为MCXN947设备提供了包括硬件评估板、软件开发集成开发环境(IDE)、示例应用程序和驱动程序在内的工具和软件支持。该板FlexSPI接口默认接了一块MT35XU512 NOR Flash。

NXP

在本文中,我们将探讨如何在MCXN947板的FlexSPI接口接HyperRAM。

硬件环境:

开发板:FRDM-MCXN947

HyperRAM:W956D8MBYA

软件环境:

IDE:MCUXpresso IDE v11.9.0

SDK:SDK Builder | MCUXpresso SDKBuilder (nxp.com)

HyperRAM原理图

以下是官方FRDM-MCXN947中的八线Flash的原理图,由于W956D8MBYA的HyperRAM的封装都为TFBGA 24-Ball 5 x 5 Array,所以可以直接进行替换。

NXP

根据以上原理图,总结出HyperRAM存储器的信号连接方式见表:

NXP

HyperRAM配置流程

3.1 时钟配置

FlexSPI的时钟需要正确配置。

NXP

我们在调试程序的阶段还是保险地选择低一点的频率,这里选择75MHz。

3.2 FlexSPI初始化配置结构体详解

接下来是FlexSPI相关配置,我们可以调用FLEXSPI_GetDefaultConfig获取一些针对FlexSPI特性结构体flexspi_config_t的一些默认配置,这个默认配置具有一定的普遍性,能兼容大部分的FlexSPI设备,对于该W956D8MBYA 的HyperRAM,在默认配置的基础上,增加如下几个参数:

config.ahbConfig.enableAHBPrefetch = true;

config.ahbConfig.enableAHBBufferable = true;

config.ahbConfig.enableReadAddressOpt= true;

config.ahbConfig.enableAHBCachable = true;

config.rxSampleClock= kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;

(1)enableAHBPrefetch:是否使能AHB预读取特性,当使能时,FlexSPI会读取比当前AHB突发读取更多的数据。

(2)enableAHBBufferable :是否使能AHB写缓冲访问,在执行写命令后,不等待其执行完毕就返回,允许后续指令继续执行,提高系统的并发性。

(3)enableReadAddressOpt:控制是否移除AHB读取突发起始地址对齐限制,若使能,突发读取地址没有字节对齐限制。

(4)enableAHBCachable:使能AHB总线缓存读取,若命中则从缓存中读取,但要确保数据的一致性

(5)rxSampleClock:读数据使用的时钟源,对于HyperRAM来说,HyperRAM提供读选通脉冲并从DQS引脚输入。

3.3 FlexSPI外部设备配置结构体详解

FlexSPI与外部设备通讯时常常需要与设备协调通讯的时序,如时钟频率、数据有效时间等内容,NXP软件库提供了结构体类型flexspi_device_config_t专门用于配置这些参数。

 

typedef struct _flexspi_device_config


{


uint32_t flexspiRootClk;


bool isSck2Enabled;


uint32_t flashSize;


flexspi_cs_interval_cycle_unit_t CSIntervalUnit;


uint16_t CSInterval;


uint8_t CSHoldTime;


uint8_t CSSetupTime;


uint8_t dataValidTime;


uint8_t columnspace;


bool enableWordAddress;


uint8_t AWRSeqIndex;


uint8_t AWRSeqNumber;


uint8_t ARDSeqIndex;


uint8_t ARDSeqNumber;


flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit;


uint16_t AHBWriteWaitInterval;


bool enableWriteMask;


} flexspi_device_config_t;

 

(1) flexspiRootClk = 75000000,此参数与前面设置的FlexSPI的时钟频率一致。

(2) flashSize = 0x2000, Flash的大小,以KB为单位。对于W956D8MBYA,64Mb = 8MB = 8 *1024KB。

(3) CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,此参数用于配置CS信号线间隔的时间单位。

(4) CSInterval = 2,此参数用于配置CS信号线有效与无效切换的最小时间间隔,单位为上面CSIntervalUnit成员的配置。

(5) CSHoldTime = 3,此参数用于设定CS信号线的保持时间,单位为FlexSPI根时钟周期。

(6) CSSetupTime=3,此参数用于设定CS信号线的建立时间,单位为FlexSPI根时钟周期。

NXP

NXP

根据MCXNx4x datasheet, = 6ns,最小的 = 8.3ns,最小的 = 9.8ns。时钟为75M的周期时间大约是13.3ns。故CSHoldTime和CSSetupTime大于等于1即可,均配置成3。

(7) dataValidTime=2,寄存器DLLACR和DLLBCR,本成员用于配置通讯中的数据有效时间,单位为纳秒。

(8) columnspace = 3,低位列地址宽度,对于这个HyperRAM来说,是用行列进行寻址的,这里列地址的宽度为3位。

NXP

(9) enableWordAddress = true,配置是否使能2字节可寻址功能,使能后会以16位的数据格式对HyperRAM进行访问。

(10) AWRSeqIndex = 1,对应写的时序序列在LUT中的索引。

(11) AWRSeqNumber =1,此参数配置AHB写命令的序列数目。

(12) ARDSeqIndex = 0,对应读的时序序列在LUT中的索引。

(13) ARDSeqNumber =1,此参数配置AHB读命令的序列数目。

(14) enableWriteMask = true,此参数用于设置FlexSPI写外部设备时是否使能驱动DQS位作为掩码,这种功能在访问数据宽度为16位时用于地址对齐。

3.4 LUT表格配置

下面是HyperRAM 读和写的时序LUT表格的代码示例,

 

const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {


/* Read Data */


   [4 * PSRAM_CMD_LUT_SEQ_IDX_READDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,kFLEXSPI_8PAD, 0xA0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),


   [4 * PSRAM_CMD_LUT_SEQ_IDX_READDATA + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR,kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x07),


   [4 * PSRAM_CMD_LUT_SEQ_IDX_READDATA + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR,kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),


   /* Write data */


   [4 * PSRAM_CMD_LUT_SEQ_IDX_WRITEDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),


   [4 * PSRAM_CMD_LUT_SEQ_IDX_WRITEDATA + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR,kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x07),


   [4 * PSRAM_CMD_LUT_SEQ_IDX_WRITEDATA + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR,kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),






};

 

(1) 我们使用的是8线差分的HyperRAM,在时钟的双边沿都采样,所以与外部存储器通信时用的数据线的个数均为kFLEXSPI_8PAD。

(2) HyperRAM和HyperFlash是基于Cypress Semiconductor的HyperBus接口规范设计的存储器产品,这个operand是在该规范中定义的,所以读操作operand固定为0xA0,写数据的operand固定为0x20。

NXP

(3) CADDR_DDR列地址,由于一次传输的字节一定是8的倍数,如果你传的行列地址大于特定大小的HyperRAM最大的行和列,FlexSPI会自动将高位置0。

上表中显示低16位是列地址,有效位有3位,高13位是预留兼容的列地址位,需要置0。所以这里列地址的时序参数需要填16,即0x10。

NXP

(4) RADDR_DDR行地址,如图所示,如果 FLSHxxCR1[CAS] 位不为 0 ,那么 FlexSPI 外设在传输时序里会拆分实际映射 Flash Address (即存储器自身偏移地址) 为行地址 FA[31:CAS] 和列地址 [CAS-1:1] 来分别传输。对于字可寻址闪存设备,不需要地址的最后一位,因为闪存是按照两个字节读取和编程的。Flexspi 一个字为两个字节,所有需要如果2个字节对齐,就需要少一位地址。行列地址加一起少一位。W956D8MBYA有64Mbit,即2^26,列地址还有3位,所以理论上行地址需要传输26-1-3=22位,即可寻址整个HyperRAM。然后向8位对齐,不然FlexSPI会在低位补0,就不是我们要访问的地址了。所以参数为0x18,即24位。

实验验证 我们可以利用简单的AHB读写来验证此HyperRAM是否可以工作。

代码如下:

 

for (i = 0; i < sizeof(s_psram_write_buffer); i++)


{


s_psram_write_buffer[i] = i;


}


memcpy((uint32_t*)(EXAMPLE_FLEXSPI_AMBA_BASE), s_psram_write_buffer, sizeof(s_psram_write_buffer));


memcpy(s_psram_read_buffer,(uint32_t*)(EXAMPLE_FLEXSPI_AMBA_BASE) , sizeof(s_psram_read_buffer));


if (memcmp(s_psram_read_buffer, s_psram_write_buffer,sizeof(s_psram_write_buffer)) == 0)


{


      PRINTF("AHB Command Read/Write data successfully !
");


}

 

当你的串口打印出"AHB Command Read/Write data successfully!"

证明你的FlexSPI接HyperRAM现在可以正常工作啦!

作者:Hang Zhang

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分