对于小白的我来说,当时写这个真的是一头雾水。擦除的跨页处理就很恶心。
你想删除一段,这时就还得考虑把这一段额,说不清楚,画个图吧
当时因为这块,抓耳挠腮了很久,为什么网上的驱动都没有考虑这些呢?
gd25q64.h
#ifndef __GD25Q64_H | |
#define __GD25Q64_H | |
#include "gd32f30x.h" | |
//******************************** 引脚初始化 *************************************************// | |
#define gd25q64RCU_SPIx RCU_SPI0 | |
#define gd25q64RCU_GPIOx RCU_GPIOA | |
#define gd25q64GPIOx GPIOA | |
#define gd25q64GPIO_PIN_x GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 | |
#define gd25q64SPI_CS_PIN_x GPIO_PIN_4 | |
//******************************** 引脚初始化 *************************************************// | |
//**********************************************************************************************// | |
//******************************** 数组的长度 *************************************************// | |
#define gd25q64DataLen 4096 | |
//******************************** 数组的长度 *************************************************// | |
//**********************************************************************************************// | |
//********************************GD25 存储芯片的指令 ************************************// | |
#define GD25Q64_WriteEnable 0x06 | |
#define GD25Q64_WriteDisable 0x04 | |
#define GD25Q64_ReadStatusRegister1 0x05 //S7-S0 | |
#define GD25Q64_ReadStatusRegister2 0x35 //S15-S8 | |
#define GD25Q64_ReadStatusRegister3 0x15 //S23-S16 | |
#define GD25Q64_WriteStatusRegister1 0x01 | |
#define GD25Q64_WriteStatusRegister2 0x31 | |
#define GD25Q64_WriteStatusRegister3 0x11 | |
#define GD25Q64_ReadData 0x03 | |
#define GD25Q64_FastRead 0x0B | |
#define GD25Q64_PageProgram 0x02 | |
#define GD25Q64_QuadPageProgram 0x32 | |
#define GD25Q64_SectorErase 0x20 | |
#define GD25Q64_BlockErase32 0x52 | |
#define GD25Q64_BlockErase64 0xD8 | |
#define GD25Q64_ChipErase 0xC7 | |
#define GD25Q64_ReadIdentification 0x9F | |
#define GD25Q64_DeepPowerDown 0xB9 | |
#define GD25Q64_ManufacturerDeviceID 0x90 | |
#define GD25Q64_ReleaseFromDeepPowerDown 0xAB | |
#define GD25Q64_ReadIdentification 0x9F | |
//********************************GD25 存储芯片的指令 ************************************// | |
//**********************************************************************************************// | |
//********************************GD25 存储芯片的典型速度 ******************************// | |
//Program/Erase Speed | |
#define PageProgramTime 0.6 //ms | |
#define SectorEraseTime 50 | |
#define BlockEraseTime 200 | |
#define ChipEraseTime 25000 | |
//********************************GD25 存储芯片的典型速度 ******************************// | |
//**********************************************************************************************// | |
//********************************GD25 存储芯片的片区大小 ******************************// | |
//Flexible Architecture 1M=1024K 1K=1024Byte 1Byte=8bit | |
#define GD25Q64_Size (8*1024*1024) | |
#define GD25Q64_PageSize 256 //Byte | |
#define GD25Q64_SectorSize (4*1024) //Byte | |
#define GD25Q64_BlockSize (32*1024) //Byte | |
//********************************GD25 存储芯片的片区大小 ******************************// | |
// 我自己当时写远程升级时的一些位置定义 | |
#define GD25Q64_ADDRESS_DEVINFO ((uint32_t)0x00) | |
#define GD25Q64_ADDRESS_TASK ((uint32_t)0x1000) | |
#define GD25Q64_ADDRESS_GLOBALTASK ((uint32_t)0x41000) | |
#define GD25Q64_ADDRESS_BOOTLOADER_INFO ((uint32_t)0x81000) | |
#define GD25Q64_ADDRESS_BOOTLOADER_APP1 ((uint32_t)0x82000) | |
#define GD25Q64_ADDRESS_BOOTLOADER_BACKUP ((uint32_t)0xA2000) | |
//******************************** 片选引脚的宏定义 ******************************// | |
#define GD25Q64_CS_LOW() {gpio_bit_write(GPIOA, GPIO_PIN_4,RESET);} | |
#define GD25Q64_CS_HIGH() {gpio_bit_write(GPIOA, GPIO_PIN_4,SET);} | |
//******************************** 片选引脚的宏定义 ******************************// | |
//******************************** 推荐常用函数 ******************************// | |
//SPI 初始化 | |
void vgd25q64SPIInit(void); | |
// 刷新写入,先删除再写入(自动处理删除,和写入跨页) | |
void vgd25q64FlushWrite(uint8_t *sourcedata,uint32_t address,uint32_t length); | |
// 读数据 | |
void vgd25q64ReadData(uint8_t *sourcedata, uint32_t address, uint32_t length); | |
// 删除(删除指定地址到指定长度,自动处理跨页) | |
void vgd25q64FlushDel(uint32_t address,uint32_t length); | |
//******************************** 推荐常用函数 ******************************// | |
//******************************** 不常用函数 ******************************// | |
// 擦除片 | |
void vgd25q64EraseSector(uint32_t eraseAddr); | |
// 擦除范围片 | |
void vgd25q64EraseAppointSector(uint32_t addstart,uint32_t addend); | |
// 擦除整块芯片 | |
void Flash_EraseChip(void); | |
// 写数据 | |
void vgd25q64WriteData(uint8_t *sourcedata, uint32_t address, uint32_t length); | |
// 获取位置信息(用于变地址存储信息,减少芯片的擦写次数) | |
uint32_t vgd25q64GetDataPos(uint32_t Startaddress,uint32_t length); | |
// 读状态寄存器(用于配置外挂 FLASH 的一些功能) | |
void vgd25q64WriteStatusRegisterx(uint8_t sourcedata, uint8_t GD25Q64_ReadStatusRegisterx); | |
//******************************** 不常用函数 ******************************// | |
#endif |
gd25q64.c
#include "stdio.h" | |
#include "stdlib.h" | |
#include "systick.h" | |
#include "../User/BSP/gd25q64/gd25q64.h" | |
//#define DEBUG | |
uint8_t gd25q64Data[gd25q64DataLen]; | |
extern bool vdatastorageCheckArraySame(uint8_t *sourcearray, uint8_t *targetarray, uint32_t len); | |
/*********************************************************** | |
*@fuction :vgd25q64SPIInit | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void vgd25q64SPIInit(void) | |
{ | |
// 打开时钟 | |
rcu_periph_clock_enable(RCU_AF); | |
rcu_periph_clock_enable(gd25q64RCU_GPIOx); | |
rcu_periph_clock_enable(gd25q64RCU_SPIx); | |
// 初始化引脚 | |
gpio_init(gd25q64GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, gd25q64GPIO_PIN_x); | |
gpio_init(gd25q64GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, gd25q64SPI_CS_PIN_x); | |
gpio_bit_write(gd25q64GPIOx, gd25q64SPI_CS_PIN_x, SET); | |
// 初始化 SPI | |
spi_parameter_struct spi_init_struct; | |
spi_i2s_deinit(SPI0); | |
spi_struct_para_init(&spi_init_struct); | |
spi_init_struct.device_mode = SPI_MASTER; | |
spi_init_struct.prescale = SPI_PSC_32; | |
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; | |
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; | |
spi_init_struct.endian = SPI_ENDIAN_MSB; | |
spi_init_struct.nss = SPI_NSS_SOFT; | |
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; | |
spi_init(SPI0, &spi_init_struct); | |
spi_enable(SPI0); | |
} | |
/*********************************************************** | |
*@fuction :spi_master_send_recv_byte | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
uint8_t spi_master_send_recv_byte(uint8_t sourcedata) | |
{ | |
static uint8_t ByteRecv; | |
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE)) | |
; | |
spi_i2s_data_transmit(SPI0, sourcedata); | |
while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE)) | |
; | |
ByteRecv = spi_i2s_data_receive(SPI0); | |
return ByteRecv; | |
} | |
/*********************************************************** | |
*@fuction :spi_master_recv_some_bytes | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void spi_master_recv_some_bytes( uint8_t *sourcedata, uint16_t length) | |
{ | |
uint8_t *temp_data = sourcedata; | |
while (length--) | |
{ | |
*temp_data = spi_master_send_recv_byte(0xFF); // 发送 0xff 为从设备提供时钟 | |
temp_data++; | |
} | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64WriteEnable | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void vgd25q64WriteEnable(void) | |
{ | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_WriteEnable); | |
GD25Q64_CS_HIGH(); | |
} | |
/*********************************************************** | |
*@fuction :ucgd25q64ReadStatusRegister | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
uint8_t ucgd25q64ReadStatusRegister(uint8_t GD25Q64_ReadStatusRegisterx) | |
{ | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_ReadStatusRegisterx); | |
uint8_t StatusRegisterx = spi_master_send_recv_byte(0xFF); | |
GD25Q64_CS_HIGH(); | |
return StatusRegisterx; | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64WriteStatusRegisterx | |
*@brief : 写状态寄存器 | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void vgd25q64WriteStatusRegisterx(uint8_t sourcedata, uint8_t GD25Q64_ReadStatusRegisterx) | |
{ | |
vgd25q64WriteEnable(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_ReadStatusRegisterx); | |
spi_master_send_recv_byte(sourcedata); | |
GD25Q64_CS_HIGH(); | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64EraseSector | |
*@brief : 擦除 sector | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void vgd25q64EraseSector(uint32_t eraseAddr) | |
{ | |
vgd25q64WriteEnable(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_SectorErase); | |
spi_master_send_recv_byte((uint8_t)(eraseAddr >> 16)); | |
spi_master_send_recv_byte((uint8_t)(eraseAddr >> 8)); | |
spi_master_send_recv_byte((uint8_t)(eraseAddr)); | |
GD25Q64_CS_HIGH(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64EraseAppointSector | |
*@brief : 擦除指定范围的 sector | |
*@param : 起始地址到结束地址 | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void vgd25q64EraseAppointSector(uint32_t addstart, uint32_t addend) | |
{ | |
uint32_t startsector = addstart / GD25Q64_SectorSize * GD25Q64_SectorSize; | |
uint32_t endsector = addend / GD25Q64_SectorSize * GD25Q64_SectorSize; | |
uint32_t erasesectornum = (endsector / GD25Q64_SectorSize) - (startsector / GD25Q64_SectorSize); | |
for(uint8_t i = 0; i <= erasesectornum; i++) | |
{ | |
vgd25q64EraseSector(startsector + i * GD25Q64_SectorSize); | |
} | |
} | |
/*********************************************************** | |
*@fuction :Flash_EraseChip | |
*@brief : 整片擦除 | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void Flash_EraseChip(void) | |
{ | |
vgd25q64WriteEnable(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_ChipErase); | |
GD25Q64_CS_HIGH(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
} | |
/*********************************************************** | |
*@fuction :uigd25q64ReadIdentification | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
unsigned int uigd25q64ReadIdentification(void) | |
{ | |
uint32_t Identification = 0; | |
uint8_t recv_buff[3] = {0}; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_ReadIdentification); //9fh | |
uint8_t recvLen = sizeof(recv_buff); | |
for(uint8_t i = 0 ; i < recvLen; i++) | |
{ | |
recv_buff[i] = spi_master_send_recv_byte(0xFF); // 发送 0xff 为从设备提供时钟 | |
} | |
Identification = (recv_buff[0] << 16) | (recv_buff[1] << 8) | (recv_buff[2]); | |
GD25Q64_CS_HIGH(); | |
return Identification; | |
} | |
/*********************************************************** | |
*@fuction :usgd25q64ReadID | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
unsigned short usgd25q64ReadID(void) | |
{ | |
uint16_t ID = 0; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_ManufacturerDeviceID); | |
spi_master_send_recv_byte(0x00); | |
spi_master_send_recv_byte(0x00); | |
spi_master_send_recv_byte(0x00); | |
ID |= spi_master_send_recv_byte(0xFF) << 8; | |
ID |= spi_master_send_recv_byte(0xFF); | |
GD25Q64_CS_HIGH(); | |
return ID; | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64WritePage | |
*@brief : 页编程,需要考虑 先删除,后写入,写入时要考虑跨页机制 | |
*@param :-- | |
*@return :void | |
*@author :flechazo | |
*@date :2023-06-13 | |
***********************************************************/ | |
void vgd25q64WritePage(uint8_t *sourcedata, uint32_t address, uint32_t length) | |
{ | |
vgd25q64WriteEnable(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_PageProgram); | |
spi_master_send_recv_byte(address >> 16); | |
spi_master_send_recv_byte(address >> 8); | |
spi_master_send_recv_byte(address >> 0); | |
for(uint32_t i = 0; i < length; i++) | |
{ | |
spi_master_send_recv_byte(sourcedata[i]); | |
} | |
GD25Q64_CS_HIGH(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64WriteData | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :flechazo 更多例程请访问 (flechazo.mba) | |
*@date :2023-06-22 | |
***********************************************************/ | |
void vgd25q64WriteData(uint8_t *sourcedata, uint32_t address, uint32_t length) | |
{ | |
uint32_t currentGroup = 0; | |
uint32_t DataAdd = address; | |
uint32_t currentLen = length, residuelength = length; | |
uint32_t shiftingadd = address % GD25Q64_PageSize; | |
uint32_t firstwritelength = 0; | |
uint8_t status1 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1); | |
uint8_t status2 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister2); | |
uint8_t status3 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister3); | |
vgd25q64WriteStatusRegisterx(0x04, GD25Q64_ReadStatusRegister1); | |
status1 = ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1); | |
//write first page | |
if(shiftingadd && ((shiftingadd + length) > GD25Q64_PageSize)) | |
{ | |
firstwritelength = GD25Q64_PageSize - shiftingadd; | |
vgd25q64WriteEnable(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_PageProgram); | |
spi_master_send_recv_byte(DataAdd >> 16); | |
spi_master_send_recv_byte(DataAdd >> 8); | |
spi_master_send_recv_byte(DataAdd >> 0); | |
for(uint32_t i = 0; i < firstwritelength; i++) | |
{ | |
spi_master_send_recv_byte(sourcedata[i]); | |
} | |
GD25Q64_CS_HIGH(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
DataAdd += firstwritelength; | |
residuelength -= firstwritelength; | |
currentLen = residuelength; | |
} | |
do | |
{ | |
//vgd25q64ReadData(gd25q64Data,PosGD25Q64_TaskInfo_num_I,GD25Q64_SectorSize); | |
if(currentLen > (GD25Q64_PageSize)) | |
{ | |
currentLen = GD25Q64_PageSize; | |
} | |
vgd25q64WriteEnable(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_PageProgram); | |
spi_master_send_recv_byte(DataAdd >> 16); | |
spi_master_send_recv_byte(DataAdd >> 8); | |
spi_master_send_recv_byte(DataAdd >> 0); | |
for(uint32_t i = 0; i < currentLen; i++) | |
{ | |
uint32_t shifting = firstwritelength + i + (currentGroup * GD25Q64_PageSize); | |
spi_master_send_recv_byte(sourcedata[shifting]); | |
} | |
GD25Q64_CS_HIGH(); | |
while(((ucgd25q64ReadStatusRegister(GD25Q64_ReadStatusRegister1)) & 0x01) == 0x01) | |
; | |
if(residuelength >= currentLen) | |
{ | |
residuelength -= currentLen; | |
} | |
DataAdd += currentLen; | |
currentLen = residuelength; | |
} | |
while((currentGroup++) < (length / (GD25Q64_PageSize))); | |
} | |
/*! | |
\brief vgd25q64ReadData | |
\param[in] *sourcedata | |
\param[in] address | |
\param[in] length | |
\param[out] none | |
\retval none | |
*/ | |
void vgd25q64ReadData(uint8_t *sourcedata, uint32_t address, uint32_t length) | |
{ | |
uint8_t *temp_data = sourcedata; | |
GD25Q64_CS_LOW(); | |
spi_master_send_recv_byte(GD25Q64_ReadData); | |
spi_master_send_recv_byte((uint8_t)(address >> 16)); | |
spi_master_send_recv_byte((uint8_t)(address >> 8)); | |
spi_master_send_recv_byte((uint8_t)(address >> 0)); | |
while (length--) | |
{ | |
*temp_data = spi_master_send_recv_byte(0xFF); // 发送 0xff 为从设备提供时钟 | |
temp_data++; | |
} | |
GD25Q64_CS_HIGH(); | |
} | |
/*! | |
\brief vgd25q64FlushWrite erase -> write | |
\param[in] *data | |
\param[in] add | |
\param[in] length | |
\param[out] none | |
\retval none | |
*/ | |
void vgd25q64FlushWrite(uint8_t *sourcedata, uint32_t address, uint32_t length) | |
{ | |
bool falg = false; | |
uint32_t startSectorAddress = ((address / GD25Q64_SectorSize) * GD25Q64_SectorSize); | |
uint32_t endSectorAddress = (((address + length) / GD25Q64_SectorSize) * GD25Q64_SectorSize); | |
uint32_t startAddress = address % GD25Q64_SectorSize; | |
vgd25q64ReadData(gd25q64Data, startSectorAddress, GD25Q64_SectorSize); | |
for(uint32_t i = 0; i < length; i++) | |
{ | |
if(gd25q64Data[startAddress + i] != 0xFF) | |
{ | |
falg = true; | |
} | |
} | |
//no need to erase | |
if(!falg) | |
{ | |
vgd25q64WriteData(sourcedata, address, length); | |
} | |
else | |
{ | |
//need to erase | |
if(startSectorAddress == endSectorAddress) | |
{ | |
for(uint32_t i = 0; i < length; i++) | |
{ | |
gd25q64Data[i + startAddress] = sourcedata[i]; | |
} | |
vgd25q64EraseSector(address); | |
vgd25q64WriteData(gd25q64Data, startSectorAddress, GD25Q64_SectorSize); | |
} | |
else | |
{ | |
for(uint32_t i = 0; i < (GD25Q64_SectorSize - startAddress); i++) | |
{ | |
gd25q64Data[i + startAddress] = sourcedata[i]; | |
} | |
vgd25q64EraseSector(startSectorAddress); | |
vgd25q64WriteData(gd25q64Data, startSectorAddress, GD25Q64_SectorSize); | |
uint32_t enddatalen = length - (GD25Q64_SectorSize - startAddress); | |
vgd25q64ReadData(gd25q64Data, endSectorAddress, GD25Q64_SectorSize); | |
for(uint32_t i = 0; i < enddatalen; i++) | |
{ | |
gd25q64Data[i] = sourcedata[(GD25Q64_SectorSize - startAddress) + i]; | |
} | |
vgd25q64EraseSector(endSectorAddress); | |
vgd25q64WriteData(gd25q64Data, endSectorAddress, GD25Q64_SectorSize); | |
} | |
} | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64FlushDel | |
*@brief : | |
*@param :-- | |
*@return :void | |
*@author :-- | |
*@date :2023-04-23 | |
***********************************************************/ | |
void vgd25q64FlushDel(uint32_t address, uint32_t length) | |
{ | |
uint32_t startSectorAddress = ((address / GD25Q64_SectorSize) * GD25Q64_SectorSize); | |
uint32_t endSectorAddress = (((address + length) / GD25Q64_SectorSize) * GD25Q64_SectorSize); | |
uint32_t SectorinterstartAddress = (address - startSectorAddress); | |
if(startSectorAddress == endSectorAddress) | |
{ | |
vgd25q64ReadData(gd25q64Data, startSectorAddress, GD25Q64_SectorSize); | |
vgd25q64EraseSector(startSectorAddress); | |
//write Previous | |
vgd25q64WriteData(gd25q64Data, startSectorAddress, SectorinterstartAddress); | |
//write subsequent | |
vgd25q64WriteData(gd25q64Data + SectorinterstartAddress + length, startSectorAddress + SectorinterstartAddress + length, GD25Q64_SectorSize - SectorinterstartAddress - length); | |
} | |
else | |
{ | |
//startSectorAddress | |
vgd25q64ReadData(gd25q64Data, startSectorAddress, GD25Q64_SectorSize); | |
vgd25q64EraseSector(startSectorAddress); | |
vgd25q64WriteData(gd25q64Data, startSectorAddress, SectorinterstartAddress); | |
//endSectorAddress | |
vgd25q64ReadData(gd25q64Data, endSectorAddress, GD25Q64_SectorSize); | |
vgd25q64EraseSector(endSectorAddress); | |
uint32_t endSectorWriteAdd = (length + SectorinterstartAddress) % GD25Q64_SectorSize ; | |
vgd25q64WriteData(&gd25q64Data[endSectorWriteAdd], endSectorAddress + endSectorWriteAdd, GD25Q64_SectorSize - endSectorWriteAdd); | |
//middleSector | |
uint32_t middleSector = address + GD25Q64_SectorSize; | |
for( ; middleSector < endSectorAddress; middleSector += GD25Q64_SectorSize) | |
{ | |
vgd25q64EraseSector(middleSector); | |
} | |
} | |
} | |
/*********************************************************** | |
*@fuction :vgd25q64GetDataPos | |
*@brief :input address then output this data storage position | |
*@param :uint32_t Startaddress uint32_t length | |
*@return :uint32_t position | |
*@author :flechazo | |
*@date :2023-04-23 | |
***********************************************************/ | |
uint32_t vgd25q64GetDataPos(uint32_t Startaddress, uint32_t length) | |
{ | |
uint32_t position = 0; | |
uint32_t tempPos; | |
uint32_t count = 0; | |
bool direction = false; | |
vgd25q64ReadData(gd25q64Data, Startaddress, length); | |
tempPos = length; | |
uint8_t checkdata[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | |
do | |
{ | |
tempPos /= 2; | |
if(direction) | |
{ | |
position -= tempPos; | |
} | |
else | |
{ | |
position += tempPos; | |
} | |
count++; | |
if(vdatastorageCheckArraySame(checkdata, &gd25q64Data[position], 8)) | |
{ | |
//data is front | |
direction = true; | |
} | |
else | |
{ | |
//data is back | |
direction = false; | |
} | |
} | |
while(tempPos > 0); | |
position++; | |
while(gd25q64Data[position] == 0xFF) | |
{ | |
position--; | |
} | |
position++; | |
return (position + Startaddress); | |
} |