ZNY_Pakistan/Anjiehui7_ZNY/User/spi_Flash.c

540 lines
12 KiB
C
Raw Permalink Normal View History

2025-04-03 15:24:54 +08:00
/*
*********************************************************************************************************
* IAR Development Kits
* on the
*
* M451
*
* Filename : spi_flash.c
* Version : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/
#include "includes.h"
// Ƭѡ
#define SFLASH_CS_LOW() LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_12)
#define SFLASH_CS_HIGH() LL_GPIO_SetOutputPin(GPIOE, LL_GPIO_PIN_12)
// Flash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define SFLASH_OP_WREN 0x06 // Write Enable
#define SFLASH_OP_WRDI 0x04 // Write Disable
#define SFLASH_OP_RDSR 0x05 // Read Status Register
#define SFLASH_OP_WRSR 0x01 // Write Status Register
#define SFLASH_OP_READ 0x03 // Read Memory
#define SFLASH_OP_FSTRD 0x0B // Read Memory at Higher Speed
#define SFLASH_OP_PP 0x02 // Page Program
#define SFLASH_OP_DPD 0xB9 // Deep Power-down Mode
#define SFLASH_OP_RDID 0x9F // JEDEC-ID Read
#define SFLASH_OP_PE 0x81 // Erase 256 Bytes of Memory Array
#define SFLASH_OP_SE 0x20 // Erase 4 KBytes of Memory Array
#define SFLASH_OP_CE 0xC7 // Erase Full Array
#define SFLASH_OP_ULBPR 0x98 // Global Block Protection Unlock
// Flash״̬<D7B4>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>SR)д<><D0B4><EFBFBD><EFBFBD>(WEL)<29><>־λ
#define SFLASH_WEL_Pos 1
#define SFLASH_WEL_Msk (0x01 << SFLASH_WEL_Pos)
// Flash״̬<D7B4>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>SR)Busy<73><79>־λ
#define SFLASH_BUSY_Pos 0
#define SFLASH_BUSY_Msk (0x01 << SFLASH_BUSY_Pos)
// дFlash<73><68><EFBFBD><EFBFBD>
uint8_t SFlash_wtBuf[SFLASH_ERASE_SIZE];
//uint8_t *SFlash_wtBuf; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD>ڴ<EFBFBD>
// <20><>Flashȫ<68>ֻ<EFBFBD><D6BB><EFBFBD>
uint8_t SFlash_rdBuf[SFLASH_ERASE_SIZE];
//uint8_t *SFlash_rdBuf; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD>ڴ<EFBFBD>
void SFlash_Init()
{
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
/**SPI1 GPIO Configuration
PE13 ------> SPI1_SCK
PE14 ------> SPI1_MISO
PE15 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_14|LL_GPIO_PIN_15;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/**/
LL_GPIO_SetOutputPin(GPIOE, LL_GPIO_PIN_12);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_12;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}
void SFlash_Open()
{
LL_SPI_InitTypeDef SPI_InitStruct = {0};
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD>ڴ<EFBFBD>
// SFlash_rdBuf = SRAM_Alloc(SFLASH_ERASE_SIZE);
// SFlash_wtBuf = SRAM_Alloc(SFLASH_ERASE_SIZE);
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
/* SPI1 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 7;
LL_SPI_Init(SPI1, &SPI_InitStruct);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_DisableNSSPulseMgt(SPI1);
LL_SPI_SetRxFIFOThreshold(SPI1, LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_Enable(SPI1);
// <20><><EFBFBD><EFBFBD>ID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
SFlash_ReadID();
}
void SFlash_ReadID()
{
uint8_t i;
__disable_irq();
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDID;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
PRINTF("\r\nFlash ID is: ");
for(i = 0; i < 3; i++)
{
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
PRINTF("%02X ", *(__IO uint8_t *)&SPI1->DR);
}
PRINTF("\r\n");
SFLASH_CS_HIGH();
__enable_irq();
}
uint8_t SFlash_UnlockBPR()
{
__disable_irq();
SFlash_WriteEN();
SFLASH_CS_LOW();
// Write Enabled
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_ULBPR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
__enable_irq();
return 1;
}
uint8_t SFlash_WriteEN()
{
uint8_t SR = 0x00;
SFLASH_CS_LOW();
// Write Enabled
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_WREN;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Read SR
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDSR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
SR = *(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Check WEL
if(SR & SFLASH_WEL_Msk)
return 1;
PRINTF("\r\nWrite enable failed\r\n");
return 0;
}
uint8_t SFlash_WriteDI()
{
uint8_t SR = 0xFF;
SFLASH_CS_LOW();
// Write Enabled
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_WRDI;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Read SR
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDSR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
SR = *(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Check WEL
if(SR & SFLASH_WEL_Msk)
{
PRINTF("\r\nWrite disable failed\r\n");
return 0;
}
return 1;
}
uint32_t SFlash_BufferRead(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
{
uint32_t i;
__disable_irq();
SFLASH_CS_LOW();
// Read
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_READ;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address highest byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 16) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address high byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 8) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address low byte
*(__IO uint8_t *)&SPI1->DR = Addr & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// data
for(i = 0; i < nbytes && Addr + i < SFLASH_SIZE; i++)
{
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
buf[i] = *(__IO uint8_t *)&SPI1->DR;
}
SFLASH_CS_HIGH();
__enable_irq();
return i;
}
void SFlash_PageErase(uint32_t Addr)
{
uint8_t SR = 0xFF;
SFLASH_CS_LOW();
// Sector erase
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_PE;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address highest byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 16) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address high byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 8) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address low byte
*(__IO uint8_t *)&SPI1->DR = Addr & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Read SR
do
{
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDSR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
SR = *(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
} while(SR & SFLASH_BUSY_Msk);
}
void SFlash_SectorErase(uint32_t Addr)
{
uint8_t SR = 0xFF;
SFLASH_CS_LOW();
// Sector erase
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_SE;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address highest byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 16) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address high byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 8) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address low byte
*(__IO uint8_t *)&SPI1->DR = Addr & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Read SR
do
{
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDSR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
SR = *(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
} while(SR & SFLASH_BUSY_Msk);
}
void SFlash_ChipErase()
{
uint8_t SR = 0xFF;
SFLASH_CS_LOW();
// Chip erase
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_CE;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
// Read SR
do
{
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDSR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
SR = *(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
} while(SR & SFLASH_BUSY_Msk);
}
uint16_t SFlash_PageProgram(uint32_t Addr, uint8_t *buf)
{
uint8_t SR = 0xFF;
uint16_t i;
SFLASH_CS_LOW();
// Page grogram
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_PP;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address highest byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 16) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address high byte
*(__IO uint8_t *)&SPI1->DR = (Addr >> 8) & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// address low byte
*(__IO uint8_t *)&SPI1->DR = Addr & 0xFF;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
// data
for(i = 0; i < SFLASH_PAGE_SIZE && Addr + i < SFLASH_SIZE; i++)
{
*(__IO uint8_t *)&SPI1->DR = buf[i];
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
}
SFLASH_CS_HIGH();
// Read SR
do
{
SFLASH_CS_LOW();
*(__IO uint8_t *)&SPI1->DR = SFLASH_OP_RDSR;
while(!(SPI1->SR & SPI_SR_RXNE));
*(__IO uint8_t *)&SPI1->DR;
*(__IO uint8_t *)&SPI1->DR = 0; // <20>ṩCLK
while(!(SPI1->SR & SPI_SR_RXNE));
SR = *(__IO uint8_t *)&SPI1->DR;
SFLASH_CS_HIGH();
} while(SR & SFLASH_BUSY_Msk);
return i;
}
uint16_t SFlash_SectorProgram(uint32_t Addr, uint8_t *buf)
{
uint16_t i = 0;
uint16_t j;
for(j = 0; j < SFLASH_ERASE_SIZE; j += SFLASH_PAGE_SIZE)
{
__disable_irq();
SFlash_WriteEN();
i += SFlash_PageProgram(Addr + j, buf + j);
__enable_irq();
}
return i;
}
uint32_t SFlash_BufferWrite(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
{
uint32_t count, offset;
while(nbytes > 0)
{
// <20><><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3>ƫ<EFBFBD>ƣ<EFBFBD>ֻ<EFBFBD>е<EFBFBD>һҳ<D2BB>п<EFBFBD><D0BF>ܷ<EFBFBD>0<EFBFBD><30>
offset = Addr % SFLASH_ERASE_SIZE;
// <20><><EFBFBD><EFBFBD>һҳ<D2BB><D2B3>д<EFBFBD><D0B4><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
count = SFLASH_ERASE_SIZE - offset;
if(count > nbytes)
count = nbytes;
// ҳ<><D2B3><EFBFBD><EFBFBD>
Addr -= offset;
// <20><><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SFlash_BufferRead(Addr, SFlash_wtBuf, SFLASH_ERASE_SIZE);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>£<EFBFBD><C2A3><EFBFBD><EFBFBD><EFBFBD>д
if(memcmp(SFlash_wtBuf + offset, buf, count) != 0)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ
__disable_irq();
SFlash_WriteEN();
SFlash_PageErase(Addr);
__enable_irq();
// <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD>
memcpy(SFlash_wtBuf + offset, buf, count);
// д<>뱾ҳ<EBB1BE><D2B3><EFBFBD><EFBFBD>
__disable_irq();
SFlash_WriteEN();
SFlash_PageProgram(Addr, SFlash_wtBuf);
__enable_irq();
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һҳ
Addr += SFLASH_ERASE_SIZE;
buf += count;
nbytes -= count;
}
return TRUE;
}
uint32_t SFlash_BufferVerify(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
{
uint32_t data_len;
while(nbytes > 0)
{
if(nbytes > SFLASH_ERASE_SIZE)
data_len = SFLASH_ERASE_SIZE;
else
data_len = nbytes;
SFlash_BufferRead(Addr, SFlash_wtBuf, data_len);
if(memcmp(SFlash_wtBuf, buf, data_len) != 0)
return FALSE;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һҳ
Addr += data_len;
buf += data_len;
nbytes -= data_len;
}
return TRUE;
}
uint16_t do_sflash_crc(unsigned long base_addr, long len)
{
unsigned short crc = 0;
unsigned short data_len;
while(len > 0)
{
if(len > SFLASH_ERASE_SIZE)
data_len = SFLASH_ERASE_SIZE;
else
data_len = len;
SFlash_BufferRead(base_addr, SFlash_rdBuf, data_len);
crc = do_crc_16(crc, SFlash_rdBuf, data_len);
base_addr += data_len;
len -= data_len;
}
return crc;
}