1. 程式人生 > >基於Stm32硬體SPI控制GD25QFlash

基於Stm32硬體SPI控制GD25QFlash

/**
  *********************************************************************************************************
  * @file    hal_spiflash.c
  * @author  Movebroad -- KK
  * @version V1.0
  * @date    2018-07-24
  * @brief   SPI FLASH GD25Q80CSIG Device
  *		   SPI FLASH GD25Q40BSIG Device
  *********************************************************************************************************
  * @attention
  *		   NSS  : PB12
  *		   SCK  : PA5
  *		   MOSI : PA7
  *		   MISO : PA6
  *********************************************************************************************************
  */

#include "hal_spiflash.h"
#include "platform_config.h"
#include "platform_map.h"
#include "delay.h"
#include "usart.h"

SPI_HandleTypeDef GD25Q_SPIFLASH_Handler;
GD25Q_StatusTypeDef GD25QStatus = GD25Q80CSIG_OK;

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_Init(void)
 @Description			GD25Q_SPIFLASH_Init			: GD25Q SPIFLASH 初始化
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_Init(void)
{
	u32 ReadIdentificationID;
	GD25QStatus = GD25Q80CSIG_OK;
	
	GD25Q_SPIFLASH_Handler.Instance				= GD25Q_FLASH_SPIx;						//SPI1
	GD25Q_SPIFLASH_Handler.Init.Mode				= SPI_MODE_MASTER;						//設定SPI工作模式為主模式
	GD25Q_SPIFLASH_Handler.Init.Direction			= SPI_DIRECTION_2LINES;					//設定SPI資料模式為雙線模式
	GD25Q_SPIFLASH_Handler.Init.DataSize			= SPI_DATASIZE_8BIT;					//設定SPI資料大小為8位幀結構
	GD25Q_SPIFLASH_Handler.Init.CLKPolarity			= SPI_POLARITY_HIGH;					//串行同步時鐘的空閒狀態為高電平
	GD25Q_SPIFLASH_Handler.Init.CLKPhase			= SPI_PHASE_2EDGE;						//串行同步時鐘的第二個跳變沿資料被取樣
	GD25Q_SPIFLASH_Handler.Init.NSS				= SPI_NSS_SOFT;						//NSS訊號由軟體控制
	
#ifndef SYSTEMCLOCK
	#error No Define SYSTEMCLOCK!
#else
#if (SYSTEMCLOCK == SYSTEMCLOCKMSI)
	GD25Q_SPIFLASH_Handler.Init.BaudRatePrescaler	= SPI_BAUDRATEPRESCALER_2;				//定義波特率與分頻值
#elif (SYSTEMCLOCK == SYSTEMCLOCKHSI)
	GD25Q_SPIFLASH_Handler.Init.BaudRatePrescaler	= SPI_BAUDRATEPRESCALER_8;				//定義波特率與分頻值
#else
	#error SYSTEMCLOCK Define Error
#endif
#endif
	
	GD25Q_SPIFLASH_Handler.Init.FirstBit			= SPI_FIRSTBIT_MSB;						//資料傳輸從MSB位開始
	GD25Q_SPIFLASH_Handler.Init.TIMode				= SPI_TIMODE_DISABLE;					//關閉TI模式
	GD25Q_SPIFLASH_Handler.Init.CRCCalculation		= SPI_CRCCALCULATION_DISABLE;				//關閉硬體CRC校驗
	GD25Q_SPIFLASH_Handler.Init.CRCPolynomial		= 10;								//CRC值計算多項式
	
	if (HAL_SPI_Init(&GD25Q_SPIFLASH_Handler) != HAL_OK) {
		/* Initialization Error */
		GD25QStatus = GD25Q80CSIG_ERROR;
	}
	
	GD25Q_SPIFLASH_WakeUp();
	ReadIdentificationID = GD25Q_SPIFLASH_ReadIdentificationID();
	if ((ReadIdentificationID != GD25Q80CSIGIdentificationID) && (ReadIdentificationID != GD25Q40BSIGIdentificationID)) {
		GD25QStatus = GD25Q80CSIG_ERROR;
	}
}

/**********************************************************************************************************
 @Function			GD25Q_StatusTypeDef GD25Q_SPIFLASH_Get_Status(void)
 @Description			GD25Q_SPIFLASH_Get_Status	: GD25Q SPIFLASH 狀態
 @Input				void
 @Return				GD25Q_StatusTypeDef
**********************************************************************************************************/
GD25Q_StatusTypeDef GD25Q_SPIFLASH_Get_Status(void)
{
#ifdef	GD25Q_80CSIG
	return GD25QStatus;
#else
	return GD25Q80CSIG_ERROR;
#endif
}

