GD25Q64存储芯片的读写驱动

对于小白的我来说,当时写这个真的是一头雾水。擦除的跨页处理就很恶心。

你想删除一段,这时就还得考虑把这一段额,说不清楚,画个图吧

当时因为这块,抓耳挠腮了很久,为什么网上的驱动都没有考虑这些呢?

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);
    //我用得模式为CMP = 0 ,status1 = 0,status2=0;所对应的为没有数据保护
    //vgd25q64WriteStatusRegisterx(0x04, GD25Q64_ReadStatusRegister1);//GD25Q64_WriteStatusRegister1这一块似乎存在问题
    //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);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlechazoCLF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值