STM32之SPI驱动外部Flash

MCU为STM32F030C8T6,Nor Flash为IS25LQ010B。

spi.h源代码

#ifndef __spi_H
#define __spi_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx_hal.h"

#define    SPI2_NSS     GPIO_PIN_12    /* PB12 */
#define    SPI2_SCLK    GPIO_PIN_13    /* PB13 */
#define    SPI2_MISO    GPIO_PIN_14    /* PB14 */
#define    SPI2_MOSI    GPIO_PIN_15    /* PB15 */

/* Variables */
extern SPI_HandleTypeDef hspi2;


/* Function prototype */
extern void _Error_Handler(char *, int);
void MX_SPI2_Init(void);

#ifdef __cplusplus
}
#endif

#endif /*__ spi_H */

spi.c源代码:

#include "spi.h"

SPI_HandleTypeDef hspi2;

/* SPI2 init function */
void MX_SPI2_Init(void)
{
    hspi2.Instance = SPI2;
    hspi2.Init.Mode = SPI_MODE_MASTER;
    hspi2.Init.Direction = SPI_DIRECTION_2LINES;
    hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi2.Init.NSS = SPI_NSS_SOFT;
    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi2.Init.CRCPolynomial = 7;
    hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
    hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;

    if (HAL_SPI_Init(&hspi2) != HAL_OK)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
}

/* Init SPI GPIO pins */
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    if(spiHandle->Instance==SPI2)
    {
        /* SPI2 clock enable */
        __HAL_RCC_SPI2_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();

        /**SPI2 GPIO Configuration
        PB12     ------> SPI2_NSS
        PB13     ------> SPI2_SCK
        PB14     ------> SPI2_MISO
        PB15     ------> SPI2_MOSI
        */
        GPIO_InitStruct.Pin = SPI2_NSS;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        GPIO_InitStruct.Pin =  SPI2_SCLK | SPI2_MISO | SPI2_MOSI;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        /* Configure SPI2_NSS default output level */
        HAL_GPIO_WritePin(GPIOB, SPI2_NSS, GPIO_PIN_SET);
    }
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
    if(spiHandle->Instance==SPI2)
    {
        /* Peripheral clock disable */
        __HAL_RCC_SPI2_CLK_DISABLE();
        __HAL_RCC_GPIOB_CLK_DISABLE();

        /**SPI2 GPIO Configuration
        PB12     ------> SPI2_NSS
        PB13     ------> SPI2_SCK
        PB14     ------> SPI2_MISO
        PB15     ------> SPI2_MOSI
        */
        HAL_GPIO_DeInit(GPIOB, SPI2_NSS | SPI2_SCLK | SPI2_MISO | SPI2_MOSI);
    }
}

flash.h源代码:

#ifndef __FLASH_IS25LQ010B_H__
#define __FLASH_IS25LQ010B_H__  /* Define macro __FLASH_IS25LQ010B_H__ */