/**********************************************************************************************************
 @Function			u8 GD25Q_SPI_FLASH_ReadByte(void)
 @Description			GD25Q_SPI_FLASH_ReadByte		: SPI FLASH 讀取一個位元組資料
 @Input				void
 @Return				readByte					: 讀取到的資料
**********************************************************************************************************/
u8 GD25Q_SPI_FLASH_ReadByte(void)
{
	u8 readByte, sendByte = GD25Q_Dummy_Byte;
	
	if (HAL_SPI_TransmitReceive(&GD25Q_SPIFLASH_Handler, &sendByte, &readByte, 1, 500) != HAL_OK) {
		readByte = GD25Q_Dummy_Byte;
	}
	return readByte;
}

/**********************************************************************************************************
 @Function			u8 GD25Q_SPI_FLASH_SendByte(u8 byte)
 @Description			GD25Q_SPI_FLASH_SendByte		: SPI FLASH 傳送一個位元組資料
 @Input				byte						: 傳送的資料
 @Return				void
**********************************************************************************************************/
u8 GD25Q_SPI_FLASH_SendByte(u8 byte)
{
	u8 readByte = 0x00, sendByte = byte;
	
	if (HAL_SPI_TransmitReceive(&GD25Q_SPIFLASH_Handler, &sendByte, &readByte, 1, 500) != HAL_OK) {
		readByte = GD25Q_Dummy_Byte;
	}
	return readByte;
}

/**********************************************************************************************************
 @Function			u32 GD25Q_SPIFLASH_ReadDeviceID(void)
 @Description			GD25Q_SPIFLASH_ReadDeviceID			: GD25Q SPIFLASH 讀取裝置ID
 @Input				void
 @Return				裝置ID
**********************************************************************************************************/
u32 GD25Q_SPIFLASH_ReadDeviceID(void)
{
	u32 deviceID = 0;
	
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_DeviceID);
	GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	deviceID = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return deviceID;
}

/**********************************************************************************************************
 @Function			u32 GD25Q_SPIFLASH_ReadManufactureID(void)
 @Description			GD25Q_SPIFLASH_ReadManufactureID		: GD25Q SPIFLASH 讀取廠商ID
 @Input				void
 @Return				廠商ID
**********************************************************************************************************/
u32 GD25Q_SPIFLASH_ReadManufactureID(void)
{
	u32 manufactureID = 0;
	
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_ManufactDeviceID);
	GD25Q_SPI_FLASH_SendByte(0x00);
	GD25Q_SPI_FLASH_SendByte(0x00);
	GD25Q_SPI_FLASH_SendByte(0x00);
	manufactureID |= GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte) << 8;
	manufactureID |= GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return manufactureID;
}

/**********************************************************************************************************
 @Function			u32 GD25Q_SPIFLASH_ReadIdentificationID(void)
 @Description			GD25Q_SPIFLASH_ReadIdentificationID	: GD25Q SPIFLASH 讀取型號ID
 @Input				void
 @Return				型號ID
**********************************************************************************************************/
u32 GD25Q_SPIFLASH_ReadIdentificationID(void)
{
	u32 identificationID = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
	
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_JedecDeviceID);
	Temp0 = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	Temp1 = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	Temp2 = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	identificationID = (Temp0 << 16) | (Temp1 << 8) | Temp2;
	
	return identificationID;
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteEnable(void)
 @Description			GD25Q_SPIFLASH_WriteEnable	: GD25Q SPIFLASH 寫使能
 @Input				void
 @Return				void
 @attention			WEL置位
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteEnable(void)
{
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_WriteEnable);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteDisable(void)
 @Description			GD25Q_SPIFLASH_WriteDisable	: GD25Q SPIFLASH 寫禁止
 @Input				void
 @Return				void
 @attention			WEL清零
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteDisable(void)
{
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_WriteDisable);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			u8 GD25Q_SPIFLASH_ReadStatusRegister(u8 statusRegister)
 @Description			GD25Q_SPIFLASH_ReadStatusRegister	: GD25Q SPIFLASH 讀狀態暫存器
 @Input				狀態暫存器地址
 @Return				狀態暫存器值
