555 lines
19 KiB
C
555 lines
19 KiB
C
/* x25q.c */
|
|
#include "x25q.h"
|
|
#include "stdio.h"
|
|
|
|
static X25Q_DeviceInfo_Type X25Q_DeviceTable[] = X25Q_DEVICE_TABLE; /* record the device information. */
|
|
|
|
static void X25Q_EnableWrite(uint32_t dev_index, bool enable); /* enable Write. */
|
|
static uint32_t X25Q_ReadRegisterValue(uint32_t dev_index, uint32_t reg_index); /* read register value, the index of register x is (x - 1). */
|
|
static void X25Q_WriteRegisterValue(uint32_t dev_index, uint32_t reg_index, uint8_t value); /* write register value, the index of register x is (x - 1). */
|
|
static void X25Q_WaitBusyBlocking(uint32_t dev_index); /* wait for chip idle. */
|
|
static void X25Q_EnableQPI(uint32_t dev_index, bool enable); /* enable QPI mode. */
|
|
static void X25Q_EnableQE(uint32_t dev_index, bool enable); /* enable Quad Mode (IO2 & IO3 are used). */
|
|
|
|
/* init x25q. */
|
|
void X25Q_Init(void)
|
|
{
|
|
X25Q_HAL_Init(); /* init hardware. */
|
|
|
|
/* init chip operation mode. */
|
|
for (uint32_t i = 0; i < sizeof(X25Q_DeviceTable) / sizeof(X25Q_DeviceInfo_Type); i++)
|
|
{
|
|
if (0 == X25Q_DeviceTable[i].MemSize) /* invalid device info. */
|
|
{
|
|
continue;
|
|
}
|
|
X25Q_EnableQPI(i, false); /* close qpi mode, even if it is not enableed. */
|
|
switch (X25Q_DeviceTable[i].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI:
|
|
break; /* do nothing. */
|
|
case X25Q_OperationMode_DSPI:
|
|
break; /* do nothing. */
|
|
case X25Q_OperationMode_QSPI:
|
|
X25Q_EnableQE(i, true);
|
|
break; /* need to enable QE mode. */
|
|
case X25Q_OperationMode_QPI:
|
|
X25Q_EnableQE(i, true); /* need to enable QE mode before enable QPI mode. */
|
|
X25Q_EnableQPI(i, true); /* enable QPI mode. */
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* read manufactor id. */
|
|
uint32_t X25Q_ReadManuId(uint32_t dev_index)
|
|
{
|
|
uint8_t buf[2u] = {0u};
|
|
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode) /* set the bus width. */
|
|
{
|
|
case X25Q_OperationMode_SPI: /* read manu id by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* read manu id by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* read manu id by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* read manu id by qpi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_4b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* invalid operation mode, using spi mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.AddrWordWidth = X25Q_WordWidth_24b; /* after 2 dummy bytes, need to send a 0x00 data, then can recv manu id. */
|
|
xfer.AddrValue = 0xFFFF00; /* use addr phase instead dummy phase. */
|
|
xfer.DummyBytes = 0u;
|
|
xfer.CmdValue = X25Q_Cmd_GetManuId;
|
|
xfer.DataLen = sizeof(buf);
|
|
xfer.DataBuf = buf;
|
|
|
|
X25Q_HAL_Read(&xfer);
|
|
|
|
return (buf[0u] << 8u) | buf[1u]; /* big endian. */
|
|
}
|
|
|
|
/* erase chip data. */
|
|
void X25Q_EraseChip(uint32_t dev_index)
|
|
{
|
|
X25Q_EnableWrite(dev_index, true); /* must enable write before erase chip. */
|
|
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI: /* cmd phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* cmd phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* cmd phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* cmd phase use 4b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* unknow the operation, using SPI mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.CmdValue = X25Q_Cmd_EraseChip;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_None;
|
|
xfer.DummyBytes = 0u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_None;
|
|
xfer.DataLen = 0;
|
|
|
|
X25Q_HAL_Write(&xfer);
|
|
|
|
X25Q_WaitBusyBlocking(dev_index); /* wait for erase chip done. */
|
|
|
|
X25Q_EnableWrite(dev_index, false); /* disable write function. */
|
|
}
|
|
|
|
/* erase sector. */
|
|
void X25Q_EraseSector(uint32_t dev_index, uint32_t addr)
|
|
{
|
|
if (addr > X25Q_DeviceTable[dev_index].MemSize - X25Q_DeviceTable[dev_index].SectorSize)
|
|
{
|
|
return; /* addr overflow. */
|
|
}
|
|
|
|
X25Q_EnableWrite(dev_index, true); /* must enable write before erase sector. */
|
|
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI: /* cmd % addr phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* cmd % addr phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* cmd % addr phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* all phase use 4b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* unknow the operation, using SPI mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.AddrWordWidth = X25Q_WordWidth_24b;
|
|
xfer.CmdValue = X25Q_Cmd_EraseSector;
|
|
xfer.AddrValue = addr;
|
|
xfer.DummyBytes = 0u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_None;
|
|
xfer.DataLen = 0;
|
|
|
|
X25Q_HAL_Write(&xfer);
|
|
|
|
X25Q_WaitBusyBlocking(dev_index); /* wait for erase sector done. */
|
|
|
|
X25Q_EnableWrite(dev_index, false); /* close write. */
|
|
}
|
|
|
|
/* write page. */
|
|
void X25Q_WritePage(uint32_t dev_index, uint32_t addr, uint32_t size, uint8_t * buf)
|
|
{
|
|
if (addr + size > X25Q_DeviceTable[dev_index].MemSize) /* addr overflow. */
|
|
{
|
|
return;
|
|
}
|
|
|
|
X25Q_EnableWrite(dev_index, true); /* must enable write before write page. */
|
|
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI: /* 1b bus in data phase. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_WritePage;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* DSPI use SPI mode to write data. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_WritePage;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* 4b bus in data phase. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_WritePageQuad;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* 4b bus in all phase. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.CmdValue = X25Q_Cmd_WritePage;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_4b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* unknow the operation, using SPI mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_WritePage;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.AddrWordWidth = X25Q_WordWidth_24b;
|
|
xfer.AddrValue = addr;
|
|
xfer.DummyBytes = 0u;
|
|
xfer.DataLen = size;
|
|
xfer.DataBuf = buf;
|
|
|
|
X25Q_HAL_Write(&xfer);
|
|
|
|
X25Q_WaitBusyBlocking(dev_index); /* wait for write page done (chip idle). */
|
|
|
|
X25Q_EnableWrite(dev_index, false); /* close write. */
|
|
}
|
|
|
|
void X25Q_WriteData(uint32_t dev_index, uint32_t addr, uint32_t size, uint8_t * buf)
|
|
{
|
|
if (addr + size > X25Q_DeviceTable[dev_index].MemSize)/* addr overflow. */
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint32_t xfer_count = 0u;
|
|
uint32_t xfer_remain = size;
|
|
uint32_t xfer_size = 0u;
|
|
|
|
/* align write. */
|
|
if (0u != addr % X25Q_DeviceTable[dev_index].PageSize)
|
|
{
|
|
uint32_t xfer_align = X25Q_DeviceTable[dev_index].PageSize - (addr % X25Q_DeviceTable[dev_index].PageSize);
|
|
|
|
xfer_size = (xfer_remain > xfer_align ? xfer_align : xfer_remain);
|
|
|
|
X25Q_WritePage(dev_index, addr + xfer_count, xfer_size, &buf[xfer_count]);
|
|
xfer_remain -= xfer_size;
|
|
xfer_count += xfer_size;
|
|
}
|
|
|
|
/* page write. */
|
|
while(xfer_remain > 0u)
|
|
{
|
|
xfer_size = (xfer_remain > X25Q_DeviceTable[dev_index].PageSize ? X25Q_DeviceTable[dev_index].PageSize : xfer_remain);
|
|
X25Q_WritePage(dev_index, addr + xfer_count, xfer_size, &buf[xfer_count]);
|
|
xfer_remain -= xfer_size;
|
|
xfer_count += xfer_size;
|
|
}
|
|
}
|
|
|
|
/* read data. */
|
|
void X25Q_ReadData(uint32_t dev_index, uint32_t addr, uint32_t size, uint8_t * buf)
|
|
{
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
if (addr + size > X25Q_DeviceTable[dev_index].MemSize)
|
|
{
|
|
return; /* addr overflow. */
|
|
}
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode) /* set the info of xfer. */
|
|
{
|
|
case X25Q_OperationMode_SPI: /* all phase use 1b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_FaseRead;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DummyBytes = 1u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* data phase use 2b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_FaseReadDual;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DummyBytes = 2u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_2b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* data phase use 4b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_FaseReadQuad;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DummyBytes = 4u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* all phase use 4b bus. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.CmdValue = X25Q_Cmd_FaseRead;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_4b;
|
|
xfer.DummyBytes = 1u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* unknow the operation, using SPI mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_FaseRead;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DummyBytes = 1u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.AddrWordWidth = X25Q_WordWidth_24b;
|
|
xfer.AddrValue = addr;
|
|
xfer.DataLen = size;
|
|
xfer.DataBuf = buf;
|
|
X25Q_HAL_Read(&xfer); /* read data. */
|
|
}
|
|
|
|
/* write & erase must enable write function. */
|
|
static void X25Q_EnableWrite(uint32_t dev_index, bool enable)
|
|
{
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI:
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI:
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI:
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QPI:
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default:
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_None; /* no addr phase. */
|
|
xfer.DummyBytes = 0u; /* no dummy phase. */
|
|
xfer.DataBusWidth = X25Q_BusWidth_None; /* no data phase. */
|
|
xfer.DataLen = 0;
|
|
|
|
if (true == enable)
|
|
{
|
|
xfer.CmdValue = X25Q_Cmd_EnableWrite; /* enable write. */
|
|
}
|
|
else
|
|
{
|
|
xfer.CmdValue = X25Q_Cmd_DisableWrite; /* disable write. */
|
|
}
|
|
|
|
X25Q_HAL_Write(&xfer);
|
|
}
|
|
|
|
/* read register value from device register n, n = reg_index + 1. */
|
|
static uint32_t X25Q_ReadRegisterValue(uint32_t dev_index, uint32_t reg_index)
|
|
{
|
|
const X25Q_Cmd_Type cmd[3u] = {X25Q_Cmd_ReadRegister1, X25Q_Cmd_ReadRegister2, X25Q_Cmd_ReadRegister3};
|
|
|
|
X25Q_Xfer_Type xfer;
|
|
uint8_t buf[1u];
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI: /* xfer by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* xfer by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* xfer by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* xfer by qpi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* unknow operation mode, using spi mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.CmdValue = cmd[reg_index];
|
|
xfer.AddrBusWidth = X25Q_BusWidth_None; /* no addr phase. */
|
|
xfer.DummyBytes = 0u; /* no dummy phase. */
|
|
xfer.DataLen = sizeof(buf);
|
|
xfer.DataBuf = buf;
|
|
|
|
X25Q_HAL_Read(&xfer);
|
|
|
|
return buf[0u];
|
|
}
|
|
|
|
/* write register value to device register n, n = reg_index + 1. */
|
|
static void X25Q_WriteRegisterValue(uint32_t dev_index, uint32_t reg_index, uint8_t value)
|
|
{
|
|
const X25Q_Cmd_Type cmd[3u] = {X25Q_Cmd_WriteRegister1, X25Q_Cmd_WriteRegister2, X25Q_Cmd_WriteRegister3};
|
|
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
X25Q_EnableWrite(dev_index, true); /* enable write. */
|
|
|
|
switch (X25Q_DeviceTable[dev_index].OperationMode)
|
|
{
|
|
case X25Q_OperationMode_SPI: /* xfer by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_DSPI: /* xfer by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QSPI: /* xfer by spi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
case X25Q_OperationMode_QPI: /* xfer by qpi. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_4b;
|
|
break;
|
|
default: /* unknow operation mode, using spi mode. */
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
break;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.CmdValue = cmd[reg_index];
|
|
xfer.AddrBusWidth = X25Q_BusWidth_None; /* no addr phase. */
|
|
xfer.DummyBytes = 0u; /* no dummy phase. */
|
|
xfer.DataLen = 1u;
|
|
xfer.DataBuf = &value;
|
|
|
|
X25Q_HAL_Write(&xfer);
|
|
|
|
|
|
X25Q_EnableWrite(dev_index, false); /* disable write. */
|
|
}
|
|
|
|
/* wait write or erase done. */
|
|
static void X25Q_WaitBusyBlocking(uint32_t dev_index)
|
|
{
|
|
while(0u != (X25Q_ReadRegisterValue(dev_index, 0u) & X25Q_REGISTER1_BUSY_MASK) )
|
|
{
|
|
}
|
|
}
|
|
|
|
/* enable qpi mode, all phase bus is 4b. */
|
|
static void X25Q_EnableQPI(uint32_t dev_index, bool enable)
|
|
{
|
|
X25Q_Xfer_Type xfer;
|
|
|
|
if (true == enable) /* xspi -> qpi */
|
|
{
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_EnableQpi;
|
|
}
|
|
else /* qpi -> xspi. */
|
|
{
|
|
xfer.CmdBusWidth = X25Q_BusWidth_4b;
|
|
xfer.CmdValue = X25Q_Cmd_DisableQpi;
|
|
}
|
|
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_None; /* no addr. */
|
|
xfer.DummyBytes = 0u; /* no dummy. */
|
|
xfer.DataBusWidth = X25Q_BusWidth_None; /* no data. */
|
|
xfer.DataLen = 0u;
|
|
|
|
/* write. */
|
|
X25Q_HAL_Write(&xfer);
|
|
}
|
|
|
|
/* enable QE mode, WP & HOLD be used for IO2 & IO3. */
|
|
static void X25Q_EnableQE(uint32_t dev_index, bool enable)
|
|
{
|
|
X25Q_Xfer_Type xfer;
|
|
uint8_t buf[1];
|
|
|
|
/* enable write by spi mode. */
|
|
xfer.DeviceIndex = dev_index;
|
|
xfer.CmdBusWidth = X25Q_BusWidth_1b;
|
|
xfer.CmdValue = X25Q_Cmd_EnableWrite;
|
|
xfer.AddrBusWidth = X25Q_BusWidth_None;
|
|
xfer.DummyBytes = 0u;
|
|
xfer.DataBusWidth = X25Q_BusWidth_None;
|
|
xfer.DataLen = 0u;
|
|
X25Q_HAL_Write(&xfer);
|
|
|
|
/* read register 2 value by spi mode. */
|
|
xfer.CmdValue = X25Q_Cmd_ReadRegister2;
|
|
xfer.DataBusWidth = X25Q_BusWidth_1b;
|
|
xfer.DataLen = sizeof(buf);
|
|
xfer.DataBuf = buf;
|
|
X25Q_HAL_Read(&xfer);
|
|
|
|
/* set value. */
|
|
if (true == enable)
|
|
{
|
|
buf[0] |= X25Q_REGISTER2_QE_MASK; /* set QE bit. */
|
|
}
|
|
else
|
|
{
|
|
buf[0] &= ~X25Q_REGISTER2_QE_MASK; /* clear QE bit. */
|
|
}
|
|
|
|
/* write register 2 by spi mode. */
|
|
xfer.CmdValue = X25Q_Cmd_WriteRegister2;
|
|
X25Q_HAL_Write(&xfer);
|
|
|
|
/* wait for write done. */
|
|
xfer.CmdValue = X25Q_Cmd_ReadRegister1;
|
|
buf[0] = X25Q_REGISTER1_BUSY_MASK;
|
|
while(0 != (buf[0] & X25Q_REGISTER1_BUSY_MASK) )
|
|
{
|
|
X25Q_HAL_Read(&xfer);
|
|
}
|
|
|
|
/* disable write. */
|
|
xfer.CmdValue = X25Q_Cmd_DisableWrite;
|
|
xfer.DataBusWidth = X25Q_BusWidth_None;
|
|
xfer.DataLen = 0u;
|
|
X25Q_HAL_Write(&xfer);
|
|
}
|
|
|
|
/* EOF. */
|