#ifdef __cplusplus
extern "C"{
#endif

#include 
#include 

#define IS25LQ010B   /* Define NOR Flash type */
#define MAX_COMMAND_SIZE  (256+3+1)

#define    DUMMY_BYTE    (0x00)
#define    SPI2_TIMEOUT  (1000)
#define    SPI2_WAITING_FOREVER    (0xFFFFFFFF)

#define IS25LQ010B_FLASH_BASE_ADDRESS    (0x000000)
#define IS25LQ010B_FLASH_SECTOR_SIZE     (0x1000)              /* 4Kb */
#define IS25LQ010B_FLASH_BLOCK_SIZE      (IS25LQ010B_FLASH_SECTOR_SIZE*8)    /* 32Kb */
#define IS25LQ010B_FLASH_SIZE            (IS25LQ010B_FLASH_BLOCK_SIZE*4)      /* 128Kb */

/* Device Operation Instruction Set */
#define   RD       0x03    /* Read Data Bytes from Memory at Normal Read Mode, SPI mode, Maximum frequency 33MHz */
#define   FR       0x0B    /* Read Data Bytes from Memory at Fast Read Mode, SPI mode, Maximum frequency 104MHz */
#define   FRDIO    0xBB    /* Fast Read Dual I/O, SPI mode, Maximum frequency 104MHz */
#define   FRDO     0x3B    /* Fast Read Dual Output, SPI mode, Maximum frequency 104MHz */
#define   FRQIO    0xEB    /* Fast Read Quad I/O, SPI mode, Maximum frequency 104MHz */
#define   FRQO     0x6B    /* Fast Read Quad Output, SPI mode, Maximum frequency 104MHz */

/* Follow instructions must be preceded by the WREN instruction */ 
/************************** Start *********************************/ 
#define    PP    0x02       /* Page Program Data Bytes into Memory, SPI mode, Maximum frequency 104MHz */
#define    PPQ   0x32       /* Page Program Data Bytes into Memory with Quad Interface, SPI mode, Maximum frequency 104MHz */
//#define    PPQ   0x38     /* Page Program Data Bytes into Memory with Quad Interface, SPI mode, Maximum frequency 104MHz */
#define    SER   0xD7       /* Sector Erase 4KB, SPI mode, Maximum frequency 104MHz */
//#define    SER   0x20     /* Sector Erase 4KB, SPI mode, Maximum frequency 104MHz */

#if defined(IS25LQ040B) || defined(IS25LQ020B) || defined(IS25LQ010B)
    #define    BER32    0x52    /* Block Erase 32KB, SPI mode, Maximum frequency 104MHz */
    #define    BER64    0xD8    /* Block Erase 64KB, SPI mode, Maximum frequency 104MHz */
#elif defined(IS25LQ512B) || defined(IS25LQ025B)
    #define    BER32    0x52    /* Block Erase 32KB, SPI mode, Maximum frequency 104MHz */
    //#define    BER32    0xD8    /* Block Erase 32KB, SPI mode, Maximum frequency 104MHz */
    #define    BER64            /* Unsupported instruction */
#endif

#if defined(IS25LQ040B) || defined(IS25LQ020B) || defined(IS25LQ010B) || defined(IS25LQ512B)
    #define    CER      0xC7    /* Chip Erase, SPI mode, Maximum frequency 104MHz */
    //#define    CER      0x60    /* Chip Erase, SPI mode, Maximum frequency 104MHz */
#endif

#define    WRSR     0x01    /* Write Status Register, SPI mode, Maximum frequency 104MHz */
#define    WRFR     0x42    /* Write Function Register, SPI mode, Maximum frequency 104MHz */
#define    IRP      0x62    /* Program Information Row, SPI mode, Maximum frequency 104MHz */
/************************** End *********************************/

#define    WREN     0x06    /* Write Enable, SPI mode, Maximum frequency 104MHz */
#define    WRDI     0x04    /* Write Disable, SPI mode, Maximum frequency 104MHz */
#define    RDSR     0x05    /* Read Status Register, SPI mode, Maximum frequency 104MHz */
#define    RDFR     0x48    /* Read Function Register, SPI mode, Maximum frequency 104MHz */
#define    PERSUS   0x75    /* Suspend during the Program/Erase, SPI mode, Maximum frequency 104MHz */ 
//#define    PERSUS   0xB0    /* Suspend during the Program/Erase, SPI mode, Maximum frequency 104MHz */
#define    PERRSM    0x7A   /* Resume Program/Erase, SPI mode, Maximum frequency 104MHz */ 
//#define    PERRSM    0x30   /* Resume Program/Erase, SPI mode, Maximum frequency 104MHz */
#define    DP       0xB9    /* Deep Power Down Mode, SPI mode, Maximum frequency 104MHz */
#define    RDID     0xAB    /* Read Manufacturer and Product ID/Release Deep Power Down, SPI mode, Maximum frequency 104MHz */
#define    RDPD     0xAB    /* Read Manufacturer and Product ID/Release Deep Power Down, SPI mode, Maximum frequency 104MHz */
#define    RDUID    0x4B    /* Read Unique ID Number, SPI mode, Maximum frequency 104MHz */
#define    RDJDID   0x9F    /* Read Manufacturer and Product ID by JEDEC ID Command, SPI mode, Maximum frequency 104MHz */
#define    RDMDID   0x90    /* Read Manufacturer and Device ID, SPI mode, Maximum frequency 104MHz */
#define    RDSFDP   0x5A    /* SFDP Read, SPI mode, Maximum frequency 104MHz */
#define    RSTEN    0x66    /* Software Reset Enable, SPI mode, Maximum frequency 104MHz */
#define    RST      0x99    /* Reset, SPI mode, Maximum frequency 104MHz */
#define    IRRD     0x68    /* Read Information Row, SPI mode, Maximum frequency 104MHz */
#define    SECUNLOCK  0x26  /* Sector Unlock, SPI mode, Maximum frequency 104MHz */
#define    SECLOCK  0x24    /* Sector Lock, SPI mode, Maximum frequency 104MHz */

/* Function Prototype */
void IS25LQ010B_NORFlashInit(void);
void IS25LQ010B_NSSEnable(void);
void IS25LQ010B_NSSDisable(void);
bool IS25LQ010B_WriteEnable(void);
bool IS25LQ010B_WriteDisable(void);
int32_t IS25LQ010B_ReadStatusRegister(uint8_t* StatusRegister);
int32_t IS25LQ010B_WriteSatusRegister(uint8_t SatusRegister);
int32_t IS25LQ010B_ReadFunctionRegister(uint8_t* FunctionRegister);
int32_t IS25LQ010B_WriteFunctionRegister(uint8_t FunctionRegister);
bool IS25LQ010B_DeviceIsBusy(void);
int32_t IS25LQ010B_WritePage(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_WriteNoCheck(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_Write(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_SectorErase(uint32_t Address);
int32_t IS25LQ010B_BlockErase32KB(uint32_t Address);
int32_t IS25LQ010B_BlockErase64KB(uint32_t Address);
int32_t IS25LQ010B_EraseChip(void);
int32_t IS25LQ010B_Read(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_FastRead(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_DeepPowerDown(void);
int32_t IS25LQ010B_ReleaseDeepPowerDown(void);
int32_t IS25LQ010B_ReadDeviceID(uint8_t* DeviceID);
int32_t IS25LQ010B_ReadManufacturerProductCapacity(uint8_t* ManufacturerID, uint8_t* DeviceType, uint8_t* Capacity);
int32_t IS25LQ010B_ReadManufacturerIDDeviceID(uint32_t Address, uint8_t* ManufacturerID, uint8_t* DeviceID);
int32_t IS25LQ010B_ReadUID(uint32_t Address, uint8_t* UID, uint16_t* UIDSize);
int32_t IS25LQ010B_ReadSerialFlashDiscoverableParameter(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_SoftwareReset(void);
int32_t IS25LQ010B_WritRowPage(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_WriteRowNoCheck(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_WriteRow(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_ReadRow(uint32_t Address, uint8_t* Data, uint16_t Size);
int32_t IS25LQ010B_SectorLock(void);
int32_t IS25LQ010B_SectorUnlock(uint32_t Address);

#ifdef __cplusplus
}
#endif

#endif /* End define macro __FLASH_IS25LQ010B_H__ */

flash.c源代码:

#include "flash_is25lq010b.h"
#include "spi.h"
#include 

/*
** @Brief: Init flash spi driver
** @Parameter: None
** @Return: None
**/
void IS25LQ010B_NORFlashInit(void)
{
    MX_SPI2_Init();
}

/*
** @Brief: Spi Chip Select Pin pull down and enable spi
** @Parameter: None
** @Return: None
**/
void IS25LQ010B_NSSEnable(void)
{
    HAL_GPIO_WritePin(GPIOB, SPI2_NSS, GPIO_PIN_RESET);
}

/*
** @Brief: Spi Chip Select Pin up down and disable spi
** @Parameter: None
** @Return: None
**/
void IS25LQ010B_NSSDisable(void)
{
    HAL_GPIO_WritePin(GPIOB, SPI2_NSS, GPIO_PIN_SET);
}

/*
** @Brief: Enable flash write function
** @Parameter: None
** @Return: 1) true, Enable OK
            2) false, Enable failed
**/
bool IS25LQ010B_WriteEnable(void)
{
    uint8_t Command = WREN;

    IS25LQ010B_NSSEnable();

    HAL_StatusTypeDef State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return false;
    }

    IS25LQ010B_NSSDisable();

    return true;
}

/*
** @Brief: Disable flash write function
** @Parameter: None
** @Return: 1) true, Disable OK
            2) false, Disable failed
**/
bool IS25LQ010B_WriteDisable(void)
{
    uint8_t Command = WRDI;

    IS25LQ010B_NSSEnable();

    HAL_StatusTypeDef State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return false;
    }

    IS25LQ010B_NSSDisable();

    return true;
}

/*
** @Brief: Read status register value
** @Parameter: StatusRegister, Status Register value
** @Return: 1) 0, get Status Register OK
            2) -1, get Status Register failed
**/
int32_t IS25LQ010B_ReadStatusRegister(uint8_t* StatusRegister)
{
    uint8_t Command = RDSR;
    HAL_StatusTypeDef State = HAL_OK;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        StatusRegister = NULL;
        return -1;
    }

    State = HAL_SPI_Receive(&hspi2, StatusRegister, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        StatusRegister = NULL;
        return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Write status register value
** @Parameter: SatusRegister, status register value
** @Return: 1) -1, transmit command data failed
            2) 0, set status register value successful
**/
int32_t IS25LQ010B_WriteSatusRegister(uint8_t SatusRegister)
{
    uint8_t Command[2] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    Command[CommandSize++] = WRSR;
    Command[CommandSize++] = SatusRegister;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -1;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Read function register value
** @Parameter: FunctionRegister, Function Register
** @Return: 1) 0, get Function Register value
            2) -1, get Function Register failed
**/
int32_t IS25LQ010B_ReadFunctionRegister(uint8_t* FunctionRegister)
{
    uint8_t Command = RDFR;
    HAL_StatusTypeDef State = HAL_OK;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        FunctionRegister = NULL;
        return -1;
    }

    State = HAL_SPI_Receive(&hspi2, FunctionRegister, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        FunctionRegister = NULL;
        return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Write function register value
** @Parameter: FunctionRegister, function register value
** @Return: 1) -1, transmit command failed
            2) 0, set function register value successful
**/
int32_t IS25LQ010B_WriteFunctionRegister(uint8_t FunctionRegister)
{
    uint8_t Command[2] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    Command[CommandSize++] = WRFR;
    Command[CommandSize++] = FunctionRegister;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -1;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Check device is busy
** @Parameter: None
** @Return: 1) true, device is busy
            2) false, device ready
**/
bool IS25LQ010B_DeviceIsBusy(void)
{
    uint8_t StatusRegister = 0;
    int32_t Result = 0;

    Result = IS25LQ010B_ReadStatusRegister(&StatusRegister);
    if(Result < 0)
    {
        /* Device busy, get status register failed */
        return true;
    }

    if(StatusRegister & 0x01)
    {
        /* Device busy */
        return true;
    }

    /* Device ready */
    return false;
}

/*
** @Brief: Write data to flash page
** @Parameter: 1) Address, flash address
               2) Data, write data
               3) Size, write data size
** @Return: 1) -1, enable write failed
            2) -2, write data to flash failed
            3) 0, write data to flash successful
**/
int32_t IS25LQ010B_WritePage(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint8_t Command[MAX_COMMAND_SIZE] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    if(!IS25LQ010B_WriteEnable())
    {
        return -1;
    }

    Command[CommandSize++] = PP;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;
    memcpy(&Command[CommandSize], Data, Size);
    CommandSize = Size + 4;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
         return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Write data to flash
** @Parameter: 1) Address, flash address
               2) Data, write data
               3) Size, write data size
** @Return: 1) -1, write data to flash page failed
            2) 0, write data to flash successful
