LPC5536 和 Hyperram 你好 我在 LPC5536JBD100 上配置 FLEXSPI 外设时遇到了难题;hyperram 芯片是 S27KS0642GABHV020。该系统位于自定义板上,我们已经成功地在其中集成了其他功能。 我受到 AN12239 的启发,它适用于不同的处理器,但以一种与我正在使用的芯片非常相似的芯片为例:在我看来,主要区别在于 S27KS0642 的新节点技术,它比应用程序节点中使用的 S27KS0641 更快,但时序图(因此虚拟周期)和命令是相同的。 另一个灵感来源是这篇文章 https://community.nxp.com/t5/MCX-Microcontrollers-Knowledge/MCX-N947-FlexSPI-Connecting-to-HyperRAM-Analysis-and/ta-p/1988799 这与我使用的处理器不同,但解释了配置数据结构中某些字段的含义。 我还看了示例 lpcxpresso55s36_flexspi_octal_polling_transfer 来比较 FlexSPI 配置(知道必须进行某些更改,因为它针对的是闪存设备)。 我的症状是,当我尝试读取供应商 ID 时,函数不返回 kStatus_Success(返回值为 7001)。 我检查了时钟是否已连接: CLOCK_SetClkDiv(kCLOCK_DivFlexSpiClk, 0U, true); /*!< Reset FLEXSPICLKDIV divider counter and halt it */ CLOCK_SetClkDiv(kCLOCK_DivFlexSpiClk, 2U, false); /*!< Set FLEXSPICLKDIV divider to value 2 */ CLOCK_AttachClk(kPLL0_to_FLEXSPI); /*!< Switch FLEXSPI to PLL0 */ 并通过图形用户界面配置了引脚 周波的配置方式为 int config_hr(void) { flexspi_config_t config; uint32_t tempCustomLUT[ARRAY_SIZE(customLUT)] = {0U}; /* Copy LUT information from flash region into RAM region, because flash will be reset and back to single mode; In lately time, LUT table assignment maybe failed after flash reset due to LUT read entry is application's required mode(such as octal DDR mode) and flash is being in single SDR mode, they don't matched. */ memcpy(tempCustomLUT, customLUT, sizeof(tempCustomLUT)); /* Get FLEXSPI default settings and configure the flexspi. */ FLEXSPI_GetDefaultConfig(&config); /* Init FLEXSPI. */ config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad;//kFLEXSPI_ReadSampleClkLoopbackFromDqsPad;//kFLEXSPI_ReadSampleClkExternalInputFromDqsPad; //config.enableSckBDiffOpt = true; //config.enableCombination = true; config.ahbConfig.enableAHBPrefetch = true; config.ahbConfig.enableAHBBufferable = true; config.ahbConfig.enableAHBCachable = true; // config.enableDoze = false; 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, tempCustomLUT, ARRAY_SIZE(customLUT)); /* Do software reset. */ FLEXSPI_SoftwareReset(EXAMPLE_FLEXSPI); return 0; } 我检查过了,即使在读取供应商 ID 的函数中,我们使用的也是 A1 端口 status_t flexspi_hyper_ram_get_id(FLEXSPI_Type *base, uint32_t *vendorId) { flexspi_transfer_t flashXfer; status_t status; uint32_t id; /* Write data */ flashXfer.deviceAddress = 0x0U; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Read; flashXfer.SeqNumber = 1; flashXfer.seqIndex = HYPERRAM_CMD_LUT_SEQ_IDX_READREG; flashXfer.data = &id; flashXfer.dataSize = 4; status = FLEXSPI_TransferBlocking(base, &flashXfer); *vendorId = id & 0xffffU; return status; } flexspi_device_config_t 结构的初始化过程如下 flexspi_device_config_t deviceconfig = { .flexspiRootClk = 75000000, /* 75MHZ SPI serial clock */ .isSck2Enabled = false, .flashSize = FLASH_SIZE, .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle, .CSInterval = 2, .CSHoldTime = 1, .CSSetupTime = 1, .dataValidTime = 1, .columnspace = 3, .enableWordAddress = true, .AWRSeqIndex = HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA, .AWRSeqNumber = 1, .ARDSeqIndex =HYPERRAM_CMD_LUT_SEQ_IDX_READDATA, .ARDSeqNumber = 0, .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle, .AHBWriteWaitInterval = 0, .enableWriteMask = true, }; LUT 值为 #define LATENCY (0x04) uint32_t customLUT[20] = { /* Read Data */ [4 * HYPERRAM_CMD_LUT_SEQ_IDX_READDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0,kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_READDATA + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, LATENCY), [4 * HYPERRAM_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 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, LATENCY), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEDATA + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), /* Read Register */ [4 * HYPERRAM_CMD_LUT_SEQ_IDX_READREG] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xE0,kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_READREG + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, LATENCY), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_READREG + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), /* Write Register */ [4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x60,kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, LATENCY), [4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), }; 这对我来说很有感知,因为我总共使用了 48 个地址位,8 个键盘上有 DDR 模式,命令是正确的。 我是不是漏掉了什么? Re: LPC5536 and Hyperram 你好 谢谢。 不,我配置了更多引脚,但截图拍得很差:我猜有 8 个数据引脚,一个 RWDS、一个 CS_n 和一对差分时钟引脚。 Re: LPC5536 and Hyperram 你好@img_gabrigob
关于引脚配置
您是否只配置了 5 个数据引脚?
S27KS0642GABHV020 需要 8 个数据引脚。
BR
哈利
Re: LPC5536 and Hyperram 你好 谢谢。我给你回复了,但我想我做错了什么(第一次使用这个社区),回复直接转到了我的原帖。 Re: LPC5536 and Hyperram 你好@img_gabrigob
首先,我认为您可以检查硬件。
探测物理信号(示波器):
确认 CK 按您预期的速率切换,交易的 CS# 脉冲,当您触发信号 Read-ID 序列时,DQ [7:0]/RWDS 会显示活动。
并将 FlexSPI 串行时钟降低到较低的安全频率(例如20-25 MHz),同时进行调试。
那么我认为您可以参考这个 LUT。
/* Read Register */
[4 * HYPERRAM_CMD_LUT_SEQ_IDX_READREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xE0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
[4 * HYPERRAM_CMD_LUT_SEQ_IDX_READREG + 1] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x06),
[4 * HYPERRAM_CMD_LUT_SEQ_IDX_READREG + 2] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
/* Write Register */
[4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG] =
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x60, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
[4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG + 1] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x06),
[4 * HYPERRAM_CMD_LUT_SEQ_IDX_WRITEREG + 2] = FLEXSPI_LUT_SEQ(
kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
RT1064 HyperRAM 支持 S27KS0641 和 S27KS0642 - NXP Community
BR
哈利 Re: LPC5536 and Hyperram 你好,@Harry_Zhang、 谢谢您! 我试着查看我的 LUT 与您链接的另一篇文章中用户使用的 LUT 之间是否存在任何差异,但即使在尝试调整延迟等待状态下的假人数量后,我还是遇到了同样的问题。 我不知道我是否在安装 IDE 时配置错误,但在 LPC5536 上,我似乎无法通过 flexspi_config_t 数据结构设置差分时钟(字段 enableSckBDiffOpt 位于禁用的 ifdef 中)。 我们在董事会采取了一些措施。CSN 和 CLK 信号处于激活状态。 我们使用两种压摆率(标准和高)来捕获时钟 时钟频率比我预想的要慢(我想我把它设置为 75MHz,这里是 75/2,而不是 150/2)。 数据和 RWDS 信号稳定在 0V。我们只是在数据信号上看到一个小故障(5 毫微秒)。 我还附上了从图形用户界面输出的 pin_mux 和 clock_config 文件。 请问您还有其他建议吗? 顺祝商祺! Re: LPC5536 and Hyperram 您好! 感谢您的回复 我再次检查了电路图,...我意识到 RESN 不受 FLEXspi 控制,因此我更改了软件,使其上升。 现在控制器可以工作了,我们还将 MCU 上的引脚配置为快速转换速率选项。 例如,这是 RWDS 与 CLK 的对比。 因此,问题在于 LUT 中的延迟值(使用您的链接进行更正)和 RESET。 我还有一些不明白的地方,即使这对这个项目并不重要,但可能对未来的应用有用:从时钟树中的配置来看,我期望 CLK 频率为 75MHz,但我测量的频率为 37.5MHz。 还有其他我错过的时钟分频器吗? 谢谢! 顺祝商祺! 加布里埃尔 Re: LPC5536 and Hyperram 你好@img_gabrigob
您能分享与 HyperRAM 的连接原理图吗?
BR
哈利 Re: LPC5536 and Hyperram 你好@img_gabrigob
根据 LPC55S36 数据表。
时钟频率最高为 50M(DDR 模式)。
/* Flexspi frequency 150MHz / 3 = 50MHz */
CLOCK_SetClkDiv(kCLOCK_DivFlexSpiClk, 0U, true); /*!< Reset FLEXSPICLKDIV divider counter and halt it */
CLOCK_SetClkDiv(kCLOCK_DivFlexSpiClk, 3U, false); /*!< Set FLEXSPICLKDIV divider to value 3 */
CLOCK_AttachClk(kPLL0_to_FLEXSPI); /*!< Switch FLEXSPI to PLL0 */
BR
哈利
記事全体を表示