Hello,
I am struggling with the configuration of the FLEXSPI peripheral on a LPC5536JBD100; the hyperram chip is a S27KS0642GABHV020. The system is on a custom board on which we already successfully integrated other features.
I got inspired by AN12239 which is for a different processor but takes as example a very similar chip to the one I am using: it seems to me that the main difference is in the newer node technology for S27KS0642 which makes it faster than the S27KS0641 used in the application node but the timing diagrams (and so the dummy cycles) and the commands are the same.
Another source of inspiration is from this article
https://community.nxp.com/t5/MCX-Microcontrollers-Knowledge/MCX-N947-FlexSPI-Connecting-to-HyperRAM-...
which is not for the same processor I am using but explains the meaning of some fields in the configuration data structures.
I also looked at the example lpcxpresso55s36_flexspi_octal_polling_transfer for comparing the FlexSPI configuration (knowing that something must be changed because it targets a flash device).
My symptom is that when I try to read the vendor id, the function does not return kStatus_Success (it returns the value 7001).
I checked that the clock is connected:
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 */
and the pins have been configured with the GUI

The configuration of the perihperal is done as
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;
}
I checked that we are using the port A1 even in the function that reads the vendor ID
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;
}
The flexspi_device_config_t structure is initialized as follows
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,
};
and the LUTs values are
#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),
};
which make sense to me because I am using a total of 48 address bits, DDR mode on 8 pads, the commands are correct.
Is there something I am missing?