**/
int32_t IS25LQ010B_WriteNoCheck(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint16_t PageRemain = 256 - Address % 256;
    int32_t Result = 0;

    if(PageRemain >= Size)
    {
        PageRemain = Size;
    }

    while(1)
    {
        Result = IS25LQ010B_WritePage(Address, Data, PageRemain);
        if(Result != 0)
        {
             return -1;
        }

        if(Size == PageRemain)
        {
            break;
        }
        else
        {
            Data    += PageRemain;
            Address += PageRemain;
            Size    -= PageRemain;

            if(Size > 256)
            {
                PageRemain = 256;
            }
            else
            {
                PageRemain = Size;
            }
        }
    }

    return 0;
}

/*
** @Brief: Write data to flash
** @Parameter: 1) Address, flash address
               2) Data, write data
               3) Size, write data size
** @Return: 1) -1, read flash data failed
            2) -2, erase sector failed
            3) -3, write date to flash failed
            4) -4, write data to flash failed
            5) 0, write data to flash successful
**/
int32_t IS25LQ010B_Write(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint16_t SectorPosition = Address / IS25LQ010B_FLASH_SECTOR_SIZE;
    uint16_t SectorOffset = Address % IS25LQ010B_FLASH_SECTOR_SIZE;
    uint16_t SectorRemain = IS25LQ010B_FLASH_SECTOR_SIZE - SectorOffset;
    uint8_t TempBuffer[IS25LQ010B_FLASH_SECTOR_SIZE] = {0};
    int32_t Result = 0;
    int32_t Index = 0;

    if(SectorRemain >= Size)
    {
        SectorRemain = Size;
    }

    while(1)
    {
        Result = IS25LQ010B_Read(SectorPosition*IS25LQ010B_FLASH_SECTOR_SIZE, TempBuffer, IS25LQ010B_FLASH_SECTOR_SIZE);
        if(Result != 0)
        {
            return -1;
        }

        for(Index = 0; Index < SectorRemain; Index++)
        {
            if(TempBuffer[SectorOffset + Index] != 0xFF)
            {
                break;
            }
        }

        if(Index < SectorRemain)
        {
            Result = IS25LQ010B_SectorErase(SectorPosition);
            if(Result != 0)
            {
                return -2;
            }

            memcpy(&TempBuffer[SectorOffset], Data, SectorRemain);

            Result = IS25LQ010B_WriteNoCheck(SectorPosition*IS25LQ010B_FLASH_SECTOR_SIZE, TempBuffer, IS25LQ010B_FLASH_SECTOR_SIZE);
            if(Result != 0)
            {
                return -3;
            }
        }
        else
        {
            Result = IS25LQ010B_WriteNoCheck(Address, Data, SectorRemain);
            if(Result != 0)
            {
                return -4;
            }
        }

        if(SectorRemain == Size)
        {
            break;
        }
        else
        {
            SectorPosition++;
            SectorOffset = 0;
            Data    += SectorRemain;
            Address += SectorRemain;
            Size    -= SectorRemain;

            if(Size > IS25LQ010B_FLASH_SECTOR_SIZE)
            {
                SectorRemain = IS25LQ010B_FLASH_SECTOR_SIZE;
            }
            else
            {
                SectorRemain = Size;
            }
        }
    }

    return 0;
}