**********************************************************************************************************/
u8 GD25Q_SPIFLASH_ReadStatusRegister(u8 statusRegister)
{
	u8 readByte = 0;
	
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(statusRegister);
	readByte = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return readByte;
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteStatusRegister(u8 srLow, u8 srHigh)
 @Description			GD25Q_SPIFLASH_WriteStatusRegister	: GD25Q SPIFLASH 寫狀態暫存器
 @Input				srLow						: 狀態暫存器低位元組
					srHigh						: 狀態暫存器高位元組
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteStatusRegister(u8 srLow, u8 srHigh)
{
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_WriteStatusReg);
	GD25Q_SPI_FLASH_SendByte(srLow);
	GD25Q_SPI_FLASH_SendByte(srHigh);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WaitForBusy(void)
 @Description			GD25Q_SPIFLASH_WaitForBusy		: GD25Q SPIFLASH 等待裝置空閒
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_WaitForBusy(void)
{
	u8 flashStatus = 0;
	
	/* 選擇SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* Send "Read Status Register" instruction */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReadStatusReg1);
	
	/* Loop as long as the memory is busy with a write cycle */
	do {
		flashStatus = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	}
	while ((flashStatus & 0x01) == 0x01);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_PowerDown(void)
 @Description			GD25Q_SPIFLASH_PowerDown			: GD25Q SPIFLASH 進入掉電模式
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_PowerDown(void)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* Send "Power Down" instruction */
	GD25Q_SPI_FLASH_SendByte(GD25Q_PowerDown);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* Wait for TDP */
	Delay_US(3);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WakeUp(void)
 @Description			GD25Q_SPIFLASH_WakeUp			: GD25Q SPIFLASH 喚醒
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_WakeUp(void)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* Send "Release Power Down" instruction */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReleasePowerDown);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* Wait for TRES1 */
	Delay_US(5);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_EraseChip(void)
 @Description			GD25Q_SPIFLASH_EraseChip			: GD25Q SPIFLASH 擦除Chip
 @Input				void
 @Return				void
 @attention			800MS
**********************************************************************************************************/
void GD25Q_SPIFLASH_EraseChip(void)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 傳送FLASH寫使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空閒 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 傳送片擦除命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ChipErase);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待擦除完畢 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_EraseBlock(u32 BlockAddr)
 @Description			GD25Q_SPIFLASH_EraseBlock		: GD25Q SPIFLASH 擦除Block
 @Input				BlockAddr						: 塊地址(0x10000倍數)
 @Return				void
 @attention			GD25Q80CSIG SPI FLASH 擦除塊大小為64KB(65536Byte),即一個塊區大小,在寫入資料之前要求先擦除空間
					50MS
**********************************************************************************************************/
void GD25Q_SPIFLASH_EraseBlock(u32 BlockAddr)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 傳送FLASH寫使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空閒 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 傳送塊區擦除命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_BlockErase);
	
	/* 傳送塊區擦除地址高位 */
	GD25Q_SPI_FLASH_SendByte((BlockAddr & 0xFF0000) >> 16);
	
	/* 傳送塊區擦除地址中位 */
	GD25Q_SPI_FLASH_SendByte((BlockAddr & 0xFF00) >> 8);
	
	/* 傳送塊區擦除地址低位 */
	GD25Q_SPI_FLASH_SendByte(BlockAddr & 0xFF);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待擦除完畢 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_EraseSector(u32 SectorAddr)
 @Description			GD25Q_SPIFLASH_EraseSector		: GD25Q SPIFLASH 擦除Sector
 @Input				SectorAddr					: 扇區地址(0x1000倍數)
 @Return				void
 @attention			GD25Q80CSIG SPI FLASH 最小擦除塊大小為4KB(4096Byte),即一個扇區大小,在寫入資料之前要求先擦除空間
					20MS
