/** ****************************************************************************** * File Name : w25qxx.c * Description : This file provides code for the configuration * of w25qxx configuration. ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stdio.h" #include "spi.h" #include "w25qxx.h" #include "delay.h" #include "usart.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ uint16_t W25QXX_TYPE = W25Q128; // The default is W25Q128 uint8_t W25QXX_BUFFER[4096]; /* Private function prototypes -----------------------------------------------*/ en_result_t SpiFlash_WaitForWriteEnd(void); /* Private functions ---------------------------------------------------------*/ // 4Kbytes to a Sector // 16 slices for 1 Block // W25Q40 : Capacity of 512K bytes, and a total of 16 Block, 128 Sector // W25Q128: Capacity of 16M bytes, and a total of 128 Block, 4096 Sector //Initializes IO port SPI FLASH void W25QXX_Init(void) { stc_port_init_t stcPortInit; /* configure structure initialization */ MEM_ZERO_STRUCT(stcPortInit); stcPortInit.enPinMode = Pin_Mode_Out; PORT_Init(SPI3_NSS_PORT, SPI3_NSS_PIN, &stcPortInit); SPI3_NSS_HIGH(); Spi3_Config(); W25QXX_TYPE = W25QXX_ReadID(); // Read FLASH ID. } // The status register read W25QXX // BIT7 6 5 4 3 2 1 0 // SPR RV TB BP2 BP1 BP0 WEL BUSY // SPR:Default 0, the State Register protection, used with WP // TB,BP2,BP1,BP0:FLASH write-protect setting // WEL: write lock // BUSY: busy flag bits (1, busy; 0, idle) // Default:0x00 uint8_t W25QXX_ReadSR(void) { uint8_t byte = 0; SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_ReadStatusReg); // Sends a read status register command byte = Spi3Flash_WriteReadByte(FLASH_DUMMY_BYTE_VALUE); // Read a byte while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)); SPI3_NSS_HIGH(); return byte; } // Write W25QXX status register // Only the SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)You can write!!! void W25QXX_Write_SR(uint8_t sr) { SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_WriteStatusReg); // Sending of taking the State register command Spi3Flash_WriteReadByte(sr); // Writes a byte while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)); SPI3_NSS_HIGH(); W25QXX_Wait_Busy(); //Waiting to be written to the end } //W25QXX write enable //WEL is set void W25QXX_Write_Enable(void) { SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_WriteEnable); // Send written while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)); SPI3_NSS_HIGH(); // Cancel selected } //W25QXX write protect //WEL reset void W25QXX_Write_Disable(void) { SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_WriteDisable); // Send written while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)); SPI3_NSS_HIGH(); // Cancel selected } //Read the chip ID //Return values are as follows: //0XEF13,Chip and the model is W25Q80 //0XEF14,Chip and the model is W25Q16 //0XEF15,Chip and the model is W25Q32 //0XEF16,Chip and the model is W25Q64 //0XEF17,Chip and the model is W25Q128 uint16_t W25QXX_ReadID(void) { uint16_t Temp = 0; SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(0x90);//Send the read ID command Spi3Flash_WriteReadByte(0x00); Spi3Flash_WriteReadByte(0x00); Spi3Flash_WriteReadByte(0x00); Temp|=Spi3Flash_WriteReadByte(0xFF)<<8; Temp|=Spi3Flash_WriteReadByte(0xFF); while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)) { } SPI3_NSS_HIGH(); return Temp; } //Read SPI FLASH //Starting at the specified address reads the specified length of data //pBuffer:The data store //ReadAddr:Read start address(24bit) //NumByteToRead:Number of bytes to read(Max 65535) void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead) { uint16_t i; SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_ReadData); //Send read commands Spi3Flash_WriteReadByte((uint8_t)((ReadAddr)>>16)); //Send 24bit Spi3Flash_WriteReadByte((uint8_t)((ReadAddr)>>8)); Spi3Flash_WriteReadByte((uint8_t)ReadAddr); for(i=0;i>16)); //Send 24bit Spi3Flash_WriteReadByte((uint8_t)((WriteAddr)>>8)); Spi3Flash_WriteReadByte((uint8_t)WriteAddr); for(i=0;ipageremain { pBuffer+=pageremain; WriteAddr+=pageremain; NumByteToWrite-=pageremain; //Minus has written a number of bytes if(NumByteToWrite>256)pageremain=256; //Once you can write to 256 bytes else pageremain=NumByteToWrite; //Less than 256 bytes } }; } //Write SPI FLASH //Starting at the specified address to write to the specified length of data //This function erases the operation! //pBuffer:The data store //WriteAddr:Start write address(24bit) //NumByteToWrite:Number of bytes to write(Max 65535) void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite) { uint32_t secpos; uint16_t secoff; uint16_t secremain; uint16_t i; uint8_t * W25QXX_BUF; W25QXX_BUF=W25QXX_BUFFER; secpos=WriteAddr/4096;//Sector address secoff=WriteAddr%4096;//In the sector of migration secremain=4096-secoff;//Slice the remaining space //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//Testing if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//Not greater than 4,096 bytes while(1) { WDT_RefreshCounter(); W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//Read out the contents of an entire sector for(i=0;i4096)secremain=4096; //Next sector but still not finished else secremain=NumByteToWrite; //Next slice to finish } }; } //Erase the entire chip //Wait for long... void W25QXX_Erase_Chip(void) { W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_ChipErase); //Send erase command SPI3_NSS_HIGH(); //Cancel selected W25QXX_Wait_Busy(); //Wait for end of the chip erase } //Erase one sector //Dst_Addr:Sector address set according to actual capacity //Erasing a mountain at least time: 150ms void W25QXX_Erase_Sector(uint32_t Dst_Addr) { //Monitor Falsh erasure, testing // printf("fe:%x\r\n",Dst_Addr); Dst_Addr*=4096; W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_SectorErase); //Send sector erase command Spi3Flash_WriteReadByte((uint8_t)((Dst_Addr)>>16)); //Send 24bit Spi3Flash_WriteReadByte((uint8_t)((Dst_Addr)>>8)); Spi3Flash_WriteReadByte((uint8_t)Dst_Addr); SPI3_NSS_HIGH(); //Cancel selected W25QXX_Wait_Busy(); //Wait for the erase to complete } //Waiting for a free void W25QXX_Wait_Busy(void) { while((W25QXX_ReadSR() & 0x01) == 0x01); // Wait for the BUSY emptying } //Enter the power off mode void W25QXX_PowerDown(void) { SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_PowerDown); //Send the power command SPI3_NSS_HIGH(); //Cancel selected delay_us(3); //Wait for the TPD } //Wake up void W25QXX_WAKEUP(void) { SPI3_NSS_LOW(); // Enabling devices Spi3Flash_WriteReadByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB SPI3_NSS_HIGH(); //Cancel selected delay_us(3); //Waiting for TRES1 } /** ******************************************************************************* ** \brief SPI flash wait for write operation end function ** ** \param [in] None ** ** \retval Ok Flash internal operation finish ** \retval ErrorTimeout Flash internal operation timeout ** ******************************************************************************/ en_result_t SpiFlash_WaitForWriteEnd(void) { en_result_t enRet = Ok; uint8_t u8Status = 0u; uint32_t u32Timeout; stc_clk_freq_t stcClkFreq; CLK_GetClockFreq(&stcClkFreq); u32Timeout = stcClkFreq.sysclkFreq / 1000u; SPI3_NSS_LOW(); Spi3Flash_WriteReadByte(FLASH_INSTR_READ_SR1); do { u8Status = Spi3Flash_WriteReadByte(FLASH_DUMMY_BYTE_VALUE); u32Timeout--; } while ((u32Timeout != 0ul) && ((u8Status & FLASH_BUSY_BIT_MASK) == FLASH_BUSY_BIT_MASK)); if (FLASH_BUSY_BIT_MASK == u8Status) { enRet = ErrorTimeout; } while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle)) { } SPI3_NSS_HIGH(); return enRet; } /*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/