/*******************************************************************************
|
* File Name : SPIFlash.c
|
* Description :
|
* Created on : 2021Äê5ÔÂ07ÈÕ
|
* Author : www.hido-studio.com
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Include Files *
|
*******************************************************************************/
|
#include "SPIFlash.h"
|
|
#include "stm32l0xx_hal.h"
|
#include "GPIO.h"
|
#include "HIDO_CRC32.h"
|
#include "string.h"
|
|
/*******************************************************************************
|
* Macro *
|
*******************************************************************************/
|
#define SPIFLASH_N25Q_SECTOR_COUNT 64
|
#define SPIFLASH_N25Q_SUBSECTOR_COUNT 1024
|
#define SPIFLASH_N25Q_PAGE_COUNT 16384
|
|
#define SPIFLASH_N25Q_2MB_CAPACITY_VALUE 0x15
|
#define SPIFLASH_N25Q_4MB_CAPACITY_VALUE 0x16
|
#define SPIFLASH_N25Q_8MB_CAPACITY_VALUE 0x17
|
#define SPIFLASH_N25Q_16MB_CAPACITY_VALUE 0x18
|
|
#define SPIFLASH_N25Q_4MB_SIZE 0x400000
|
#define SPIFLASH_N25Q_8MB_SIZE 0x800000
|
#define SPIFLASH_N25Q_16MB_SIZE 0x1000000
|
|
#define SPIFLASH_N25Q_SECTOR_SIZE 0x10000
|
#define SPIFLASH_N25Q_HALF_SECTOR_SIZE 0x8000
|
#define SPIFLASH_N25Q_SUBSECTOR_SIZE 0x1000
|
#define SPIFLASH_N25Q_PAGE_SIZE 0x100
|
#define SPIFLASH_N25Q_CHIP_LEFT_SIZE(id, addr) (l_astSPIFlashResourse[id].m_u32ChipSize - (addr & (l_astSPIFlashResourse[id].m_u32ChipSize - 1)))
|
#define SPIFLASH_N25Q_PAGE_LEFT_SIZE(addr) (SPIFLASH_N25Q_PAGE_SIZE - (addr & (SPIFLASH_N25Q_PAGE_SIZE - 1)))
|
#define SPIFLASH_N25Q_SUBSECTOR_LEFT_SIZE(addr) (SPIFLASH_N25Q_SUBSECTOR_SIZE - (addr & (SPIFLASH_N25Q_SUBSECTOR_SIZE - 1)))
|
#define SPIFLASH_N25Q_SECTOR_LEFT_SIZE(addr) (SPIFLASH_N25Q_SECTOR_SIZE - (addr & (SPIFLASH_N25Q_SECTOR_SIZE - 1)))
|
|
#define SPIFLASH_N25Q_SECTOR_ADDR(addr) ((addr) & (~(SPIFLASH_N25Q_SECTOR_SIZE - 1)))
|
#define SPIFLASH_N25Q_SUBSECTOR_ADDR(addr) ((addr) & (~(SPIFLASH_N25Q_SUBSECTOR_SIZE - 1)))
|
|
#define SPIFLASH_N25Q_CMD_READ_ID 0x9E
|
#define SPIFLASH_N25Q_CMD_READ 0x03
|
#define SPIFLASH_N25Q_CMD_FAST_READ 0x0B
|
#define SPIFLASH_N25Q_CMD_DUAL_OUTPUT_FAST_READ 0x3B
|
|
#define SPIFLASH_N25Q_CMD_WRITE_ENABLE 0x06
|
#define SPIFLASH_N25Q_CMD_WRITE_DISABLE 0x04
|
#define SPIFLASH_N25Q_CMD_READ_STATUS_REGISTER 0x05
|
#define SPIFLASH_N25Q_CMD_SUBSECTOR_ERASE 0x20
|
#define SPIFLASH_N25Q_CMD_HALF_SECTOR_ERASE 0x52
|
#define SPIFLASH_N25Q_CMD_SECTOR_ERASE 0xD8
|
#define SPIFLASH_N25Q_CMD_BULK_ERASE 0xC7
|
#define SPIFLASH_N25Q_CMD_PAGE_PROGRAM 0x02
|
#define SPIFLASH_N25Q_CMD_JEDEC_ID 0x9F
|
|
#define SPIFLASH_N25Q_CMD_POWER_DOWN 0xB9
|
#define SPIFLASH_N25Q_CMD_RELEASE_POWER_DOWN 0xAB
|
|
#define SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_BIT 0x01
|
#define SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_READY 0
|
#define SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_BUSY 1
|
|
#define SPIFLASH_DUMMY_BYTE 0xFF
|
|
/*******************************************************************************
|
* Type Definition *
|
*******************************************************************************/
|
typedef struct
|
{
|
E_SPI_ID m_eSPI_ID;
|
ST_GPIO m_stPin[SPI_FLASH_PIN_LAST];
|
HIDO_UINT32 m_u32ChipSize;
|
} ST_SPIFlashResourse;
|
|
/*******************************************************************************
|
* Local Variable *
|
*******************************************************************************/
|
static ST_SPIFlashResourse l_astSPIFlashResourse[SPI_FLASH_ID_LAST];
|
|
/* ²»Í¬²Á³ýÃüÁî¶ÔÓ¦µÄ¿é´óС */
|
const static HIDO_UINT32 l_au32SPIFlashSectorEraseSize[SPI_FLASH_SECTOR_ERASE_MODE_LAST] =
|
{
|
SPIFLASH_N25Q_SUBSECTOR_SIZE, SPIFLASH_N25Q_HALF_SECTOR_SIZE, SPIFLASH_N25Q_SECTOR_SIZE
|
};
|
|
/* ²»Í¬²Á³ýÃüÁî¶ÔÓ¦µÄÃüÁî */
|
const static HIDO_UINT8 l_au8SPIFlashSectorEraseCmd[SPI_FLASH_SECTOR_ERASE_MODE_LAST] =
|
{
|
SPIFLASH_N25Q_CMD_SUBSECTOR_ERASE, SPIFLASH_N25Q_CMD_HALF_SECTOR_ERASE, SPIFLASH_N25Q_CMD_SECTOR_ERASE
|
};
|
|
/*******************************************************************************
|
* Local Function Declaration *
|
*******************************************************************************/
|
void IWDG_Refresh(void);
|
|
/*******************************************************************************
|
* Local Function *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_CSEnable
|
* Description : SPI CSʹÄÜ
|
* Input : _eID SPIFlash ID
|
* Output : None
|
* Return : None
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static void SPIFlash_CSEnable(E_SPIFlashID _eID)
|
{
|
HAL_GPIO_WritePin(l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_CS].m_pstGPIOx, l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_CS].m_u16GPIOPin, GPIO_PIN_RESET);
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_CSDisable
|
* Description : SPI CSʧÄÜ
|
* Input : _eID SPIFlash ID
|
* Output : None
|
* Return : None
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static void SPIFlash_CSDisable(E_SPIFlashID _eID)
|
{
|
HAL_GPIO_WritePin(l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_CS].m_pstGPIOx, l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_CS].m_u16GPIOPin, GPIO_PIN_SET);
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_SendByte
|
* Description : SPIдһ¸ö×Ö½Ú
|
* Input : _eID SPIFlash ID
|
* : _u8SendByte дÈëµÄ×Ö½Ú
|
* Output : _pu8RecvByte ¶ÁÈ¡µÄ×Ö½Ú
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_SendByte(E_SPIFlashID _eID, HIDO_UINT8 _u8SendByte, HIDO_UINT8 *_pu8RecvByte)
|
{
|
return SPI_ReadWrite(l_astSPIFlashResourse[_eID].m_eSPI_ID, _pu8RecvByte, &_u8SendByte, 1);
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_WriteEnable
|
* Description : SPIFlashÖ´ÐÐдʹÄÜÃüÁî
|
* Input : _eID SPIFlash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_WriteEnable(E_SPIFlashID _eID)
|
{
|
HIDO_INT32 i32Result = HIDO_OK;
|
|
SPIFlash_CSEnable(_eID);
|
i32Result = SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_WRITE_ENABLE, HIDO_NULL);
|
SPIFlash_CSDisable(_eID);
|
|
return i32Result;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_WriteDisable
|
* Description : SPIFlashÖ´ÐÐдʧÄÜÃüÁî
|
* Input : _eID SPIFlash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_WriteDisable(E_SPIFlashID _eID)
|
{
|
HIDO_INT32 i32Result = HIDO_OK;
|
|
SPIFlash_CSEnable(_eID);
|
i32Result = SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_WRITE_DISABLE, HIDO_NULL);
|
SPIFlash_CSDisable(_eID);
|
|
return i32Result;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_ReadStatusRegister
|
* Description : SPIFlashÖ´ÐжÁȡ״̬ÃüÁî
|
* Input : _eID SPIFlash ID
|
* Output : _pu8Status SPIFlash״̬
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_ReadStatusRegister(E_SPIFlashID _eID, HIDO_UINT8 *_pu8Status)
|
{
|
HIDO_INT32 i32Result = HIDO_OK;
|
|
SPIFlash_CSEnable(_eID);
|
i32Result = SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_READ_STATUS_REGISTER, HIDO_NULL);
|
if(HIDO_OK == i32Result)
|
{
|
i32Result = SPIFlash_SendByte(_eID, SPIFLASH_DUMMY_BYTE, _pu8Status);
|
}
|
SPIFlash_CSDisable(_eID);
|
|
return i32Result;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_WaitBusy
|
* Description : SPIFlashæµÈ´ý
|
* Input : _eID SPIFlash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_WaitBusy(E_SPIFlashID _eID)
|
{
|
HIDO_INT32 i32Result = HIDO_OK;
|
HIDO_UINT8 u8Status = 0;
|
|
do
|
{
|
i32Result = SPIFlash_ReadStatusRegister(_eID, &u8Status);
|
if (i32Result != HIDO_OK)
|
{
|
break;
|
}
|
|
//IWDG_Refresh();
|
}
|
while ((u8Status & SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_BIT) == SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_BUSY);
|
|
return i32Result;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_PageProgram
|
* Description : SPIFlashÒ³±à³Ì
|
* Input : _eID SPIFlash ID
|
* : _u32DstAddr Ä¿µÄµØÖ·
|
* : _pu8SrcBuf Ô´µØÖ·
|
* : _u32SrcLen Ô´³¤¶È
|
* Output : _pu32ProgramLen ±à³ÌµÄ³¤¶È
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_PageProgram(E_SPIFlashID _eID, HIDO_UINT32 _u32DstAddr, HIDO_UINT8 *_pu8SrcBuf, HIDO_UINT32 _u32SrcLen, HIDO_UINT32 *_pu32ProgramLen)
|
{
|
HIDO_UINT32 i = 0;
|
HIDO_UINT32 u32ProgramLen = 0;
|
|
u32ProgramLen = SPIFLASH_N25Q_PAGE_LEFT_SIZE(_u32DstAddr);
|
if (u32ProgramLen > _u32SrcLen)
|
{
|
u32ProgramLen = _u32SrcLen;
|
}
|
|
if(SPIFlash_WaitBusy(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
if(SPIFlash_WriteEnable(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_PAGE_PROGRAM, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) ((_u32DstAddr) >> 16), HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) ((_u32DstAddr) >> 8), HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) _u32DstAddr, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
for (i = 0; i < u32ProgramLen; i++)
|
{
|
if (SPIFlash_SendByte(_eID, _pu8SrcBuf[i], HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
}
|
|
SPIFlash_CSDisable(_eID);
|
|
if(SPIFlash_WriteDisable(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
if(SPIFlash_WaitBusy(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
if(_pu32ProgramLen != HIDO_NULL)
|
{
|
*_pu32ProgramLen = u32ProgramLen;
|
}
|
|
return HIDO_OK;
|
|
err:
|
return HIDO_ERR;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_SectorErase
|
* Description : SPIFlash¿é²Á³ý
|
* Input : _eID SPIFlash ID
|
* : _u32SectorAddr ¿éµØÖ·
|
* : _eEraseMode ²Á³ýģʽ
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
static HIDO_INT32 SPIFlash_SectorErase(E_SPIFlashID _eID, HIDO_UINT32 _u32SectorAddr, E_SPIFlashSectorEraseMode _eEraseMode)
|
{
|
_u32SectorAddr = _u32SectorAddr & (~(l_au32SPIFlashSectorEraseSize[_eEraseMode] - 1));
|
|
if(SPIFlash_WriteEnable(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, l_au8SPIFlashSectorEraseCmd[_eEraseMode], HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) ((_u32SectorAddr) >> 16), HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) ((_u32SectorAddr) >> 8), HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) _u32SectorAddr, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
SPIFlash_CSDisable(_eID);
|
|
if(SPIFlash_WriteDisable(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
if(SPIFlash_WaitBusy(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
return HIDO_OK;
|
|
err:
|
return HIDO_ERR;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Global Function *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_BulkErase
|
* Description : SPIFlashÕûƬ²Á³ý
|
* Input : _eID SPIFlash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_BulkErase(E_SPIFlashID _eID)
|
{
|
if(SPIFlash_WriteEnable(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_BULK_ERASE, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
SPIFlash_CSDisable(_eID);
|
|
if(SPIFlash_WriteDisable(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
if(SPIFlash_WaitBusy(_eID) != HIDO_OK)
|
{
|
goto err;
|
}
|
|
return HIDO_OK;
|
|
err:
|
return HIDO_ERR;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_Read
|
* Description : SPIFlash¶ÁÈ¡Êý¾Ý
|
* Input : _eID SPIFlash ID
|
* : _u32SrcAddr Ô´µØÖ·
|
* : _u32SrcLen Ô´³¤¶È
|
* Output : _pu8DstBuf Ä¿µÄµØÖ·
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Read(E_SPIFlashID _eID, HIDO_UINT8 *_pu8DstBuf, HIDO_UINT32 _u32SrcAddr, HIDO_UINT32 _u32SrcLen)
|
{
|
|
HIDO_INT32 i = 0;
|
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_READ, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) ((_u32SrcAddr) >> 16), HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) ((_u32SrcAddr) >> 8), HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
if (SPIFlash_SendByte(_eID, (HIDO_UINT8) _u32SrcAddr, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
for (i = 0; i < _u32SrcLen; i++)
|
{
|
if (SPIFlash_SendByte(_eID, SPIFLASH_DUMMY_BYTE, &_pu8DstBuf[i]) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
}
|
|
SPIFlash_CSDisable(_eID);
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_Write
|
* Description : SPIFlashдÊý¾Ý
|
* Input : _eID SPIFlash ID
|
* : _u32DstAddr Ä¿µÄµØÖ·
|
* : _pu8SrcBuf Ô´µØÖ·
|
* : _u32SrcLen Ô´Êý¾Ý³¤¶È
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Write(E_SPIFlashID _eID, HIDO_UINT32 _u32DstAddr, HIDO_UINT8 *_pu8SrcBuf, HIDO_UINT32 _u32SrcLen)
|
{
|
// return HIDO_OK;
|
HIDO_UINT32 u32ProgramLen = 0;
|
HIDO_UINT32 u32PageProgramLen = 0;
|
|
if (_u32DstAddr >= l_astSPIFlashResourse[_eID].m_u32ChipSize || HIDO_NULL == _pu8SrcBuf || 0 == _u32SrcLen)
|
{
|
return HIDO_ERR;
|
}
|
|
if (_u32SrcLen > SPIFLASH_N25Q_CHIP_LEFT_SIZE(_eID, _u32DstAddr))
|
{
|
_u32SrcLen = SPIFLASH_N25Q_CHIP_LEFT_SIZE(_eID, _u32DstAddr);
|
}
|
|
while (_u32SrcLen != 0)
|
{
|
if (SPIFlash_PageProgram(_eID, _u32DstAddr, _pu8SrcBuf, _u32SrcLen, &u32PageProgramLen) != HIDO_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
_u32DstAddr += u32PageProgramLen;
|
_pu8SrcBuf += u32PageProgramLen;
|
_u32SrcLen -= u32PageProgramLen;
|
u32ProgramLen += u32PageProgramLen;
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_Erase
|
* Description : SPIFlash ²Á³ý
|
* Input : _eID SPIFlash ID
|
* : _u32EraseAddr ²Á³ýµØÖ·
|
* : _u32EraseLen ²Á³ý³¤¶È
|
* : _eEraseMode ²Á³ýģʽ
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Erase(E_SPIFlashID _eID, HIDO_UINT32 _u32EraseAddr, HIDO_UINT32 _u32EraseLen, E_SPIFlashSectorEraseMode _eEraseMode)
|
{
|
HIDO_UINT32 u32TempLen = 0;
|
|
if (_u32EraseAddr >= l_astSPIFlashResourse[_eID].m_u32ChipSize || 0 == _u32EraseLen || (_u32EraseAddr + _u32EraseLen) > l_astSPIFlashResourse[_eID].m_u32ChipSize
|
|| ((_u32EraseAddr & (l_au32SPIFlashSectorEraseSize[_eEraseMode] - 1)) != 0) || _eEraseMode >= SPI_FLASH_SECTOR_ERASE_MODE_LAST)
|
{
|
return HIDO_ERR;
|
}
|
|
if (0 == _u32EraseAddr && _u32EraseLen >= l_astSPIFlashResourse[_eID].m_u32ChipSize)
|
{
|
SPIFlash_BulkErase(_eID);
|
|
return HIDO_OK;
|
}
|
|
while (u32TempLen < _u32EraseLen)
|
{
|
SPIFlash_SectorErase(_eID, _u32EraseAddr + u32TempLen, _eEraseMode);
|
u32TempLen += l_au32SPIFlashSectorEraseSize[_eEraseMode];
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_ReadJedecID
|
* Description : SPIFlash¶ÁȡоƬID
|
* Input : _eID Flash ID
|
* : _u32IDBufSize ID»º´æ´óС
|
* Output : _pu8IDBuf ID»º´æ
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_ReadJedecID(E_SPIFlashID _eID, HIDO_UINT8 *_pu8IDBuf, HIDO_UINT32 _u32IDBufSize)
|
{
|
HIDO_INT32 i = 0;
|
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_JEDEC_ID, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
for (i = 0; i < _u32IDBufSize; i++)
|
{
|
if (SPIFlash_SendByte(_eID, SPIFLASH_DUMMY_BYTE, &_pu8IDBuf[i]) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
}
|
|
SPIFlash_CSDisable(_eID);
|
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_PowerDown
|
* Description : SPIFlash Ö´ÐÐPOWER_DOWN
|
* Input : _eID Flash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_PowerDown(E_SPIFlashID _eID)
|
{
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_POWER_DOWN, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
SPIFlash_CSDisable(_eID);
|
HAL_Delay(1);
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_ReleasePowerDown
|
* Description : SPIFlash Ö´ÐÐRELEASE_POWER_DOWN
|
* Input : _eID Flash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_ReleasePowerDown(E_SPIFlashID _eID)
|
{
|
SPIFlash_CSEnable(_eID);
|
|
if (SPIFlash_SendByte(_eID, SPIFLASH_N25Q_CMD_RELEASE_POWER_DOWN, HIDO_NULL) != HIDO_OK)
|
{
|
goto err_cs_disable;
|
}
|
|
SPIFlash_CSDisable(_eID);
|
HAL_Delay(1);
|
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_SPIRegister
|
* Description : SPIFlash SPI×¢²á
|
* Input : _eID Flash ID
|
* : _eSPI_ID SPI ID
|
* Output : None
|
* Return : None
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_VOID SPIFlash_SPIRegister(E_SPIFlashID _eID, E_SPI_ID _eSPI_ID)
|
{
|
l_astSPIFlashResourse[_eID].m_eSPI_ID = _eSPI_ID;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_PinRegister
|
* Description : SPIFlash¹Ü½Å×¢²á
|
* Input : _eID Flash ID
|
* : _ePin ¹Ü½ÅÃû³Æ
|
* : _pGPIO GPIOx
|
* : _u16Pin GPIO_PIN_x
|
* Output : None
|
* Return : None
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_VOID SPIFlash_PinRegister(E_SPIFlashID _eID, E_SPIFlashPin _ePin, HIDO_VOID *_pGPIO, HIDO_UINT16 _u16Pin)
|
{
|
l_astSPIFlashResourse[_eID].m_stPin[_ePin].m_pstGPIOx = (GPIO_TypeDef *)_pGPIO;
|
l_astSPIFlashResourse[_eID].m_stPin[_ePin].m_u16GPIOPin = _u16Pin;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_UnInit
|
* Description : SPIFlash·´³õʼ»¯
|
* Input : _eID Flash ID
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_UnInit(E_SPIFlashID _eID)
|
{
|
HAL_GPIO_DeInit(l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_CS].m_pstGPIOx, l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_CS].m_u16GPIOPin);
|
HAL_GPIO_DeInit(l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_MISO].m_pstGPIOx, l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_MISO].m_u16GPIOPin);
|
HAL_GPIO_DeInit(l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_MOSI].m_pstGPIOx, l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_MOSI].m_u16GPIOPin);
|
HAL_GPIO_DeInit(l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_SCK].m_pstGPIOx, l_astSPIFlashResourse[_eID].m_stPin[SPI_FLASH_PIN_SCK].m_u16GPIOPin);
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name : SPIFlash_Init
|
* Description : SPIFlash³õʼ»¯
|
* Input : None
|
* Output : None
|
* Return : HIDO_OK ³É¹¦, HIDO_ERR ʧ°Ü
|
* Author : www.hido-studio.com
|
* Modified Date: : 2021Äê5ÔÂ07ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Init(E_SPIFlashID _eID)
|
{
|
HIDO_UINT8 au8JedecID[3];
|
|
if (SPIFlash_ReadJedecID(_eID, au8JedecID, 3) != HIDO_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
if (0xFF == au8JedecID[0] && 0xFF == au8JedecID[1] && 0xFF == au8JedecID[2])
|
{
|
if (SPIFlash_ReadJedecID(_eID, au8JedecID, 3) != HIDO_OK)
|
{
|
return HIDO_ERR;
|
}
|
}
|
|
switch (au8JedecID[2])
|
{
|
case SPIFLASH_N25Q_2MB_CAPACITY_VALUE:
|
{
|
l_astSPIFlashResourse[_eID].m_u32ChipSize = SPIFLASH_N25Q_4MB_SIZE;
|
break;
|
}
|
case SPIFLASH_N25Q_4MB_CAPACITY_VALUE:
|
{
|
l_astSPIFlashResourse[_eID].m_u32ChipSize = SPIFLASH_N25Q_4MB_SIZE;
|
break;
|
}
|
case SPIFLASH_N25Q_8MB_CAPACITY_VALUE:
|
{
|
l_astSPIFlashResourse[_eID].m_u32ChipSize = SPIFLASH_N25Q_8MB_SIZE;
|
break;
|
}
|
case SPIFLASH_N25Q_16MB_CAPACITY_VALUE:
|
{
|
l_astSPIFlashResourse[_eID].m_u32ChipSize = SPIFLASH_N25Q_16MB_SIZE;
|
break;
|
}
|
default:
|
{
|
l_astSPIFlashResourse[_eID].m_u32ChipSize = SPIFLASH_N25Q_4MB_SIZE;
|
break;
|
}
|
}
|
|
return HIDO_OK;
|
}
|