基於Stm32硬體SPI控制GD25QFlash
阿新 • • 發佈:2018-12-14
/** ********************************************************************************************************* * @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 */