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;
}