/*
** @Brief: Erase a sector
** @Parameter: Address, sector address
** @Return: 1) -1, sector address illegal
            2) -2, write enable failed
            3) -3, sector erase  failed
            4) 0, sector erase successfil
**/
int32_t IS25LQ010B_SectorErase(uint32_t Address)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    /* Check whether address is legal */
    if(Address > (IS25LQ010B_FLASH_SIZE - IS25LQ010B_FLASH_SECTOR_SIZE))
    {
        return -1;
    }

    if(!IS25LQ010B_WriteEnable())
    {
        return -2;
    }

    while(IS25LQ010B_DeviceIsBusy());

    Command[CommandSize++] = SER;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -3;
    }

    IS25LQ010B_NSSDisable();

    while(IS25LQ010B_DeviceIsBusy());

    return 0;
}

/*
** @Brief: Erase a block
** @Parameter: Address, block address
** @Return: 1) -1, block address illegal
            2) -2, write enable failed
            3) -3, block erase failed
            4) 0, block erase successfil
**/
int32_t IS25LQ010B_BlockErase32KB(uint32_t Address)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;

    /* Check whether address is legal */
    if(Address > (IS25LQ010B_FLASH_SIZE - IS25LQ010B_FLASH_BLOCK_SIZE))
    {
        return -1;
    }

    if(!IS25LQ010B_WriteEnable())
    {
        return -2;
    }

    while(IS25LQ010B_DeviceIsBusy());

    Command[CommandSize++] = BER32;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;

    IS25LQ010B_NSSEnable();

    /* Transmit erase sector command */
    HAL_StatusTypeDef TransmitState = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(TransmitState != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -3;
    }

    IS25LQ010B_NSSDisable();

    while(IS25LQ010B_DeviceIsBusy());

    return 0;
}

