123 lines
4.1 KiB
C
123 lines
4.1 KiB
C
#include "app_fspi.h"
|
|
|
|
#include "fsl_clock.h"
|
|
#include "fsl_flexspi.h"
|
|
|
|
#define FSPI_BASE FLEXSPI
|
|
#define FSPI_PORT kFLEXSPI_PortB1
|
|
|
|
#define FSPI_SEQ_WR_IDX 0
|
|
#define FSPI_SEQ_W1_IDX 1
|
|
#define FSPI_SEQ_RD_IDX 2
|
|
#define FSPI_SEQ_R_REG_IDX 3
|
|
#define FSPI_SEQ_INVALID 4
|
|
|
|
/* clang-format off */
|
|
static uint32_t s_fspi_lut[4 * (FSPI_SEQ_INVALID + 1)] = {
|
|
/* Multi-byte write sequence, 1st is RADDR to avoid internal confusion */
|
|
[4 * FSPI_SEQ_WR_IDX + 0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 8U, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0U),
|
|
/* Single-byte write sequence, use RADDR to avoid internal confusion */
|
|
[4 * FSPI_SEQ_W1_IDX + 0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 8U, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0U),
|
|
/* Multi-byte read sequence */
|
|
[4 * FSPI_SEQ_RD_IDX + 0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0U, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0U),
|
|
/* Register read sequence, the first byte is register address, the length can be modified by changing op0. */
|
|
[4 * FSPI_SEQ_R_REG_IDX + 0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 8U, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0U),
|
|
};
|
|
/* clang-format on */
|
|
|
|
status_t fspi_init(void) {
|
|
status_t ret = kStatus_Success;
|
|
flexspi_config_t fspi_cfg;
|
|
|
|
FLEXSPI_GetDefaultConfig(&fspi_cfg);
|
|
|
|
FLEXSPI_Init(FSPI_BASE, &fspi_cfg);
|
|
|
|
flexspi_device_config_t fspi_dev_cfg = {
|
|
.flexspiRootClk = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot),
|
|
.flashSize = 1 * 1024 * 1024, /* Don't care */
|
|
.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,
|
|
.CSInterval = 2,
|
|
.CSHoldTime = 3,
|
|
.CSSetupTime = 3,
|
|
.dataValidTime = 2,
|
|
.columnspace = 0,
|
|
.enableWordAddress = false,
|
|
.AWRSeqIndex = FSPI_SEQ_INVALID,
|
|
.AWRSeqNumber = 1,
|
|
.ARDSeqIndex = FSPI_SEQ_INVALID,
|
|
.ARDSeqNumber = 1,
|
|
.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,
|
|
.AHBWriteWaitInterval = 0,
|
|
.enableWriteMask = false,
|
|
};
|
|
|
|
FLEXSPI_SetFlashConfig(FSPI_BASE, &fspi_dev_cfg, FSPI_PORT);
|
|
FLEXSPI_UpdateLUT(FSPI_BASE, 0, s_fspi_lut, 4 * (FSPI_SEQ_INVALID + 1));
|
|
|
|
FLEXSPI_SoftwareReset(FSPI_BASE);
|
|
|
|
return ret;
|
|
}
|
|
|
|
status_t fspi_write(uint8_t *data, uint32_t len) {
|
|
flexspi_transfer_t ip_xfer = {
|
|
.port = FSPI_PORT,
|
|
.deviceAddress = data[0],
|
|
.cmdType = kFLEXSPI_Write,
|
|
.seqIndex = FSPI_SEQ_W1_IDX,
|
|
.SeqNumber = 1U,
|
|
.data = (uint32_t *)data,
|
|
.dataSize = 1,
|
|
};
|
|
|
|
if (len > 1) {
|
|
ip_xfer.seqIndex = FSPI_SEQ_WR_IDX;
|
|
ip_xfer.dataSize = len - 1;
|
|
ip_xfer.data = (uint32_t *)(&data[1]);
|
|
}
|
|
|
|
return FLEXSPI_TransferBlocking(FSPI_BASE, &ip_xfer);
|
|
}
|
|
|
|
status_t fspi_read(uint8_t *data, uint32_t len) {
|
|
flexspi_transfer_t ip_xfer = {
|
|
.port = FSPI_PORT,
|
|
.deviceAddress = 0UL,
|
|
.cmdType = kFLEXSPI_Read,
|
|
.seqIndex = FSPI_SEQ_RD_IDX,
|
|
.SeqNumber = 1U,
|
|
.data = (uint32_t *)data,
|
|
.dataSize = len,
|
|
};
|
|
|
|
return FLEXSPI_TransferBlocking(FSPI_BASE, &ip_xfer);
|
|
}
|
|
|
|
status_t fspi_read_registers(uint8_t addr, uint8_t *data, uint32_t len) {
|
|
flexspi_transfer_t ip_xfer = {
|
|
.port = FSPI_PORT,
|
|
.deviceAddress = addr,
|
|
.cmdType = kFLEXSPI_Read,
|
|
.seqIndex = FSPI_SEQ_R_REG_IDX,
|
|
.SeqNumber = 1U,
|
|
.data = (uint32_t *)data,
|
|
.dataSize = len,
|
|
};
|
|
|
|
return FLEXSPI_TransferBlocking(FSPI_BASE, &ip_xfer);
|
|
}
|
|
|
|
status_t fspi_write_registers(uint8_t addr, uint8_t *data, uint32_t len) {
|
|
flexspi_transfer_t ip_xfer = {
|
|
.port = FSPI_PORT,
|
|
.deviceAddress = addr,
|
|
.cmdType = kFLEXSPI_Write,
|
|
.seqIndex = FSPI_SEQ_WR_IDX,
|
|
.SeqNumber = 1U,
|
|
.data = (uint32_t *)data,
|
|
.dataSize = len,
|
|
};
|
|
|
|
return FLEXSPI_TransferBlocking(FSPI_BASE, &ip_xfer);
|
|
} |