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