/*
** @Brief: Erase a block
** @Parameter: Address, block address
** @Return: 1) -1, block address illegal
            2) -2, write enable failed
            3) -3, erase 64 Kb failed
            4) 0, erase 64Kb successfil
**/
int32_t IS25LQ010B_BlockErase64KB(uint32_t Address)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;

    /* Check whether address is legal */
    if(Address > (IS25LQ010B_FLASH_SIZE - 2 * IS25LQ010B_FLASH_BLOCK_SIZE))
    {
        return -1;
    }

    if(!IS25LQ010B_WriteEnable())
    {
        return -2;
    }

    while(IS25LQ010B_DeviceIsBusy());

    Command[CommandSize++] = BER64;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;

    IS25LQ010B_NSSEnable();

    /* Transmit erase sector command */
    HAL_StatusTypeDef TransmitState = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(TransmitState != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -3;
    }

    IS25LQ010B_NSSDisable();

    while(IS25LQ010B_DeviceIsBusy());

    return 0;
}

/*
** @Brief: Erase flash chip
** @Parameter: None
** @Return: 1) -1, write enable failed
            2) -2, erase flash chip failed
            0) 0, erase flash chip successful
**/
int32_t IS25LQ010B_EraseChip(void)
{
    uint8_t EraseChipCommand = CER;

    if(!IS25LQ010B_WriteEnable())
    {
        return -1;
    }

    while(IS25LQ010B_DeviceIsBusy());

    IS25LQ010B_NSSEnable();

    /* Transmit erase sector command */
    HAL_StatusTypeDef TransmitState = HAL_SPI_Transmit(&hspi2, &EraseChipCommand, 1, SPI2_TIMEOUT);
    if(TransmitState != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -2;
    }

    IS25LQ010B_NSSDisable();

    while(IS25LQ010B_DeviceIsBusy());

    return 0;
}

