查看: 2891|回复: 2

[原创] MCX N947:FlexSPI接HyperRAM分析和配置

[复制链接]

该用户从未签到

723

主题

6382

帖子

0

超级版主

Rank: 8Rank: 8

积分
25459
最后登录
2025-9-4
发表于 2024-7-17 15:51:10 | 显示全部楼层 |阅读模式
本帖最后由 小恩GG 于 2024-7-17 15:52 编辑

MCX N947FlexSPIHyperRAM分析和配置
一、概述
MCXN947芯片是一款高度集成的微控制器,具有强大的处理能力、丰富的外设支持和高级安全特性,适用于多种复杂应用。其中有个非常重要的外设为FlexSPI。
FlexSPI是一种可扩展的串行外设接口,主要用于连接固态存储设备,如QuadSPI NOR Flash、QuadSPI NAND Flash、HyperRAM等。FlexSPI是一种全面的、灵活的、高性能的解决方案,可以配置成不同的模式以适应不同的存储设备。
NXP FRDM-MCXN947板是一款基于MCXN947设备的低成本设计与评估板。NXP为MCXN947设备提供了包括硬件评估板、软件开发集成开发环境(IDE)、示例应用程序和驱动程序在内的工具和软件支持。该板FlexSPI接口默认接了一块MT35XU512 NOR Flash。
图片1.png
在本文中,我们将探讨如何在MCXN947板的FlexSPI接口接HyperRAM。
硬件环境:
l  开发板:FRDM-MCXN947
l  HyperRAM:W956D8MBYA
软件环境:
l  IDE:MCUXpresso IDE v11.9.0
二、 HyperRAM原理图
以下是官方FRDM-MCXN947中的八线Flash的原理图,由于W956D8MBYA的HyperRAM的封装都为TFBGA 24-Ball 5 x 5 Array,所以可以直接进行替换。
图片4.png
根据以上原理图,总结出HyperRAM存储器的信号连接方式见表。

  
HyperRAM芯片引脚
  
功能
MCXN947相连
CS
SPI通讯的CS片选信号
P3_0/FLEXSPI0_A_SS0_b
SCK
SPI通讯SCK时钟信号
P3_7/FLEXSPI0_A_SCLK
DQS
SPI通讯的DQS信号
P3_6/FLEXSPI0_A_DQS
DQ0
OSPI的数据信号D0
P3_8/FLEXSPI0_A_DATA0
DQ1
OSPI的数据信号D1
P3_9/FLEXSPI0_A_DATA1
DQ2
OSPI的数据信号D2
P3_10/FLEXSPI0_A_DATA2
DQ3
OSPI的数据信号D3
P3_11/FLEXSPI0_A_DATA3
DQ4
OSPI的数据信号D4
P3_12/FLEXSPI0_A_DATA4
DQ5
OSPI的数据信号D5
P3_13/FLEXSPI0_A_DATA5
DQ6
OSPI的数据信号D6
P3_14/FLEXSPI0_A_DATA6
DQ7
OSPI的数据信号D7
P3_15/FLEXSPI0_A_DATA7
三、 HyperRAM配置流程
3.1 时钟配置
FlexSPI的时钟需要正确配置。
图片5.png
我们在调程序的阶段还是保险地选择低一点的频率,这里选择75MHz。
3.2 FlexSPI初始化配置结构体详解
接下来是FlexSPI相关配置,我们可以调用FLEXSPI_GetDefaultConfig获取一些针对FlexSPI特性结构体flexspi_config_t的一些默认配置,这个默认配置具有一定的普遍性,能兼容大部分的FlexSPI设备,对于该W956D8MBYA的HyperRAM,在默认配置的基础上,增加如下几个参数:
  1. config.ahbConfig.enableAHBPrefetch    = true;
  2. config.ahbConfig.enableAHBBufferable  = true;
  3. config.ahbConfig.enableReadAddressOpt = true;
  4. config.ahbConfig.enableAHBCachable    = true;
  5. 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专门用于配置这些参数。
  1. typedef struct _flexspi_device_config
  2. {
  3.     uint32_t flexspiRootClk;
  4.     bool isSck2Enabled;
  5.     uint32_t flashSize;
  6.     flexspi_cs_interval_cycle_unit_t CSIntervalUnit;
  7.     uint16_t CSInterval;
  8.     uint8_t CSHoldTime;
  9.     uint8_t CSSetupTime;
  10.     uint8_t dataValidTime;
  11.     uint8_t columnspace;
  12.     bool enableWordAddress;
  13.     uint8_t AWRSeqIndex;
  14.     uint8_t AWRSeqNumber;
  15.     uint8_t ARDSeqIndex;
  16.     uint8_t ARDSeqNumber;
  17.     flexspi_ahb_write_wait_unit_t AHBWriteWaitUnit;
  18.     uint16_t AHBWriteWaitInterval;
  19.     bool enableWriteMask;
  20. } 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根时钟周期。