**********************************************************************************************************/
void GD25Q_SPIFLASH_EraseSector(u32 SectorAddr)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 傳送FLASH寫使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空閒 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 傳送扇區擦除命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_SectorErase);
	
	/* 傳送扇區擦除地址高位 */
	GD25Q_SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
	
	/* 傳送扇區擦除地址中位 */
	GD25Q_SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
	
	/* 傳送扇區擦除地址低位 */
	GD25Q_SPI_FLASH_SendByte(SectorAddr & 0xFF);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待擦除完畢 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_ReadBuffer(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
 @Description			GD25Q_SPIFLASH_ReadBuffer		: GD25Q SPIFLASH 讀取SPI FLASH資料
 @Input				pBuffer						: 資料儲存區
					ReadAddr						: 資料讀取地址
					NumByteToRead					: 讀取資料長度
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_ReadBuffer(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 傳送讀指令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReadData);
	
	/* 傳送讀地址高位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
	
	/* 傳送讀地址中位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);
	
	/* 傳送讀地址低位 */
	GD25Q_SPI_FLASH_SendByte(ReadAddr & 0xFF);
	
	/* 讀取資料 */
	while (NumByteToRead--) {
		*pBuffer = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
		pBuffer++;
	}
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WritePage(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
 @Description			GD25Q_SPIFLASH_WritePage			: GD25Q SPIFLASH 寫入SPI FLASH資料Page
 @Input				pBuffer						: 資料儲存區
					WriteAddr						: 資料寫入地址
					NumByteToWrite					: 寫入資料長度
 @Return				void
 @attention			寫入位元組數不得超過該頁寫入剩餘位元組數
**********************************************************************************************************/
void GD25Q_SPIFLASH_WritePage(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 傳送FLASH寫使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空閒 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 傳送頁寫命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_PageProgram);
	
	/* 傳送寫地址高位 */
	GD25Q_SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
	
	/* 傳送寫地址中位 */
	GD25Q_SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
	
	/* 傳送寫地址低位 */
	GD25Q_SPI_FLASH_SendByte(WriteAddr & 0xFF);
	
	/* 寫入資料 */
	while (NumByteToWrite--) {
		GD25Q_SPI_FLASH_SendByte(*pBuffer);
		pBuffer++;
	}
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待寫入完畢 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteBuffer(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
 @Description			GD25Q_SPIFLASH_WriteBuffer		: GD25Q SPIFLASH 寫入SPI FLASH資料
 @Input				pBuffer						: 資料儲存區
					WriteAddr						: 資料寫入地址
					NumByteToWrite					: 寫入資料長度
 @Return				void
 @attention			具有自動換頁功能
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteBuffer(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
#ifdef GD25Q_80CSIG
	u16 pagereMain;
	
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	pagereMain = GD25Q80_PAGE_BYTE_SIZE - WriteAddr % GD25Q80_PAGE_BYTE_SIZE;
	if (NumByteToWrite <= pagereMain) pagereMain = NumByteToWrite;
	
	while (true) {
		GD25Q_SPIFLASH_WritePage(pBuffer, WriteAddr, pagereMain);
		if (NumByteToWrite == pagereMain) break;
		else {
			pBuffer += pagereMain;
			WriteAddr += pagereMain;
			
			NumByteToWrite -= pagereMain;
			if (NumByteToWrite > GD25Q80_PAGE_BYTE_SIZE) pagereMain = GD25Q80_PAGE_BYTE_SIZE;
			else pagereMain = NumByteToWrite;
		}
	}
#endif
}

/**********************************************************************************************************
 @Function			unsigned char GD25Q_SPIFLASH_GetByte(u32 ReadAddr)
 @Description			GD25Q_SPIFLASH_GetByte						: GD25Q SPIFLASH 讀取1個Byte
 @Input				void
 @Return				val
**********************************************************************************************************/
unsigned char GD25Q_SPIFLASH_GetByte(u32 ReadAddr)
{
#ifdef GD25Q_80CSIG
	unsigned char val = 0;
	
	GD25Q_SPIFLASH_ReadBuffer(&val, ReadAddr, 1);
	
	return val;
#endif
}

/**********************************************************************************************************
 @Function			unsigned short GD25Q_SPIFLASH_GetHalfWord(u32 ReadAddr)
 @Description			GD25Q_SPIFLASH_GetHalfWord					: GD25Q SPIFLASH 讀取2個Byte
 @Input				void
 @Return				val
**********************************************************************************************************/
unsigned short GD25Q_SPIFLASH_GetHalfWord(u32 ReadAddr)
{
#ifdef GD25Q_80CSIG
	unsigned short val = 0;
	unsigned char tmpval[2];
	
	GD25Q_SPIFLASH_ReadBuffer(tmpval, ReadAddr, 2);
	
	val |= tmpval[0];
	val |= tmpval[1] << 8;
	
	return val;
#endif
}

/**********************************************************************************************************
 @Function			unsigned int GD25Q_SPIFLASH_GetWord(u32 ReadAddr)
 @Description			GD25Q_SPIFLASH_GetWord						: GD25Q SPIFLASH 讀取4個Byte
 @Input				void
 @Return				val
**********************************************************************************************************/
unsigned int GD25Q_SPIFLASH_GetWord(u32 ReadAddr)
{
#ifdef GD25Q_80CSIG
	unsigned int val = 0;
	unsigned char tmpval[4];
	
	GD25Q_SPIFLASH_ReadBuffer(tmpval, ReadAddr, 4);
	
	val |= tmpval[0];
	val |= tmpval[1] << 8;
	val |= tmpval[2] << 16;
	val |= tmpval[3] << 24;
	
	return val;
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_SetByte(u32 WriteAddr, unsigned char val)
 @Description			GD25Q_SPIFLASH_SetByte						: GD25Q SPIFLASH 寫入1個Byte
 @Input				val
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_SetByte(u32 WriteAddr, unsigned char val)
{
#ifdef GD25Q_80CSIG
	GD25Q_SPIFLASH_WriteBuffer(&val, WriteAddr, 1);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_SetHalfWord(u32 WriteAddr, unsigned short val)
 @Description			GD25Q_SPIFLASH_SetHalfWord					: GD25Q SPIFLASH 寫入2個Byte
 @Input				val
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_SetHalfWord(u32 WriteAddr, unsigned short val)
{
#ifdef GD25Q_80CSIG
	unsigned char tmpval[2];
	
	tmpval[0] = val & 0xFF;
	tmpval[1] = (val >> 8) & 0xFF;
	
	GD25Q_SPIFLASH_WriteBuffer(tmpval, WriteAddr, 2);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_SetWord(u32 WriteAddr, unsigned int val)
 @Description			GD25Q_SPIFLASH_SetWord						: GD25Q SPIFLASH 寫入4個Byte
 @Input				val
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_SetWord(u32 WriteAddr, unsigned int val)
{
#ifdef GD25Q_80CSIG
	unsigned char tmpval[4];
	
	tmpval[0] = val & 0xFF;
	tmpval[1] = (val >> 8) & 0xFF;
	tmpval[2] = (val >> 16) & 0xFF;
	tmpval[3] = (val >> 24) & 0xFF;
	
	GD25Q_SPIFLASH_WriteBuffer(tmpval, WriteAddr, 4);
#endif
}

/**********************************************************************************************************
 @Function			unsigned int GD25Q_SPIFLASH_GetNumofByte(u32 ReadAddr, u16 AllNum, u8 ByteVal)
 @Description			GD25Q_SPIFLASH_GetNumofByte					: GD25Q SPIFLASH 讀取指定地址中指定位元組中有該值的個數
 @Input				ReadAddr									: 讀取地址
					AllNum									: 讀取位元組數
					ByteVal									: 匹配值
 @Return				val
**********************************************************************************************************/
unsigned int GD25Q_SPIFLASH_GetNumofByte(u32 ReadAddr, u16 AllNum, u8 ByteVal)
{
#ifdef GD25Q_80CSIG
	unsigned int ReadByteval = 0;
	
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return 0;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 傳送讀指令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReadData);
	
	/* 傳送讀地址高位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
	
	/* 傳送讀地址中位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);
	
	/* 傳送讀地址低位 */
	GD25Q_SPI_FLASH_SendByte(ReadAddr & 0xFF);
	
	/* 讀取資料 */
	while (AllNum--) {
		if (ByteVal == GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte)) {
			ReadByteval++;
		}
	}
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return ReadByteval;
#endif
}

/********************************************** END OF FLEE **********************************************/
#ifndef __HAL_SPI_FLASH_H
#define   __HAL_SPI_FLASH_H

#include "sys.h"

#define GD25Q80CSIGDeviceID						0x13
#define GD25Q80CSIGManufactureID					0xC813
#define GD25Q80CSIGIdentificationID				0xC84014

#define GD25Q40BSIGDeviceID						0x12
#define GD25Q40BSIGManufactureID					0xC812
#define GD25Q40BSIGIdentificationID				0xC84013

#define GD25Q80_BASE_ADDR						0x000000U
#define GD25Q80_CHIP_BYTE_SIZE					0x100000U													// 1 M
#define GD25Q80_BLOCK_BYTE_SIZE					0x010000U													//64 K
#define GD25Q80_SECTOR_BYTE_SIZE					0x001000U													// 4 K
#define GD25Q80_PAGE_BYTE_SIZE					0x000100U													//256Byte

#define GD25Q80_BLOCK_ADDRESS0					0x000000U
#define GD25Q80_BLOCK_ADDRESS1					0x010000U
#define GD25Q80_BLOCK_ADDRESS2					0x020000U
#define GD25Q80_BLOCK_ADDRESS3					0x030000U
#define GD25Q80_BLOCK_ADDRESS4					0x040000U
#define GD25Q80_BLOCK_ADDRESS5					0x050000U
#define GD25Q80_BLOCK_ADDRESS6					0x060000U
#define GD25Q80_BLOCK_ADDRESS7					0x070000U
#define GD25Q80_BLOCK_ADDRESS8					0x080000U
#define GD25Q80_BLOCK_ADDRESS9					0x090000U
#define GD25Q80_BLOCK_ADDRESS10					0x0A0000U
#define GD25Q80_BLOCK_ADDRESS11					0x0B0000U
#define GD25Q80_BLOCK_ADDRESS12					0x0C0000U
#define GD25Q80_BLOCK_ADDRESS13					0x0D0000U
#define GD25Q80_BLOCK_ADDRESS14					0x0E0000U
#define GD25Q80_BLOCK_ADDRESS15					0x0F0000U

#define GD25Q80_SECTOR_ADDRESS(nSector)				(GD25Q80_BASE_ADDR + (GD25Q80_SECTOR_BYTE_SIZE * nSector))
#define GD25Q80_PAGE_ADDRESS(nPage)				(GD25Q80_BASE_ADDR + (GD25Q80_PAGE_BYTE_SIZE * nPage))

#define GD25Q80_SECTOR_NUM						256
#define GD25Q80_PAGE_NUM							4096

#define APP_PACKSLICE_NUM						300														//升級APP分片最大分片數

/* APP1 FLASH ADDRESS TABLE */
#define APP1_BASE_ADDR							0x000000U
#define APP1_BYTE_SIZE							0x040000U
#define APP1_INFORMATION_ADDR						APP1_BASE_ADDR
#define APP1_INFORMATION_SIZE						0x1000
#define APP1_DATA_ADDR							APP1_BASE_ADDR + APP1_INFORMATION_SIZE
#define APP1_DATA_SIZE							APP1_BYTE_SIZE - APP1_INFORMATION_SIZE
#define APP1_INFO_UPGRADE_STATUS_OFFSET				APP1_INFORMATION_ADDR
#define APP1_INFO_UPGRADE_STATUS_LENGTH				1														//升級標誌 高4位0x5(0101)有升級包 低4位0x5(0101)可升級
#define APP1_INFO_UPGRADE_BASEADDR_OFFSET			APP1_INFO_UPGRADE_STATUS_OFFSET + APP1_INFO_UPGRADE_STATUS_LENGTH
#define APP1_INFO_UPGRADE_BASEADDR_LENGTH			4														//升級APP起始地址
#define APP1_INFO_UPGRADE_BLOCKNUM_OFFSET			APP1_INFO_UPGRADE_BASEADDR_OFFSET + APP1_INFO_UPGRADE_BASEADDR_LENGTH
#define APP1_INFO_UPGRADE_BLOCKNUM_LENGTH			2														//升級APP存放塊數
#define APP1_INFO_UPGRADE_BLOCKLEN_OFFSET			APP1_INFO_UPGRADE_BLOCKNUM_OFFSET + APP1_INFO_UPGRADE_BLOCKNUM_LENGTH
#define APP1_INFO_UPGRADE_BLOCKLEN_LENGTH			2														//升級APP塊長度
#define APP1_INFO_UPGRADE_DATALEN_OFFSET			APP1_INFO_UPGRADE_BLOCKLEN_OFFSET + APP1_INFO_UPGRADE_BLOCKLEN_LENGTH
#define APP1_INFO_UPGRADE_DATALEN_LENGTH			2														//升級APP塊有效長度
#define APP1_INFO_UPGRADE_INDEX_OFFSET				APP1_INFO_UPGRADE_DATALEN_OFFSET + APP1_INFO_UPGRADE_DATALEN_LENGTH
#define APP1_INFO_UPGRADE_INDEX_LENGTH				4														//升級APP序號
#define APP1_INFO_UPGRADE_SOFTVER_OFFSET			APP1_INFO_UPGRADE_INDEX_OFFSET + APP1_INFO_UPGRADE_INDEX_LENGTH
#define APP1_INFO_UPGRADE_SOFTVER_LENGTH			4														//升級包版本號 高2位元組主版本號 低2位元組從版本號
#define APP1_INFO_DOWNLOAD_TIME_OFFSET				APP1_INFO_UPGRADE_SOFTVER_OFFSET + APP1_INFO_UPGRADE_SOFTVER_LENGTH
#define APP1_INFO_DOWNLOAD_TIME_LENGTH				4														//升級包下載時間
#define APP1_DATA_CHECK_CODE_OFFSET				APP1_INFO_DOWNLOAD_TIME_OFFSET + APP1_INFO_DOWNLOAD_TIME_LENGTH
#define APP1_DATA_CHECK_CODE_LENGTH				4														//升級包校驗碼
#define APP1_PACKSLICE_STATUS_OFFSET				APP1_DATA_CHECK_CODE_OFFSET + APP1_DATA_CHECK_CODE_LENGTH
#define APP1_PACKSLICE_STATUS_LENGTH				APP_PACKSLICE_NUM											//升級包分片下載狀態(0x00有 0xFF無)
/* END APP1 ADDRESS TABLE */

/* APP2 FLASH ADDRESS TABLE */
#define APP2_BASE_ADDR							0x040000U
#define APP2_BYTE_SIZE							0x040000U
#define APP2_INFORMATION_ADDR						APP2_BASE_ADDR
#define APP2_INFORMATION_SIZE						0x1000
#define APP2_DATA_ADDR							APP2_BASE_ADDR + APP2_INFORMATION_SIZE
#define APP2_DATA_SIZE							APP2_BYTE_SIZE - APP2_INFORMATION_SIZE
#define APP2_INFO_UPGRADE_STATUS_OFFSET				APP2_INFORMATION_ADDR
#define APP2_INFO_UPGRADE_STATUS_LENGTH				1														//升級標誌 高4位0x5(0101)有升級包 低4位0x5(0101)可升級
#define APP2_INFO_UPGRADE_BASEADDR_OFFSET			APP2_INFO_UPGRADE_STATUS_OFFSET + APP2_INFO_UPGRADE_STATUS_LENGTH
#define APP2_INFO_UPGRADE_BASEADDR_LENGTH			4														//升級APP起始地址
#define APP2_INFO_UPGRADE_BLOCKNUM_OFFSET			APP2_INFO_UPGRADE_BASEADDR_OFFSET + APP2_INFO_UPGRADE_BASEADDR_LENGTH
#define APP2_INFO_UPGRADE_BLOCKNUM_LENGTH			2														//升級APP存放塊數
#define APP2_INFO_UPGRADE_BLOCKLEN_OFFSET			APP2_INFO_UPGRADE_BLOCKNUM_OFFSET + APP2_INFO_UPGRADE_BLOCKNUM_LENGTH
#define APP2_INFO_UPGRADE_BLOCKLEN_LENGTH			2														//升級APP塊長度
#define APP2_INFO_UPGRADE_DATALEN_OFFSET			APP2_INFO_UPGRADE_BLOCKLEN_OFFSET + APP2_INFO_UPGRADE_BLOCKLEN_LENGTH
#define APP2_INFO_UPGRADE_DATALEN_LENGTH			2														//升級APP塊有效長度
#define APP2_INFO_UPGRADE_INDEX_OFFSET				APP2_INFO_UPGRADE_DATALEN_OFFSET + APP2_INFO_UPGRADE_DATALEN_LENGTH
#define APP2_INFO_UPGRADE_INDEX_LENGTH				4														//升級APP序號
#define APP2_INFO_UPGRADE_SOFTVER_OFFSET			APP2_INFO_UPGRADE_INDEX_OFFSET + APP2_INFO_UPGRADE_INDEX_LENGTH
#define APP2_INFO_UPGRADE_SOFTVER_LENGTH			4														//升級包版本號 高2位元組主版本號 低2位元組從版本號
#define APP2_INFO_DOWNLOAD_TIME_OFFSET				APP2_INFO_UPGRADE_SOFTVER_OFFSET + APP2_INFO_UPGRADE_SOFTVER_LENGTH
#define APP2_INFO_DOWNLOAD_TIME_LENGTH				4														//升級包下載時間
#define APP2_DATA_CHECK_CODE_OFFSET				APP2_INFO_DOWNLOAD_TIME_OFFSET + APP2_INFO_DOWNLOAD_TIME_LENGTH
#define APP2_DATA_CHECK_CODE_LENGTH				4														//升級包校驗碼
#define APP2_PACKSLICE_STATUS_OFFSET				APP2_DATA_CHECK_CODE_OFFSET + APP2_DATA_CHECK_CODE_LENGTH
#define APP2_PACKSLICE_STATUS_LENGTH				APP_PACKSLICE_NUM											//升級包分片下載狀態(0x00有 0xFF無)
/* END APP2 ADDRESS TABLE */

/* Definition for SPIx clock resources */
#define GD25Q_FLASH_SPIx							SPI1
#define GD25Q_FLASH_SPIx_RCC_CLK_ENABLE()			__HAL_RCC_SPI1_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_RCC_CLK_DISABLE()			__HAL_RCC_SPI1_CLK_DISABLE()

#define GD25Q_FLASH_SPIx_FORCE_RESET()				__HAL_RCC_SPI1_FORCE_RESET()
#define GD25Q_FLASH_SPIx_RELEASE_RESET()			__HAL_RCC_SPI1_RELEASE_RESET()

/* Definition for SPIx GPIO resources */
#define GD25Q_FLASH_SPIx_NSS_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOB_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_NSS_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOB_CLK_DISABLE()
#define GD25Q_FLASH_SPIx_SCK_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOA_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_SCK_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOA_CLK_DISABLE()
#define GD25Q_FLASH_SPIx_MOSI_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOA_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_MOSI_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOA_CLK_DISABLE()
#define GD25Q_FLASH_SPIx_MISO_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOA_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_MISO_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOA_CLK_DISABLE()

/* Definition for SPIx Pins */
#define GD25Q_FLASH_SPIx_NSS_GPIO_PORT				GPIOB
#define GD25Q_FLASH_SPIx_NSS_PIN					GPIO_PIN_12
#define GD25Q_FLASH_SPIx_SCK_GPIO_PORT				GPIOA
#define GD25Q_FLASH_SPIx_SCK_PIN					GPIO_PIN_5
#define GD25Q_FLASH_SPIx_SCK_AF					GPIO_AF5_SPI1
#define GD25Q_FLASH_SPIx_MOSI_GPIO_PORT				GPIOA
#define GD25Q_FLASH_SPIx_MOSI_PIN					GPIO_PIN_7
#define GD25Q_FLASH_SPIx_MOSI_AF					GPIO_AF5_SPI1
#define GD25Q_FLASH_SPIx_MISO_GPIO_PORT				GPIOA
#define GD25Q_FLASH_SPIx_MISO_PIN					GPIO_PIN_6
#define GD25Q_FLASH_SPIx_MISO_AF					GPIO_AF5_SPI1

#define GD25Q_FLASH_SPIx_NSS_ENABLE()				HAL_GPIO_WritePin(GD25Q_FLASH_SPIx_NSS_GPIO_PORT, GD25Q_FLASH_SPIx_NSS_PIN, GPIO_PIN_RESET)
#define GD25Q_FLASH_SPIx_NSS_DISABLE()				HAL_GPIO_WritePin(GD25Q_FLASH_SPIx_NSS_GPIO_PORT, GD25Q_FLASH_SPIx_NSS_PIN, GPIO_PIN_SET)

#define GD25Q_Dummy_Byte							0xFF

/* GD25Q80CSIG 指令表 */
#define GD25Q_WriteEnable						0x06
#define GD25Q_WriteDisable						0x04

#define GD25Q_ReadStatusReg1						0x05
#define GD25Q_ReadStatusReg2						0x35
#define GD25Q_WriteStatusReg						0x01

#define GD25Q_ReadData							0x03
#define GD25Q_FastReadData						0x0B
#define GD25Q_FastReadDual						0x3B
#define GD25Q_PageProgram						0x02

#define GD25Q_SectorErase						0x20
#define GD25Q_BlockErase							0xD8
#define GD25Q_ChipErase							0xC7

#define GD25Q_PowerDown							0xB9
#define GD25Q_ReleasePowerDown					0xAB
#define GD25Q_DeviceID							0xAB
#define GD25Q_ManufactDeviceID					0x90
#define GD25Q_JedecDeviceID						0x9F
/* GD25Q80CSIG End Command */

typedef enum
{
	GD25Q80CSIG_OK								= 0x00,
	GD25Q80CSIG_ERROR							= 0x01
}GD25Q_StatusTypeDef;

extern SPI_HandleTypeDef GD25Q_SPIFLASH_Handler;
extern GD25Q_StatusTypeDef GD25QStatus;

void GD25Q_SPIFLASH_Init(void);														//GD25Q SPIFLASH 初始化
GD25Q_StatusTypeDef GD25Q_SPIFLASH_Get_Status(void);										//GD25Q SPIFLASH 狀態

u8 GD25Q_SPI_FLASH_ReadByte(void);														//SPI FLASH 讀取一個位元組資料
u8 GD25Q_SPI_FLASH_SendByte(u8 byte);													//SPI FLASH 傳送一個位元組資料

u32 GD25Q_SPIFLASH_ReadDeviceID(void);													//GD25Q SPIFLASH 讀取裝置ID
u32 GD25Q_SPIFLASH_ReadManufactureID(void);												//GD25Q SPIFLASH 讀取廠商ID
u32 GD25Q_SPIFLASH_ReadIdentificationID(void);											//GD25Q SPIFLASH 讀取型號ID

void GD25Q_SPIFLASH_WriteEnable(void);													//GD25Q SPIFLASH 寫使能
void GD25Q_SPIFLASH_WriteDisable(void);													//GD25Q SPIFLASH 寫禁止

u8 GD25Q_SPIFLASH_ReadStatusRegister(u8 statusRegister);									//GD25Q SPIFLASH 讀狀態暫存器
void GD25Q_SPIFLASH_WriteStatusRegister(u8 srLow, u8 srHigh);								//GD25Q SPIFLASH 寫狀態暫存器

void GD25Q_SPIFLASH_WaitForBusy(void);													//GD25Q SPIFLASH 等待裝置空閒
void GD25Q_SPIFLASH_PowerDown(void);													//GD25Q SPIFLASH 進入掉電模式
void GD25Q_SPIFLASH_WakeUp(void);														//GD25Q SPIFLASH 喚醒

void GD25Q_SPIFLASH_EraseChip(void);													//GD25Q SPIFLASH 擦除Chip
void GD25Q_SPIFLASH_EraseBlock(u32 BlockAddr);											//GD25Q SPIFLASH 擦除Block
void GD25Q_SPIFLASH_EraseSector(u32 SectorAddr);											//GD25Q SPIFLASH 擦除Sector

void GD25Q_SPIFLASH_ReadBuffer(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);					//GD25Q SPIFLASH 讀取SPI FLASH資料
void GD25Q_SPIFLASH_WritePage(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);					//GD25Q SPIFLASH 寫入SPI FLASH資料Page
void GD25Q_SPIFLASH_WriteBuffer(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);				//GD25Q SPIFLASH 寫入SPI FLASH資料

unsigned char GD25Q_SPIFLASH_GetByte(u32 ReadAddr);										//GD25Q SPIFLASH 讀取1個Byte
unsigned short GD25Q_SPIFLASH_GetHalfWord(u32 ReadAddr);									//GD25Q SPIFLASH 讀取2個Byte
unsigned int GD25Q_SPIFLASH_GetWord(u32 ReadAddr);										//GD25Q SPIFLASH 讀取4個Byte

void GD25Q_SPIFLASH_SetByte(u32 WriteAddr, unsigned char val);								//GD25Q SPIFLASH 寫入1個Byte
void GD25Q_SPIFLASH_SetHalfWord(u32 WriteAddr, unsigned short val);							//GD25Q SPIFLASH 寫入2個Byte
void GD25Q_SPIFLASH_SetWord(u32 WriteAddr, unsigned int val);								//GD25Q SPIFLASH 寫入4個Byte

unsigned int GD25Q_SPIFLASH_GetNumofByte(u32 ReadAddr, u16 AllNum, u8 ByteVal);					//GD25Q SPIFLASH 讀取指定地址中指定位元組中有該值的個數

#endif /* __HAL_SPI_FLASH_H */