/*
** @Brief:  Read memory contents of the device at a maximum frequency of 33MHz
** @Parameter: 1) Address, flash address
               2) Data,    read data
               3) Size,    read data size
** @Return: 1) -1, Address illegal
            2) -2, transmit read command failed
            3) -3, receive read data failed
            4) 0, read data from flash successful
**/
int32_t IS25LQ010B_Read(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    /* Check whether parameters is legal */
    if((0 == Size) || (Address >= IS25LQ010B_FLASH_SIZE))
    {
        return -1;
    }

    Command[CommandSize++] = RD;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -2;
    }

    State = HAL_SPI_Receive(&hspi2, Data, Size, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -3;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Read memory data at up to a 104MHZ clock
** @Parameter: 1) Address, flash address
               2) Data,    read data
               3) Size,    read data size
** @Return: 1) -1, Address illegal
            2) -2, transmit read command failed
            3) -3, receive read data failed
            4) 0, read data from flash successful
**/
int32_t IS25LQ010B_FastRead(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint8_t Command[5] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef ReceiveState = HAL_OK;

    /* Check whether parameters is legal */
    if((0 == Size) || (Address >= IS25LQ010B_FLASH_SIZE))
    {
        return -1;
    }

    Command[CommandSize++] = FR;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;
    Command[CommandSize++] = DUMMY_BYTE;

    IS25LQ010B_NSSEnable();

    /* Transmit read data instrction */
    ReceiveState = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(ReceiveState != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -2;
    }

    ReceiveState = HAL_SPI_Receive(&hspi2, Data, Size, SPI2_TIMEOUT);
    if(ReceiveState != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -3;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Enter device minimizing the power comsumption
** @Parameter: None
** @Return: 1) -1, transmit command failed
            2) 0, operate execute successful
**/
int32_t IS25LQ010B_DeepPowerDown(void)
{
    uint8_t Command = DP;
    HAL_StatusTypeDef State = HAL_OK;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -1;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Release device minimizing the power comsumption
** @Parameter: None
** @Return: 1) -1, transmit command failed
            2) 0, operate execute successful
**/
int32_t IS25LQ010B_ReleaseDeepPowerDown(void)
{
    uint8_t Command = RDPD;
    HAL_StatusTypeDef State = HAL_OK;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -1;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Read a byte device ID
** @Parameter: DeviceID, device ID
** @Return: 1) -1, transmit command failed
            2) -2, receive device ID failed
            3) 0, get a byte device ID successful
**/
int32_t IS25LQ010B_ReadDeviceID(uint8_t* DeviceID)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    Command[CommandSize++] = RDID;
    Command[CommandSize++] = DUMMY_BYTE;
    Command[CommandSize++] = DUMMY_BYTE;
    Command[CommandSize++] = DUMMY_BYTE;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        DeviceID = NULL;
        return -1;
    }

    State = HAL_SPI_Receive(&hspi2, DeviceID, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        DeviceID = NULL;
        return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Read Manufacturer ID, Device type and Capacity
** @Parameter: 1) ManufacturerID
               2) DeviceType
               3) Capacity
** @Return: 1) -1, command transmit failed
            2) -2, recive Manufacturer ID, Device Type and Capacity data failed
            3) 0, operate successful
**/
int32_t IS25LQ010B_ReadManufacturerProductCapacity(uint8_t* ManufacturerID, uint8_t* DeviceType, uint8_t* Capacity)
{
    HAL_StatusTypeDef State = HAL_OK;
    uint8_t Command = RDJDID;
    uint8_t TmpData[3] = {0};

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        ManufacturerID = NULL;
        DeviceType = NULL;
        Capacity = NULL;
        return -1;
    }

    State = HAL_SPI_Receive(&hspi2, TmpData, 3, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        ManufacturerID = NULL;
        DeviceType = NULL;
        Capacity = NULL;
        return -2;
    }

    IS25LQ010B_NSSDisable();

    *ManufacturerID = TmpData[0];
    *DeviceType     = TmpData[1];
    *Capacity       = TmpData[2];

    return 0;
}

/*
** @Brief: Read Manufacturer ID and Device ID
** @Parameter: 1) Address, flash address
               2) ManufacturerID, need return Manufacturer ID
               3) DeviceID, need return Device ID
** @Return: 1) -1, Address illegal
            2) -2, command transmit failed
            3) -3, receive data failed
            0) 0, operate successful
**/
int32_t IS25LQ010B_ReadManufacturerIDDeviceID(uint32_t Address, uint8_t* ManufacturerID, uint8_t* DeviceID)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;
    uint8_t TmpData[2] = {0};

    /* Check whether parameters is legal */
    if(Address >= IS25LQ010B_FLASH_SIZE)
    {
        ManufacturerID = NULL;
        DeviceID = NULL;
        return -1;
    }

    Command[CommandSize++] = RDMDID;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSEnable();
        ManufacturerID = NULL;
        DeviceID = NULL;
        return -2;
    }

    State = HAL_SPI_Receive(&hspi2, TmpData, 2, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSEnable();
        ManufacturerID = NULL;
        DeviceID = NULL;
        return -3;
    }

    IS25LQ010B_NSSEnable();

    *ManufacturerID = TmpData[0];
    *DeviceID       = TmpData[1];

    return 0;
}

