Files
2025-12-15 16:07:49 +08:00

619 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**********************************************************************
45DB011 Max 20MHz clock, using 8 MHz click, 512 Pages (264 Bytes/Page)
MX25l8006EM2C 台湾旺宏 8M字节 86/66/33MHZ 页256Byte 最大5ms 10万次擦写
**********************************************************************/
//#include "stm32f10x_lib.h"
#include "SPI_Flash.h"
#include "Flash.h"
#define FLASH_PAGE_SIZE 256
__no_init unsigned char spi_buf[FLASH_PAGE_SIZE]@0x20004000;//[256];;
//__no_init SPI_InitTypeDef SPI_InitStructure@0x20006000;//[256];;
//__no_init GPIO_InitTypeDef GPIO_InitStructure@0x20006100;//[256];;
//unsigned int Update_Len;
//unsigned int page;
//unsigned char* Update_Ptr;
//unsigned char Update_Data;
unsigned char m_ucFlashBuf[FLASH_PAGE_SIZE]={0};
//unsigned char m_ucFlashBuf[FLASH_PAGE_SIZE];
extern u16 FlashDataRAM[];
//0XC2 0X13
void FlashReadID(u8 *Data)@ "FLASHCODE"
{
u8 i;
Select_Flash();
SPI_Flash_SendByte(0x90);
SPI_Flash_SendByte(0x00);
SPI_Flash_SendByte(0x00);
SPI_Flash_SendByte(0x00);
for(i = 0; i < 2; i++)
{
Data[i] = SPI_Flash_ReadByte();
}
NotSelect_Flash();
}
/*******************************************************************************
* Function Name : SPI_FLASH_Init
* Description : Initializes the peripherals used by the SPI FLASH driver.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SPI_Flash_Init(void)@ "FLASHCODE"
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable SPI1 GPIOA and GPIOB clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
/* Configure SPI1 pins: NSS, SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Deselect the FLASH: Chip Select high */
NotSelect_Flash();
/* SPI1 configuration */
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; //divied by 2, SPI clock is (32M/2)/2=8MHz
//SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 4m
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
/* Enable SPI1 */
SPI_Cmd(SPI2, ENABLE);
//flash_write_enable();
}
/*******************************************************************************
* Function Name : SPI_FLASH_ReadByte
* Description : Reads a byte from the SPI Flash.
* This function must be used only if the Start_Read_Sequence
* function has been previously called.
* Input : None
* Output : None
* Return : Byte Read from the SPI Flash.
*******************************************************************************/
//u8 SPI_Flash_ReadByte(void)@ "FLASHCODE"
//{
// return (SPI_Flash_SendByte(Dummy_Byte));
//}
unsigned char SPI_Flash_ReadByte(void)@ "FLASHCODE"
{
return (SPI_Flash_SendByte(Dummy_Byte));
}
/*******************************************************************************
* Function Name : SPI_FLASH_SendByte
* Description : Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
*******************************************************************************/
u8 SPI_Flash_SendByte(u8 byte)@ "FLASHCODE"
{
/* Loop while DR register in not emplty */
while(SPI_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_SendData(SPI2, byte);
/* Wait to receive a byte */
while(SPI_GetFlagStatus(SPI2, SPI_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_ReceiveData(SPI2);
}
/*
void FlashPageEarse(u16 page)@ "FLASHCODE"
{
FlashWaitBusy();
Select_Flash();
SPI_Flash_SendByte(PAGE_ERASE);
SPI_Flash_SendByte((u8)(page >> 6));
SPI_Flash_SendByte((u8)(page << 2));
SPI_Flash_SendByte(Dummy_Byte);
//|-23-|-22-|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
//|2个无关位|------------12位页地址-------------|----10个无关位-----|
NotSelect_Flash();
}
*/
void Delay_100us_1(void)
{
unsigned int j;
for(j=0; j<424; j++)
{
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
}
}
void FlashPageRead(unsigned int wPage,unsigned char *Update_Ptr)@ "FLASHCODE"
{
unsigned short i=0;
unsigned int uiAddr=0;
//256 8006E --> 4096 page
uiAddr = (unsigned int)(wPage*256);
FlashWaitBusy();
Select_Flash();
SPI_Flash_SendByte(0x03);
SPI_Flash_SendByte( (u8)((uiAddr>>16)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr>>8)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr)&0xFF) );
for (i = 0;i < 256; i++)
{
*Update_Ptr++=SPI_Flash_ReadByte();
}
NotSelect_Flash();
}
void flash_write_enable(void)
{
unsigned char state_reg=0x00;
while((state_reg&0x02) == 0x00)
{
Select_Flash();
SPI_Flash_SendByte(0x06);
NotSelect_Flash();
Delay_100us_1();
Select_Flash();
SPI_Flash_SendByte(FLASH_STATUS);
state_reg=SPI_Flash_ReadByte();
NotSelect_Flash();
if( (state_reg&0x02) == 0x01 )
{
break;
}
Delay_100us_1();
}
}
void FlashWaitBusy(void)@ "FLASHCODE"
{
unsigned char state_reg=0x00;
while( 1 )
{
Select_Flash();
SPI_Flash_SendByte(0x05);
state_reg=SPI_Flash_ReadByte();
NotSelect_Flash();
//ClearWatchdog();
{
//WDI_10;
//IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//IWDG_ReloadCounter();
}
if( (state_reg&0x01) == 0x00)
{
break;
}
}
}
void UClearWatchdog(void)@ "FLASHCODE"
{
unsigned char k;
// P6DIR_bit.P6DIR_1 = 1;
// P6OUT_bit.P6OUT_1 = 1;
WDI_1;
for (k=0;k<200;k++)//0
{
_NOP();
}
WDI_0;
// P6OUT_bit.P6OUT_1 = 0;
// WDTCTL = WDTPW + WDTSSEL + WDTCNTCL; //enable and clear watchdog, 2006-11-21
IWDG_ReloadCounter();
}
//read flash data within page
void D_spiReadFlashPage(unsigned int iadr,unsigned short ilen,unsigned char *pdin_data)//@ "FLASHCODE"
{
unsigned int i,tn;
tn=ilen+(iadr%FLASH_PAGE_SIZE);
FlashPageRead(iadr/FLASH_PAGE_SIZE,&spi_buf[0]);
for(i=(iadr%FLASH_PAGE_SIZE);i<tn;++i)
{
*pdin_data=spi_buf[i];
pdin_data++;
}
}
/**************************************************************************
read flash, not care iit's more than one page size or not, 2010-10-13
***************************************************************************/
void D_spiFlashRead(u32 iaddr,u16 length, u8 *pdin_data)//@ "FLASHCODE"
{
u16 i, page, tn, remain;
page=iaddr/FLASH_PAGE_SIZE;
remain=iaddr%FLASH_PAGE_SIZE;
if (remain!=0)
{
FlashPageRead(iaddr/FLASH_PAGE_SIZE,&spi_buf[0]);
tn=remain+length;
if (tn<FLASH_PAGE_SIZE)
{
for(i=remain;i<tn;++i)
{
*pdin_data=spi_buf[i];
pdin_data++;
}
return; //finished read all data
}
else
{
for(i=remain;i<FLASH_PAGE_SIZE;++i)
{
*pdin_data=spi_buf[i];
pdin_data++;
}
length = length-(FLASH_PAGE_SIZE-remain);
iaddr=iaddr+(FLASH_PAGE_SIZE-remain);
}
}
//keep reading the next page
while (length>FLASH_PAGE_SIZE)
{
FlashPageRead(page,&spi_buf[0]);
for(i=0;i<FLASH_PAGE_SIZE;++i)
{
*pdin_data++=spi_buf[i];
}
length-=FLASH_PAGE_SIZE;
page++;
}
if(0 == length%FLASH_PAGE_SIZE)
{
FlashPageRead(page,&spi_buf[0]);
for(i=0;i<FLASH_PAGE_SIZE;++i)
{
*pdin_data++=spi_buf[i];
}
}
else
{
//read the remained data from the last page
FlashPageRead(page,&spi_buf[0]);
for(i=0;i<(length%FLASH_PAGE_SIZE);++i)
{
*pdin_data++=spi_buf[i];
}
}
}
/////////////////////////////////////////////////////////////////////////////////
//void D_spiWriteIIC(unsigned int iadr, unsigned short nbyte, unsigned char* psrc_data)//@ "FLASHCODE"
void D_spiWriteFlash(unsigned int iadr, unsigned short nbyte, unsigned char* psrc_data)//@ "FLASHCODE"
{
unsigned int i,tn;
tn=nbyte+(iadr%FLASH_PAGE_SIZE);
for(i=(iadr%FLASH_PAGE_SIZE);i<tn;++i)
{
spi_buf[i]=*psrc_data;
psrc_data++;
}
FlashPageWrite(iadr/FLASH_PAGE_SIZE,spi_buf);
}
/****************************************************************************************************
Write flash, don't care length is more than one page or not
****************************************************************************************************/
void D_spiFlashWrite(u32 iadr, u16 length, u8 *psrc_data)//@ "FLASHCODE"
{
u16 i=0,page=0;
page=iadr/FLASH_PAGE_SIZE;
while (length>FLASH_PAGE_SIZE)
{
for(i=0;i<FLASH_PAGE_SIZE;++i)
{
spi_buf[i]=*psrc_data++;
}
FlashPageWrite(page,spi_buf);
length-=FLASH_PAGE_SIZE;
page++;
}
//read the last page of data from flash
flash_page_read(page, spi_buf);
for(i=0;i<length;++i)
{
spi_buf[i]=*psrc_data++;
}
FlashPageWrite(page,spi_buf);
}
void FlashPageWrite(u16 wPage,u8 *Data)//@ "FLASHCODE" //写一整页页范围0-4095
{
unsigned short i=0;
unsigned int uiAddr=0;
unsigned short wSector=0;
unsigned short wStartAddr=0;
unsigned char* m_flash_sector=0;
m_flash_sector=(unsigned char*)FlashDataRAM;
wStartAddr = (wPage%16)*256;
wSector = (unsigned short)(wPage/16);
uiAddr = wSector*4096;
flash_fast_read( uiAddr, 4096 );
flash_sector_erase(uiAddr);
for( i=0; i<256; i++ )
{
m_flash_sector[wStartAddr+i]=Data[i];
}
flash_sector_write(wSector*4096, 4096);
}
//256 8006E --> 4096 page
void flash_page_write(u16 wPage,u8 *Data)
{
unsigned short i=0;
unsigned int uiAddr=0;
uiAddr = (unsigned int)(wPage*256);
FlashWaitBusy();
flash_write_enable();
Select_Flash();
SPI_Flash_SendByte(0x02);
SPI_Flash_SendByte( (u8)((uiAddr>>16)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr>>8)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr)&0xFF) );
for (i = 0;i < 256; i++)
{
SPI_Flash_SendByte(Data[i]);
}
NotSelect_Flash();
}
//256 8006E --> 4096 page
void flash_page_read(unsigned short wPage, unsigned char* pData)
{
unsigned short i=0;
unsigned int uiAddr=0;
uiAddr = (unsigned int)(wPage*256);
FlashWaitBusy();
Select_Flash();
SPI_Flash_SendByte(0x03);
SPI_Flash_SendByte( (u8)((uiAddr>>16)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr>>8)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr)&0xFF) );
for (i = 0;i < 256; i++)
{
pData[i]=SPI_Flash_ReadByte();
}
NotSelect_Flash();
}
void flash_sector_erase(unsigned int uiAddr)
{
FlashWaitBusy();
flash_write_enable();
Select_Flash();
SPI_Flash_SendByte(0x20);
SPI_Flash_SendByte( (u8)((uiAddr>>16)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr>>8)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr)&0xFF) );
NotSelect_Flash();
}
void flash_sector_write(unsigned int uiAddr, unsigned short wLen)
{
unsigned short i=0;
unsigned short wPage=0;
unsigned char* m_flash_sector=0;
m_flash_sector=(unsigned char*)FlashDataRAM;
wPage = (unsigned short)(uiAddr/256);
for( i=0; i<16; i++ )
{
memcpy( &m_ucFlashBuf[0], &m_flash_sector[ 256*i ], 256 );
flash_page_write( wPage, &m_ucFlashBuf[0] );
wPage++;
}
SPI_Flash_SendByte(0x04); //dis write
}
void flash_fast_read( unsigned int uiAddr, unsigned short wLen )
{
unsigned short i=0;
unsigned char* m_flash_sector=0;
m_flash_sector=(unsigned char*)FlashDataRAM;
if(wLen>4096)
{
return;
}
FlashWaitBusy();
Select_Flash();
SPI_Flash_SendByte(0x0B);
SPI_Flash_SendByte( (u8)((uiAddr>>16)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr>>8)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr)&0xFF) );
SPI_Flash_SendByte( 0x00 );
for (i = 0;i < wLen; i++)
{
m_flash_sector[i]=SPI_Flash_ReadByte();
}
NotSelect_Flash();
}
void FlashWaidBusy(void)@ "FLASHCODE"
{
unsigned char state_reg=0x00;
while( 1 )
{
Select_Flash();
SPI_Flash_SendByte(0x05);
state_reg=SPI_Flash_ReadByte();
NotSelect_Flash();
UClearWatchdog();
if( (state_reg&0x01) == 0x00)
{
break;
}
}
}
void Flash_Page_Read(unsigned int wPage,unsigned char *Update_Ptr)@ "FLASHCODE"
{
unsigned short i=0;
unsigned int uiAddr=0;
//256 8006E --> 4096 page
uiAddr = (unsigned int)(wPage*256);
FlashWaidBusy();
Select_Flash();
SPI_Flash_SendByte(0x03);
SPI_Flash_SendByte( (u8)((uiAddr>>16)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr>>8)&0xFF) );
SPI_Flash_SendByte( (u8)((uiAddr)&0xFF) );
for (i = 0;i < 256; i++)
{
*Update_Ptr++=SPI_Flash_ReadByte();
}
NotSelect_Flash();
}
/**
* @brief Write block of data to the SPI FLASH.
* @param WriteAddr: FLASH's internal address to write to.
* @param pBuffer: pointer to the buffer containing the data to be written to the FLASH.
* @param length: number of bytes to write to the FLASH.
* @retval None.
*/
void hal_sFLASH_WriteData(u32 WriteAddr, u8 *pBuffer, u16 length)
{
u16 pageLength = 0;
while (length > 0)
{
if ((WriteAddr & sFLASH_PAGE_MASK) == ((WriteAddr + length) & sFLASH_PAGE_MASK))
{
pageLength = length;
}
else
{
pageLength = ((WriteAddr + sFLASH_PAGE_SIZE) & sFLASH_PAGE_MASK) - WriteAddr;
}
FlashWaitBusy();
flash_write_enable();
Select_Flash();
SPI_Flash_SendByte(0x02);
SPI_Flash_SendByte((u8)((WriteAddr >> 16) & 0xFF));
SPI_Flash_SendByte((u8)((WriteAddr >> 8) & 0xFF));
SPI_Flash_SendByte((u8)((WriteAddr) & 0xFF));
for (u16 i = 0; i < pageLength; i++)
{
SPI_Flash_SendByte(pBuffer[i]);
}
NotSelect_Flash();
WriteAddr += pageLength;
pBuffer += pageLength;
length -= pageLength;
}
}
/**
* @brief Read block of data to the SPI FLASH.
* @param ReadAddr: FLASH's internal address to read from.
* @param pBuffer: pointer to the buffer containing the data to be read from the FLASH.
* @param length: number of bytes to read from the FLASH.
* @retval None.
*/
void hal_sFLASH_ReadData(u32 ReadAddr, u8 *pBuffer, u16 length)
{
FlashWaitBusy();
flash_write_enable();
Select_Flash();
SPI_Flash_SendByte(0x03);
SPI_Flash_SendByte((u8)((ReadAddr >> 16) & 0xFF));
SPI_Flash_SendByte((u8)((ReadAddr >> 8) & 0xFF));
SPI_Flash_SendByte((u8)((ReadAddr) & 0xFF));
for (u16 i = 0; i < length; i++)
{
pBuffer[i] = SPI_Flash_SendByte(Dummy_Byte);
}
NotSelect_Flash();
}