MindSDK_MM32F5270/driver_examples/qspi/qspi_x25q_basic/x25q_port.c
Yilin Sun 3977144e90
Initial MM32F527x commit.
Signed-off-by: Yilin Sun <imi415@imi.moe>
2023-03-27 21:54:40 +08:00

173 lines
5.9 KiB
C

/* x25q_port.c */
#include "x25q.h"
#include "board_init.h"
/* index table be used to X25Q_BusWidth_Type translate to QSPI_BusWidth_Type. */
const static QSPI_BusWidth_Type X25Q_BUSWIDTH[5] = {QSPI_BusWidth_None, QSPI_BusWidth_1b, QSPI_BusWidth_2b, QSPI_BusWidth_4b};
/* index table be used to X25Q_WordWidth_Type translate to QSPI_WordWidth_Type. */
const static QSPI_WordWidth_Type X25Q_WORDWIDTH[4] = {QSPI_WordWidth_8b, QSPI_WordWidth_16b, QSPI_WordWidth_24b, QSPI_WordWidth_32b};
static void X25Q_QSPI_EnableDirectRead(void); /* enable qspi direct read. */
static void X25Q_QSPI_Init(void); /* init qspi module. */
static void X25Q_QSPI_TranslateXfer(QSPI_IndirectXferConf_Type * xfer_conf, X25Q_Xfer_Type * x25q_xfer); /* translate X25Q_Xfer_Type to QSPI_IndirectXferConf_Type. */
static void X25Q_QSPI_Read(X25Q_Xfer_Type * xfer); /* QSPI read. */
static void X25Q_QSPI_Write(X25Q_Xfer_Type * xfer); /* QSPI write. */
/* init spi module. */
void X25Q_HAL_Init(void)
{
X25Q_QSPI_Init();
X25Q_QSPI_EnableDirectRead(); /* enable direct read mode. */
}
/* read from spi module. */
void X25Q_HAL_Read(X25Q_Xfer_Type * xfer)
{
switch (xfer->DeviceIndex)
{
case X25Q_Device_W25Q64:
X25Q_QSPI_Read(xfer);
break;
default: /* invalid device index. */
break;
}
}
/* write to spi module. */
void X25Q_HAL_Write(X25Q_Xfer_Type * xfer)
{
switch (xfer->DeviceIndex)
{
case X25Q_Device_W25Q64:
X25Q_QSPI_Write(xfer);
break;
default: /* invalid device index. */
break;
}
}
/* init qspi module. */
static void X25Q_QSPI_Init(void)
{
QSPI_Init_Type qspi_init;
qspi_init.SckDiv = BOARD_QSPI_SCKDIV;
qspi_init.CsHighLevelCycles = BOARD_QSPI_CS_HIGH_CYCLE;
qspi_init.SpiMode = QSPI_SpiMode_3; /* suggest using SPI Mode 3. */
qspi_init.RxSampleDelay = BOARD_QSPI_RX_SAMPLE_DELAY;
QSPI_Init(BOARD_QSPI_PORT, &qspi_init);
}
static void X25Q_QSPI_EnableDirectRead(void)
{
/* enable QSPI direct read. */
QSPI_DirectXferConf_Type direct_conf;
direct_conf.CmdBusWidth = BOARD_QSPI_DIRECT_CMD_BUSWIDTH; /* fast read quad, cmd phase bus is 1b. */
direct_conf.CmdValue = BOARD_QSPI_DIRECT_CMD_VALUE; /* instruction. */
direct_conf.AddrBusWidth = BOARD_QSPI_DIRECT_ADR_BUSWIDTH; /* fast read quad, addr phase bus is 1b. */
direct_conf.AddrWordWidth = BOARD_QSPI_DIRECT_ADR_WORDWIDTH; /* 24 bit addr. */
direct_conf.AltBusWidth = QSPI_BusWidth_None; /* no alt phase. */
direct_conf.DummyCycles = BOARD_QSPI_DIRECT_DMY_CYCLES; /* wait 8 dummy cycles. */
direct_conf.DataBusWidth = BOARD_QSPI_DIRECT_DAT_BUSWIDTH; /* fast read quad, data phase bus is 4b. */
QSPI_EnableDirectRead(BOARD_QSPI_PORT, &direct_conf);
}
/* QSPI read. */
static void X25Q_QSPI_Read(X25Q_Xfer_Type * xfer)
{
QSPI_IndirectXferConf_Type xfer_conf;
/* translate xfer content to xfer_conf. */
X25Q_QSPI_TranslateXfer(&xfer_conf, xfer);
/* prepare to read data. */
QSPI_SetIndirectReadConf(BOARD_QSPI_PORT, &xfer_conf);
uint32_t dummy_remain = xfer->DummyBytes;
uint32_t data_count = 0u;
/* read data & dummy bytes. */
while( (QSPI_STATUS_XFER_DONE | QSPI_STATUS_FIFO_EMPTY) != (QSPI_GetStatus(BOARD_QSPI_PORT) & (QSPI_STATUS_XFER_DONE | QSPI_STATUS_FIFO_EMPTY) ) )
{
if ( 0u == (QSPI_GetStatus(BOARD_QSPI_PORT) & QSPI_STATUS_FIFO_EMPTY) )
{
if (dummy_remain > 0u)
{
QSPI_GetIndirectData(BOARD_QSPI_PORT); /* skip dummy byte. */
dummy_remain--;
}
else
{
xfer->DataBuf[data_count++] = QSPI_GetIndirectData(BOARD_QSPI_PORT); /* recv data. */
}
}
}
/* clear xfer done status. */
QSPI_ClearStatus(BOARD_QSPI_PORT, QSPI_STATUS_XFER_DONE);
}
/* QSPI write. */
static void X25Q_QSPI_Write(X25Q_Xfer_Type * xfer)
{
QSPI_IndirectXferConf_Type xfer_conf;
/* translate xfer content to xfer_conf. */
X25Q_QSPI_TranslateXfer(&xfer_conf, xfer);
/* prepare to write data. */
QSPI_SetIndirectWriteConf(BOARD_QSPI_PORT, &xfer_conf);
uint32_t dummy_remain = xfer->DummyBytes;
uint32_t data_count = 0u;
/* write data & dummy bytes. */
while( QSPI_STATUS_XFER_DONE != (QSPI_GetStatus(BOARD_QSPI_PORT) & QSPI_STATUS_XFER_DONE) )
{
if ( 0u == (QSPI_GetStatus(BOARD_QSPI_PORT) & QSPI_STATUS_FIFO_FULL) )
{
if (dummy_remain > 0u)
{
QSPI_PutIndirectData(BOARD_QSPI_PORT, 0xFF); /* skip dummy byte. */
dummy_remain--;
}
else if (data_count < xfer->DataLen)
{
QSPI_PutIndirectData(BOARD_QSPI_PORT, xfer->DataBuf[data_count]); /* put data. */
data_count++;
}
}
}
/* clear xfer done status. */
QSPI_ClearStatus(BOARD_QSPI_PORT, QSPI_STATUS_XFER_DONE);
}
/* translate X25Q_Xfer_Type to QSPI_IndirectXferConf_Type. */
static void X25Q_QSPI_TranslateXfer(QSPI_IndirectXferConf_Type * xfer_conf, X25Q_Xfer_Type * x25q_xfer)
{
/* cmd phase. */
xfer_conf->CmdBusWidth = X25Q_BUSWIDTH[x25q_xfer->CmdBusWidth];
xfer_conf->CmdValue = x25q_xfer->CmdValue;
/* addr phase. */
xfer_conf->AddrBusWidth = X25Q_BUSWIDTH[x25q_xfer->AddrBusWidth];
xfer_conf->AddrWordWidth = X25Q_WORDWIDTH[x25q_xfer->AddrWordWidth];
xfer_conf->AddrValue = x25q_xfer->AddrValue;
/* no alt phase. */
xfer_conf->AltBusWidth = QSPI_BusWidth_None;
/* replace dummy phase by ignoring data. */
xfer_conf->DummyCycles = 0u;
/* data phase, including dummy bytes. */
xfer_conf->DataBusWidth = X25Q_BUSWIDTH[x25q_xfer->DataBusWidth];
xfer_conf->DataWordWidth = QSPI_WordWidth_8b;
xfer_conf->DataLen = x25q_xfer->DataLen + x25q_xfer->DummyBytes;
}
/* EOF. */