/*
** @Brief: Get 16 bytes unique ID number
** @Parameter: 1) Address, flash address
               2) UID, need return UID
               3) UIDSize, UID size
** @Return: 1) -1, parameter illegal
            2) -2,command transmit failed
            3) -3, receive UID data failed
            4) 0, operate successful
**/
int32_t IS25LQ010B_ReadUID(uint32_t Address, uint8_t* UID, uint16_t* UIDSize)
{
    uint8_t Command[5] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;
    uint8_t TmpUID[16] = {0};

    if(Address > IS25LQ010B_FLASH_SIZE)
    {
        return -1;
    }

    Command[CommandSize++] = RDUID;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;
    Command[CommandSize++] = DUMMY_BYTE;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -2;
    }

    State = HAL_SPI_Receive(&hspi2, TmpUID, 16, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -3;
    }

    IS25LQ010B_NSSDisable();

    /* return 16-byte device unique number */
    *UIDSize = 16;
    memcpy(UID, TmpUID, *UIDSize);

    return 0;
}

/*
** @Brief: Read Serial Flash Discoverable Parameter(SFDP)
** @Parameter: 1) Address, flash address
               2) Data, SFDP data
               3) Size, SFDP data size
** @Return: 1) -1, address illegal
            2) -2, command transmit failed
            3) -3, receive SFDP data failed
            4) 0, operate successful
**/
int32_t IS25LQ010B_ReadSerialFlashDiscoverableParameter(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint8_t Command[5] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    if(Address > IS25LQ010B_FLASH_SIZE)
    {
        memset(Data, 0, Size);
        return -1;
    }

    Command[CommandSize++] = RDSFDP;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;
    Command[CommandSize++] = DUMMY_BYTE;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        memset(Data, 0, Size);
        return -2;
    }

    State = HAL_SPI_Receive(&hspi2, Data, Size, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        memset(Data, 0, Size);
        return -3;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: software reset operation
** @Parameter: None
** @Return: 1) -1, transmit reset enable command failed
            2) -2, transmit reset command failed
            0) 0, operate successful
**/
int32_t IS25LQ010B_SoftwareReset(void)
{
    uint8_t ResetEnableCommand = RSTEN;
    uint8_t ResetCommand = RST;
    HAL_StatusTypeDef State = HAL_OK;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &ResetEnableCommand, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -1;
    }

    IS25LQ010B_NSSDisable();

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &ResetCommand, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Write data to flash page
** @Parameter: 1) Address, flash address
               2) Data, write data
               3) Size, write data size
** @Return: 1) -1, enable write failed
            2) -2, write data to flash failed
            3) 0, write data to flash successful
**/
int32_t IS25LQ010B_WritRowPage(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint8_t Command[MAX_COMMAND_SIZE] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    if(!IS25LQ010B_WriteEnable())
    {
        return -1;
    }

    Command[CommandSize++] = IRP;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;
    memcpy(&Command[CommandSize], Data, Size);
    CommandSize = Size + 4;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
         return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Write data to flash
** @Parameter: 1) Address, flash address
               2) Data, write data
               3) Size, write data size
** @Return: 1) -1, write data to flash page failed
            2) 0, write data to flash successful
**/
int32_t IS25LQ010B_WriteRowNoCheck(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint16_t PageRemain = 256 - Address % 256;
    int32_t Result = 0;

    if(PageRemain >= Size)
    {
        PageRemain = Size;
    }

    while(1)
    {
        Result = IS25LQ010B_WritRowPage(Address, Data, PageRemain);
        if(Result != 0)
        {
             return -1;
        }

        if(Size == PageRemain)
        {
            break;
        }
        else
        {
            Data    += PageRemain;
            Address += PageRemain;
            Size    -= PageRemain;

            if(Size > 256)
            {
                PageRemain = 256;
            }
            else
            {
                PageRemain = Size;
            }
        }
    }


    return 0;
}

