/*******************************************************************************
|
* File Name : SPIFlash.c
|
* Description :
|
* Created on : 2019Äê3ÔÂ11ÈÕ
|
* Author : www.hido-studio.com
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Include Files *
|
*******************************************************************************/
|
#include "SPIFlash.h"
|
|
#include "stm32f1xx_hal.h"
|
#include "GPIO.h"
|
#include "HIDO_CRC32.h"
|
#include "string.h"
|
|
#ifdef _USE_OS_
|
#include "cmsis_os.h"
|
#endif
|
|
/*******************************************************************************
|
* 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;
|
|
#ifdef _USE_OS_
|
osMutexId m_mutexLock;
|
#endif
|
|
} ST_SPIFlashResourse;
|
|
/*******************************************************************************
|
* Local Variable *
|
*******************************************************************************/
|
static ST_SPIFlashResourse l_astSPIFlashResourse[SPI_FLASH_ID_LAST];
|
|
|
/*******************************************************************************
|
* Local Function Declaration *
|
*******************************************************************************/
|
|
/*******************************************************************************
|
* Local Function *
|
*******************************************************************************/
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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
|
};
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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
|
};
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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;
|
}
|
|
//TODO MCU_IWDGFeed();
|
}
|
while ((u8Status & SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_BIT) == SPIFLASH_N25Q_STATUS_REGISTER_IN_PROGRESS_BUSY);
|
|
return i32Result;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Read(E_SPIFlashID _eID, HIDO_UINT8 *_pu8DstBuf, HIDO_UINT32 _u32SrcAddr, HIDO_UINT32 _u32SrcLen)
|
{
|
HIDO_INT32 i = 0;
|
|
#ifdef _USE_OS_
|
osMutexWait(l_astSPIFlashResourse[_eID].m_mutexLock, osWaitForever);
|
#endif
|
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);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Write(E_SPIFlashID _eID, HIDO_UINT32 _u32DstAddr, HIDO_UINT8 *_pu8SrcBuf, HIDO_UINT32 _u32SrcLen)
|
{
|
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);
|
}
|
|
#ifdef _USE_OS_
|
osMutexWait(l_astSPIFlashResourse[_eID].m_mutexLock, osWaitForever);
|
#endif
|
while (_u32SrcLen != 0)
|
{
|
if (SPIFlash_PageProgram(_eID, _u32DstAddr, _pu8SrcBuf, _u32SrcLen, &u32PageProgramLen) != HIDO_OK)
|
{
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_ERR;
|
}
|
|
_u32DstAddr += u32PageProgramLen;
|
_pu8SrcBuf += u32PageProgramLen;
|
_u32SrcLen -= u32PageProgramLen;
|
u32ProgramLen += u32PageProgramLen;
|
}
|
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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;
|
}
|
|
#ifdef _USE_OS_
|
osMutexWait(l_astSPIFlashResourse[_eID].m_mutexLock, osWaitForever);
|
#endif
|
if (0 == _u32EraseAddr && _u32EraseLen >= l_astSPIFlashResourse[_eID].m_u32ChipSize)
|
{
|
SPIFlash_BulkErase(_eID);
|
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
}
|
|
while (u32TempLen < _u32EraseLen)
|
{
|
SPIFlash_SectorErase(_eID, _u32EraseAddr + u32TempLen, _eEraseMode);
|
u32TempLen += l_au32SPIFlashSectorEraseSize[_eEraseMode];
|
}
|
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_ReadJedecID(E_SPIFlashID _eID, HIDO_UINT8 *_pu8IDBuf, HIDO_UINT32 _u32IDBufSize)
|
{
|
HIDO_INT32 i = 0;
|
|
#ifdef _USE_OS_
|
osMutexWait(l_astSPIFlashResourse[_eID].m_mutexLock, osWaitForever);
|
#endif
|
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);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_PowerDown(E_SPIFlashID _eID)
|
{
|
#ifdef _USE_OS_
|
osMutexWait(l_astSPIFlashResourse[_eID].m_mutexLock, osWaitForever);
|
#endif
|
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);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_ReleasePowerDown(E_SPIFlashID _eID)
|
{
|
#ifdef _USE_OS_
|
osMutexWait(l_astSPIFlashResourse[_eID].m_mutexLock, osWaitForever);
|
#endif
|
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);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_OK;
|
|
err_cs_disable:
|
SPIFlash_CSDisable(_eID);
|
#ifdef _USE_OS_
|
osMutexRelease(l_astSPIFlashResourse[_eID].m_mutexLock);
|
#endif
|
return HIDO_ERR;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_CalcCRC32(E_SPIFlashID _eID, HIDO_UINT32 _u32StartAddr, HIDO_UINT32 _u32CalcLen, HIDO_UINT32 *_pu32CRC32)
|
{
|
HIDO_UINT8 au8Buf[512];
|
HIDO_UINT32 u32CRC32 = 0xFFFFFFFF;
|
HIDO_UINT32 u32ReadLen = 0;
|
|
while (_u32CalcLen != 0)
|
{
|
if (_u32CalcLen > sizeof(au8Buf))
|
{
|
u32ReadLen = sizeof(au8Buf);
|
}
|
else
|
{
|
u32ReadLen = _u32CalcLen;
|
}
|
|
if (SPIFlash_Read(_eID, au8Buf, _u32StartAddr, u32ReadLen) != HIDO_OK)
|
{
|
return HIDO_ERR;
|
}
|
|
u32CRC32 = HIDO_CRC32SubCalc(u32CRC32, au8Buf, u32ReadLen);
|
_u32StartAddr += u32ReadLen;
|
_u32CalcLen -= u32ReadLen;
|
}
|
|
if (_pu32CRC32 != HIDO_NULL)
|
{
|
*_pu32CRC32 = u32CRC32 ^ 0xFFFFFFFF;
|
}
|
|
return HIDO_OK;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_VOID SPIFlash_SPIRegister(E_SPIFlashID _eID, E_SPI_ID _eSPI_ID)
|
{
|
l_astSPIFlashResourse[_eID].m_eSPI_ID = _eSPI_ID;
|
}
|
|
/*******************************************************************************
|
* Function Name :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
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 :
|
* Description :
|
* Input :
|
* Output :
|
* Return :
|
* Author : www.hido-studio.com
|
* Modified Date: : 2019Äê3ÔÂ11ÈÕ
|
*******************************************************************************/
|
HIDO_INT32 SPIFlash_Init(E_SPIFlashID _eID)
|
{
|
HIDO_UINT8 au8JedecID[3];
|
|
#ifdef _USE_OS_
|
l_astSPIFlashResourse[_eID].m_mutexLock = osMutexCreate(HIDO_NULL);
|
#endif
|
|
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;
|
}
|