/******************************************************************************* * 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; }