/*
** @Brief: Write data to flash
** @Parameter: 1) Address, flash address
               2) Data, write data
               3) Size, write data size
** @Return: 1) 0, write data to flash successful
            2) -1, parameter illegal
            3) -2, write enable failed
            4) -3, write data to flash failed
            5) -4, write data to flash failed
**/
int32_t IS25LQ010B_WriteRow(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint16_t SectorPosition = Address / IS25LQ010B_FLASH_SECTOR_SIZE;
    uint16_t SectorOffset = Address % IS25LQ010B_FLASH_SECTOR_SIZE;
    uint16_t SectorRemain = IS25LQ010B_FLASH_SECTOR_SIZE - SectorOffset;
    uint8_t TempBuffer[IS25LQ010B_FLASH_SECTOR_SIZE] = {0};
    int32_t Result = 0;
    int32_t Index = 0;

    if(SectorRemain >= Size)
    {
        SectorRemain = Size;
    }

    while(1)
    {
        Result = IS25LQ010B_ReadRow(SectorPosition*IS25LQ010B_FLASH_SECTOR_SIZE, TempBuffer, IS25LQ010B_FLASH_SECTOR_SIZE);
        if(Result != 0)
        {
            return -1;
        }

        for(Index = 0; Index < SectorRemain; Index++)
        {
            if(TempBuffer[SectorOffset + Index] != 0xFF)
            {
                break;
            }
        }

        if(Index < SectorRemain)
        {
            Result = IS25LQ010B_SectorErase(SectorPosition);
            if(Result != 0)
            {
                return -2;
            }

            memcpy(&TempBuffer[SectorOffset], Data, SectorRemain);

            Result = IS25LQ010B_WriteRowNoCheck(SectorPosition*IS25LQ010B_FLASH_SECTOR_SIZE, TempBuffer, IS25LQ010B_FLASH_SECTOR_SIZE);
            if(Result != 0)
            {
                return -3;
            }
        }
        else
        {
            Result = IS25LQ010B_WriteRowNoCheck(Address, Data, SectorRemain);
            if(Result != 0)
            {
                return -4;
            }
        }

        if(SectorRemain == Size)
        {
            break;
        }
        else
        {
            SectorPosition++;
            SectorOffset = 0;
            Data    += SectorRemain;
            Address += SectorRemain;
            Size    -= SectorRemain;

            if(Size > IS25LQ010B_FLASH_SECTOR_SIZE)
            {
                SectorRemain = IS25LQ010B_FLASH_SECTOR_SIZE;
            }
            else
            {
                SectorRemain = Size;
            }
        }
    }

    return 0;
}

/*
** @Brief:  Read memory data at up to a 104MHZ clock
** @Parameter: 1) Address, flash address
               2) Data, read data
               3) Size, read data size
** @Return: 1) -1, parameter illegal
            2) -2, command transmit failed
            3) -3, receive data failed
            4) 0, read data from falsh successful
**/
int32_t IS25LQ010B_ReadRow(uint32_t Address, uint8_t* Data, uint16_t Size)
{
    uint8_t Command[5] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    if((0 == Size) || ((Address + Size/256 * IS25LQ010B_FLASH_SECTOR_SIZE) > IS25LQ010B_FLASH_SIZE))
    {
        return -1;
    }

    Command[CommandSize++] = IRRD;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;
    Command[CommandSize++] = DUMMY_BYTE;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        memset(Data, 0, Size);
        return -2;
    }

    State = HAL_SPI_Receive(&hspi2, Data, Size, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        memset(Data, 0, Size);
        return -3;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: The Sector Lock command relocks a sector that was previously unlocked by the Sector Unlock command
** @Parameter: None
** @Return: 1) -1, command transmit failed
            2) 0, operate successful
**/
int32_t IS25LQ010B_SectorLock(void)
{
    uint8_t Command = SECLOCK;
    HAL_StatusTypeDef State = HAL_OK;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, &Command, 1, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -1;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

/*
** @Brief: Unlock sector
** @Parameter: Address, flash address
** @Return: 1) -1, parameter illegal
            2) -2, command transmit failed
            3) 0, operate successful
**/
int32_t IS25LQ010B_SectorUnlock(uint32_t Address)
{
    uint8_t Command[4] = {0};
    uint16_t CommandSize = 0;
    HAL_StatusTypeDef State = HAL_OK;

    if(Address > IS25LQ010B_FLASH_SIZE)
    {
        return -1;
    }

    Command[CommandSize++] = SECUNLOCK;
    Command[CommandSize++] = (Address >> 16) & 0xFF;
    Command[CommandSize++] = (Address >>  8) & 0xFF;
    Command[CommandSize++] = Address & 0xFF;

    IS25LQ010B_NSSEnable();

    State = HAL_SPI_Transmit(&hspi2, Command, CommandSize, SPI2_TIMEOUT);
    if(State != HAL_OK)
    {
        IS25LQ010B_NSSDisable();
        return -2;
    }

    IS25LQ010B_NSSDisable();

    return 0;
}

你可能感兴趣的:(C语言,嵌入式,stm32)