mirror of
https://gitee.com/lzc56/MiaoUI.git
synced 2025-08-13 12:42:53 +00:00
536 lines
14 KiB
C
536 lines
14 KiB
C
![]() |
/**
|
|||
|
******************************************************************************
|
|||
|
* @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**********************/
|