MiaoUI/examples/STM32F103C8T6/USER/HAL/HAL_Flash.c

536 lines
14 KiB
C
Raw Normal View History

/**
******************************************************************************
* @file bsp_xxx.c
* @author STMicroelectronics
* @version V1.0
* @date 2013-xx-xx
* @brief spi flash Ұ<EFBFBD><EFBFBD><EFBFBD>ײ<EFBFBD>Ӧ<EFBFBD>ú<EFBFBD><EFBFBD><EFBFBD>bsp
******************************************************************************
*/
#include "HAL_Flash.h"
static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT;
static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);
/**
* @brief SPI_FLASH<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param <EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD>
*/
void SPI_FLASH_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* ʹ<><CAB9>SPIʱ<49><CAB1> */
FLASH_SPI_APBxClock_FUN ( FLASH_SPI_CLK, ENABLE );
/* ʹ<><CAB9>SPI<50><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ʱ<EFBFBD><CAB1> */
FLASH_SPI_CS_APBxClock_FUN ( FLASH_SPI_CS_CLK|FLASH_SPI_SCK_CLK|
FLASH_SPI_MISO_CLK|FLASH_SPI_MOSI_CLK, ENABLE );
/* <20><><EFBFBD><EFBFBD>SPI<50><49> CS<43><53><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD>ͨIO<49><4F><EFBFBD><EFBFBD> */
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(FLASH_SPI_CS_PORT, &GPIO_InitStructure);
/* <20><><EFBFBD><EFBFBD>SPI<50><49> SCK<43><4B><EFBFBD><EFBFBD>*/
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(FLASH_SPI_SCK_PORT, &GPIO_InitStructure);
/* <20><><EFBFBD><EFBFBD>SPI<50><49> MISO<53><4F><EFBFBD><EFBFBD>*/
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN;
GPIO_Init(FLASH_SPI_MISO_PORT, &GPIO_InitStructure);
/* <20><><EFBFBD><EFBFBD>SPI<50><49> MOSI<53><49><EFBFBD><EFBFBD>*/
GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN;
GPIO_Init(FLASH_SPI_MOSI_PORT, &GPIO_InitStructure);
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS<43><53><EFBFBD>Ÿߵ<C5B8>ƽ*/
SPI_FLASH_CS_HIGH();
/* SPI ģʽ<C4A3><CABD><EFBFBD><EFBFBD> */
// FLASHоƬ ֧<><D6A7>SPIģʽ0<CABD><30>ģʽ3<CABD><33><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD>CPOL CPHA
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(FLASH_SPIx , &SPI_InitStructure);
/* ʹ<><CAB9> SPI */
SPI_Cmd(FLASH_SPIx , ENABLE);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>FLASH<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param SectorAddr<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
* @retval <EFBFBD><EFBFBD>
*/
void SPI_FLASH_SectorErase(u32 SectorAddr)
{
/* <20><><EFBFBD><EFBFBD>FLASHдʹ<D0B4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
SPI_FLASH_WriteEnable();
SPI_FLASH_WaitForWriteEnd();
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/* ѡ<><D1A1>FLASH: CS<43>͵<EFBFBD>ƽ */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>*/
SPI_FLASH_SendByte(W25X_SectorErase);
/*<2A><><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ĸ<EFBFBD>λ*/
SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
/* <20><><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>λ */
SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
/* <20><><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ĵ<EFBFBD>λ */
SPI_FLASH_SendByte(SectorAddr & 0xFF);
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS <20>ߵ<EFBFBD>ƽ */
SPI_FLASH_CS_HIGH();
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>FLASH<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param <EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD>
*/
void SPI_FLASH_BulkErase(void)
{
/* <20><><EFBFBD><EFBFBD>FLASHдʹ<D0B4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
SPI_FLASH_WriteEnable();
/* <20><><EFBFBD><EFBFBD> Erase */
/* ѡ<><D1A1>FLASH: CS<43>͵<EFBFBD>ƽ */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>*/
SPI_FLASH_SendByte(W25X_ChipErase);
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS <20>ߵ<EFBFBD>ƽ */
SPI_FLASH_CS_HIGH();
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief <EFBFBD><EFBFBD>FLASH<EFBFBD><EFBFBD>ҳд<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>Ҫ<EFBFBD>Ȳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param pBuffer<EFBFBD><EFBFBD>Ҫд<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ָ<EFBFBD><EFBFBD>
* @param WriteAddr<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
* @param NumByteToWrite<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD>SPI_FLASH_PerWritePageSize
* @retval <EFBFBD><EFBFBD>
*/
void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
/* <20><><EFBFBD><EFBFBD>FLASHдʹ<D0B4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
SPI_FLASH_WriteEnable();
/* ѡ<><D1A1>FLASH: CS<43>͵<EFBFBD>ƽ */
SPI_FLASH_CS_LOW();
/* дҳдָ<D0B4><D6B8>*/
SPI_FLASH_SendByte(W25X_PageProgram);
/*<2A><><EFBFBD><EFBFBD>д<EFBFBD><D0B4>ַ<EFBFBD>ĸ<EFBFBD>λ*/
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/*<2A><><EFBFBD><EFBFBD>д<EFBFBD><D0B4>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>λ*/
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/*<2A><><EFBFBD><EFBFBD>д<EFBFBD><D0B4>ַ<EFBFBD>ĵ<EFBFBD>λ*/
SPI_FLASH_SendByte(WriteAddr & 0xFF);
if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
{
NumByteToWrite = SPI_FLASH_PerWritePageSize;
FLASH_ERROR("SPI_FLASH_PageWrite too large!");
}
/* д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
while (NumByteToWrite--)
{
/* <20><><EFBFBD>͵<EFBFBD>ǰҪд<D2AA><D0B4><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD> */
SPI_FLASH_SendByte(*pBuffer);
/* ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD> */
pBuffer++;
}
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS <20>ߵ<EFBFBD>ƽ */
SPI_FLASH_CS_HIGH();
/* <20>ȴ<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief <EFBFBD><EFBFBD>FLASHд<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ñ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD>Ҫ<EFBFBD>Ȳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param pBuffer<EFBFBD><EFBFBD>Ҫд<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ָ<EFBFBD><EFBFBD>
* @param WriteAddr<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
* @param NumByteToWrite<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD>
*/
void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
/*mod<6F><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0A3AC>writeAddr<64><72>SPI_FLASH_PageSize<7A><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>AddrֵΪ0*/
Addr = WriteAddr % SPI_FLASH_PageSize;
/*<2A><>count<6E><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>պÿ<D5BA><C3BF>Զ<EFBFBD><D4B6>뵽ҳ<EBB5BD><D2B3>ַ*/
count = SPI_FLASH_PageSize - Addr;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫд<D2AA><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ*/
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
/*mod<6F><64><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><E0B2BB>һҳ<D2BB><D2B3><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>*/
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
/* Addr=0,<2C><>WriteAddr <20>պð<D5BA>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD> aligned */
if (Addr == 0)
{
/* NumByteToWrite < SPI_FLASH_PageSize */
if (NumOfPage == 0)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
else /* NumByteToWrite > SPI_FLASH_PageSize */
{
/*<2A>Ȱ<EFBFBD><C8B0><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3>д<EFBFBD><D0B4>*/
while (NumOfPage--)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
/*<2A><><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>һҳ<D2BB><D2B3><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
/* <20><><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7> SPI_FLASH_PageSize <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
else
{
/* NumByteToWrite < SPI_FLASH_PageSize */
if (NumOfPage == 0)
{
/*<2A><>ǰҳʣ<D2B3><CAA3><EFBFBD><EFBFBD>count<6E><74>λ<EFBFBD>ñ<EFBFBD>NumOfSingleС<65><D0A1>һҳд<D2B3><D0B4><EFBFBD><EFBFBD>*/
if (NumOfSingle > count)
{
temp = NumOfSingle - count;
/*<2A><>д<EFBFBD><D0B4><EFBFBD><EFBFBD>ǰҳ*/
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
/*<2A><>дʣ<D0B4><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
}
else /*<2A><>ǰҳʣ<D2B3><CAA3><EFBFBD><EFBFBD>count<6E><74>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>д<EFBFBD><D0B4>NumOfSingle<6C><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
}
else /* NumByteToWrite > SPI_FLASH_PageSize */
{
/*<2A><>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>count<6E>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
/* <20><>д<EFBFBD><D0B4>count<6E><74><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Ҫд<D2AA>ĵ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD> */
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
WriteAddr += count;
pBuffer += count;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3>д<EFBFBD><D0B4>*/
while (NumOfPage--)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
/*<2A><><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>һҳ<D2BB><D2B3><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/
if (NumOfSingle != 0)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
/**
* @brief <EFBFBD><EFBFBD>ȡFLASH<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param pBuffer<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ָ<EFBFBD><EFBFBD>
* @param ReadAddr<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ַ
* @param NumByteToRead<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD>
*/
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
/* ѡ<><D1A1>FLASH: CS<43>͵<EFBFBD>ƽ */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD> <20><> ָ<><D6B8> */
SPI_FLASH_SendByte(W25X_ReadData);
/* <20><><EFBFBD><EFBFBD> <20><> <20><>ַ<EFBFBD><D6B7>λ */
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
/* <20><><EFBFBD><EFBFBD> <20><> <20><>ַ<EFBFBD><D6B7>λ */
SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
/* <20><><EFBFBD><EFBFBD> <20><> <20><>ַ<EFBFBD><D6B7>λ */
SPI_FLASH_SendByte(ReadAddr & 0xFF);
/* <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> */
while (NumByteToRead--) /* while there is data to be read */
{
/* <20><>ȡһ<C8A1><D2BB><EFBFBD>ֽ<EFBFBD>*/
*pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
/* ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽڻ<D6BD><DABB><EFBFBD><EFBFBD><EFBFBD> */
pBuffer++;
}
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS <20>ߵ<EFBFBD>ƽ */
SPI_FLASH_CS_HIGH();
}
/**
* @brief <EFBFBD><EFBFBD>ȡFLASH ID
* @param <EFBFBD><EFBFBD>
* @retval FLASH ID
*/
u32 SPI_FLASH_ReadID(void)
{
u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/* <20><>ʼͨѶ<CDA8><D1B6>CS<43>͵<EFBFBD>ƽ */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD>JEDECָ<43><EFBFBD><EEA3AC>ȡID */
SPI_FLASH_SendByte(W25X_JedecDeviceID);
/* <20><>ȡһ<C8A1><D2BB><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD> */
Temp0 = SPI_FLASH_SendByte(Dummy_Byte);
/* <20><>ȡһ<C8A1><D2BB><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD> */
Temp1 = SPI_FLASH_SendByte(Dummy_Byte);
/* <20><>ȡһ<C8A1><D2BB><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD> */
Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
/* ֹͣͨѶ<CDA8><D1B6>CS<43>ߵ<EFBFBD>ƽ */
SPI_FLASH_CS_HIGH();
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>ֵ*/
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
/**
* @brief <EFBFBD><EFBFBD>ȡFLASH Device ID
* @param <EFBFBD><EFBFBD>
* @retval FLASH Device ID
*/
u32 SPI_FLASH_ReadDeviceID(void)
{
u32 Temp = 0;
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS_LOW();
/* Send "RDID " instruction */
SPI_FLASH_SendByte(W25X_DeviceID);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
/* Read a byte from the FLASH */
Temp = SPI_FLASH_SendByte(Dummy_Byte);
/* Deselect the FLASH: Chip Select high */
SPI_FLASH_CS_HIGH();
return Temp;
}
/*******************************************************************************
* Function Name : SPI_FLASH_StartReadSequence
* Description : Initiates a read data byte (READ) sequence from the Flash.
* This is done by driving the /CS line low to select the device,
* then the READ instruction is transmitted followed by 3 bytes
* address. This function exit and keep the /CS line low, so the
* Flash still being selected. With this technique the whole
* content of the Flash is read with a single READ instruction.
* Input : - ReadAddr : FLASH's internal address to read from.
* Output : None
* Return : None
*******************************************************************************/
void SPI_FLASH_StartReadSequence(u32 ReadAddr)
{
/* Select the FLASH: Chip Select low */
SPI_FLASH_CS_LOW();
/* Send "Read from Memory " instruction */
SPI_FLASH_SendByte(W25X_ReadData);
/* Send the 24-bit address of the address to read from -----------------------*/
/* Send ReadAddr high nibble address byte */
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
/* Send ReadAddr medium nibble address byte */
SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
/* Send ReadAddr low nibble address byte */
SPI_FLASH_SendByte(ReadAddr & 0xFF);
}
/**
* @brief ʹ<EFBFBD><EFBFBD>SPI<EFBFBD><EFBFBD>ȡһ<EFBFBD><EFBFBD><EFBFBD>ֽڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param <EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
u8 SPI_FLASH_ReadByte(void)
{
return (SPI_FLASH_SendByte(Dummy_Byte));
}
/**
* @brief ʹ<EFBFBD><EFBFBD>SPI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ֽڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param byte<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
u8 SPI_FLASH_SendByte(u8 byte)
{
SPITimeout = SPIT_FLAG_TIMEOUT;
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD>TXE<58>¼<EFBFBD> */
while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(0);
}
/* д<><D0B4><EFBFBD><EFBFBD><EFBFBD>ݼĴ<DDBC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫд<D2AA><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> */
SPI_I2S_SendData(FLASH_SPIx , byte);
SPITimeout = SPIT_FLAG_TIMEOUT;
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿգ<C7BF>RXNE<4E>¼<EFBFBD> */
while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_RXNE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(1);
}
/* <20><>ȡ<EFBFBD><C8A1><EFBFBD>ݼĴ<DDBC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
return SPI_I2S_ReceiveData(FLASH_SPIx );
}
/**
* @brief ʹ<EFBFBD><EFBFBD>SPI<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param byte<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
u16 SPI_FLASH_SendHalfWord(u16 HalfWord)
{
SPITimeout = SPIT_FLAG_TIMEOUT;
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD>TXE<58>¼<EFBFBD> */
while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_TXE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(2);
}
/* д<><D0B4><EFBFBD><EFBFBD><EFBFBD>ݼĴ<DDBC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫд<D2AA><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> */
SPI_I2S_SendData(FLASH_SPIx , HalfWord);
SPITimeout = SPIT_FLAG_TIMEOUT;
/* <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿգ<C7BF>RXNE<4E>¼<EFBFBD> */
while (SPI_I2S_GetFlagStatus(FLASH_SPIx , SPI_I2S_FLAG_RXNE) == RESET)
{
if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(3);
}
/* <20><>ȡ<EFBFBD><C8A1><EFBFBD>ݼĴ<DDBC><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
return SPI_I2S_ReceiveData(FLASH_SPIx );
}
/**
* @brief <EFBFBD><EFBFBD>FLASH<EFBFBD><EFBFBD><EFBFBD><EFBFBD> дʹ<EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param none
* @retval none
*/
void SPI_FLASH_WriteEnable(void)
{
/* ͨѶ<CDA8><D1B6>ʼ<EFBFBD><CABC>CS<43><53> */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD>дʹ<D0B4><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
SPI_FLASH_SendByte(W25X_WriteEnable);
/*ͨѶ<CDA8><D1B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CS<43><53> */
SPI_FLASH_CS_HIGH();
}
/* WIP(busy)<29><>־<EFBFBD><D6BE>FLASH<53>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4> */
#define WIP_Flag 0x01
/**
* @brief <EFBFBD>ȴ<EFBFBD>WIP(BUSY)<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>FLASH<EFBFBD>ڲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param none
* @retval none
*/
void SPI_FLASH_WaitForWriteEnd(void)
{
u8 FLASH_Status = 0;
/* ѡ<><D1A1> FLASH: CS <20><> */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD> <20><>״̬<D7B4>Ĵ<EFBFBD><C4B4><EFBFBD> <20><><EFBFBD><EFBFBD> */
SPI_FLASH_SendByte(W25X_ReadStatusReg);
/* <20><>FLASHæµ<C3A6><C2B5><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD> */
do
{
/* <20><>ȡFLASHоƬ<D0BE><C6AC>״̬<D7B4>Ĵ<EFBFBD><C4B4><EFBFBD> */
FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);
}
while ((FLASH_Status & WIP_Flag) == SET); /* <20><><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>־ */
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS <20><> */
SPI_FLASH_CS_HIGH();
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
void SPI_Flash_PowerDown(void)
{
/* ͨѶ<CDA8><D1B6>ʼ<EFBFBD><CABC>CS<43><53> */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> */
SPI_FLASH_SendByte(W25X_PowerDown);
/*ͨѶ<CDA8><D1B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CS<43><53> */
SPI_FLASH_CS_HIGH();
}
//<2F><><EFBFBD><EFBFBD>
void SPI_Flash_WAKEUP(void)
{
/*ѡ<><D1A1> FLASH: CS <20><> */
SPI_FLASH_CS_LOW();
/* <20><><EFBFBD><EFBFBD> <20>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD> */
SPI_FLASH_SendByte(W25X_ReleasePowerDown);
/* ֹͣ<CDA3>ź<EFBFBD> FLASH: CS <20><> */
SPI_FLASH_CS_HIGH();
}
/**
* @brief <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>ص<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param None.
* @retval None.
*/
static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
/* <20>ȴ<EFBFBD><C8B4><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ */
FLASH_ERROR("SPI <20>ȴ<EFBFBD><C8B4><EFBFBD>ʱ!errorCode = %d",errorCode);
return 0;
}
/*********************************************END OF FILE**********************/