图片6.png
图片7.png
根据MCXNx4x datasheet, 屏幕截图 2024-07-17 151833.png = 6ns,最小的 屏幕截图 2024-07-17 151926.png = 8.3ns,最小的 屏幕截图 2024-07-17 151935.png = 9.8ns。时钟为75M的周期时间大约是13.3纳秒。故CSHoldTimeCSSetupTime大于等于1即可,均配置成3
(7)dataValidTime=2,寄存器DLLACR和DLLBCR,本成员用于配置通讯中的数据有效时间,单位为纳秒。
(8)columnspace = 3,低位列地址宽度,对于这个HyperRAM来说,是用行列进行寻址的,这里列地址的宽度为3位。
图片9.png
(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表格的代码示例,
  1. const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
  2.         /* Read Data */
  3.             [4 * PSRAM_CMD_LUT_SEQ_IDX_READDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
  4.             [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),
  5.             [4 * PSRAM_CMD_LUT_SEQ_IDX_READDATA + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),

  6.             /* Write data */
  7.             [4 * PSRAM_CMD_LUT_SEQ_IDX_WRITEDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
  8.             [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),
  9.             [4 * PSRAM_CMD_LUT_SEQ_IDX_WRITEDATA + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),   
  10. };
复制代码
(1)我们使用的是8线差分的HyperRAM,在时钟的双边沿都采用,所以与外部存储器通信时用的数据线的个数均为kFLEXSPI_8PAD
(2)HyperRAM和HyperFlash是基于Cypress Semiconductor的HyperBus™接口规范设计的存储器产品,这个operand是在该规范中定义的,所以读操作operand固定为0xA0,写数据的operand固定为0x20。
图片8.png
(3)CADDR_DDR列地址,由于一次传输的字节一定是8的倍数,如果你传的行列地址大于特定大小的HyperRAM最大的行和列,FlexSPI会自动将高位置0。
上表中显示低16位是列地址,有效位有3位,高13位是预留兼容的列地址位,需要置0。所以这里列地址的时序参数需要填16,即0x10。
图片10.png
(4)RADDR_DDR行地址,如图所示,如果 FLSHxxCR1[CAS] 位不为 0 ,那么 FlexSPI 外设在传输时序里会拆分实际映射 Flash Address (即存储器自身偏移地址) 为行地址 FA[31:CAS] 和列地址 [CAS-1:0] 来分别传输。对于字可寻址闪存设备,不需要地址的最后一位,因为闪存是按照两个字节读取和编程的。Flexspi 一个字为两个字节,所有需要如果2个字节对齐,就需要少一位地址。行列地址加一起少一位。W956D8MBYA64Mbit,即 屏幕截图 2024-07-17 154200.png ,列地址还有3位,所以理论上行地址需要传输26-1-3=22位,即可寻址整个HyperRAM。然后向8位对齐,不然FlexSPI会在低位补0,就不是我们要访问的地址了。所以参数为0x18,即24位。
四、实验验证
我们可以利用简单的AHB读写来验证此HyperRAM是否可以工作,代码如下:
  1. for (i = 0; i < sizeof(s_psram_write_buffer); i++)
  2. {
  3.     s_psram_write_buffer[i] = i;
  4. }

  5. memcpy((uint32_t*)(EXAMPLE_FLEXSPI_AMBA_BASE), s_psram_write_buffer, sizeof(s_psram_write_buffer));
  6.     memcpy(s_psram_read_buffer,(uint32_t*)(EXAMPLE_FLEXSPI_AMBA_BASE) , sizeof(s_psram_read_buffer));
  7. if (memcmp(s_psram_read_buffer, s_psram_write_buffer, sizeof(s_psram_write_buffer)) == 0)
  8. {
  9.             PRINTF("AHB Command Read/Write data successfully !\r\n");
  10. }
复制代码
当你的串口打印出“AHB Command Read/Write data successfully !”证明你的FlexSPI接HyperRAM可以正常工作。


回复

使用道具 举报

  • TA的每日心情
    奋斗
    2021-4-15 14:49
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    19

    主题

    133

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1242
    最后登录
    2025-8-21
    发表于 2024-7-18 21:42:30 来自手机 | 显示全部楼层
    没有测试速度?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    14

    主题

    58

    帖子

    0

    高级会员

    Rank: 4

    积分
    696
    最后登录
    2025-9-4
    发表于 2025-5-12 08:54:20 | 显示全部楼层
    似乎W956D8MBYA这个型号用错了,它是1.8V。
    应该是W956A8MBYA,这个才是3V的PSRAM。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-9-8 04:43 , Processed in 0.088354 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表