#include "stdio.h" #include "w25qxx.h" #include "spi.h" #include "delay.h" #include "usart.h" ////////////////////////////////////////////////////////////////////////////////// //This program is for educational purposes only, without the author's permission, may not be used for any other purpose //ALIENTEK STM32F4 Explorer Board //W25QXX Driver code //Hot Atomic @ALIENTEK //Forum: www.openedv.com //Date modified: 2014/5/6 //Version: V1.0 //All rights reserved pirated reserved. //Copyright(C) Guangzhou wing electronic technology limited company 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// u16 W25QXX_TYPE = W25Q128; // The default is W25Q128 // 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) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // GPIOB clock //SPI_NSS - GPIOB12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // PB12 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // Output GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Push-pull output GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // Pull-up GPIO_Init(GPIOB, &GPIO_InitStructure); // Initialize W25QXX_CS = 1; // SPI FLASH is not selected SPI2_Init(); // Initialize the SPI SPI2_SetSpeed(SPI_BaudRatePrescaler_2); // Set to 42M clock high-speed mode 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 u8 W25QXX_ReadSR(void) { u8 byte = 0; W25QXX_CS = 0; // Enabling devices SPI2_ReadWriteByte(W25X_ReadStatusReg); // Sends a read status register command byte = SPI2_ReadWriteByte(0Xff); // Read a byte W25QXX_CS = 1; // Cancel selected 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(u8 sr) { W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_WriteStatusReg); //Sending of taking the State register command SPI2_ReadWriteByte(sr); //Writes a byte W25QXX_CS=1; //Cancel selected } //W25QXX write enable //WEL is set void W25QXX_Write_Enable(void) { W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_WriteEnable); //Send written W25QXX_CS=1; //Cancel selected } //W25QXX write protect //WEL reset void W25QXX_Write_Disable(void) { W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_WriteDisable); //Send written W25QXX_CS=1; //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 u16 W25QXX_ReadID(void) { u16 Temp = 0; W25QXX_CS=0; SPI2_ReadWriteByte(0x90);//Send the read ID command SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0x00); SPI2_ReadWriteByte(0x00); Temp|=SPI2_ReadWriteByte(0xFF)<<8; Temp|=SPI2_ReadWriteByte(0xFF); W25QXX_CS=1; 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(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) { u16 i; W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_ReadData); //Send read commands SPI2_ReadWriteByte((u8)((ReadAddr)>>16)); //Send 24bit SPI2_ReadWriteByte((u8)((ReadAddr)>>8)); SPI2_ReadWriteByte((u8)ReadAddr); for(i=0;i>16)); //Send 24bit SPI2_ReadWriteByte((u8)((WriteAddr)>>8)); SPI2_ReadWriteByte((u8)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) u8 W25QXX_BUFFER[4096]; void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) { u32 secpos; u16 secoff; u16 secremain; u16 i; u8 * 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) { 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(); W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_ChipErase); //Send erase command W25QXX_CS=1; //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(u32 Dst_Addr) { //Monitor Falsh erasure, testing // printf("fe:%x\r\n",Dst_Addr); Dst_Addr*=4096; W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_SectorErase); //Send sector erase command SPI2_ReadWriteByte((u8)((Dst_Addr)>>16)); //Send 24bit SPI2_ReadWriteByte((u8)((Dst_Addr)>>8)); SPI2_ReadWriteByte((u8)Dst_Addr); W25QXX_CS=1; //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) { W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_PowerDown); //Send the power command W25QXX_CS=1; //Cancel selected delay_us(3); //Wait for the TPD } //Wake up void W25QXX_WAKEUP(void) { W25QXX_CS=0; //Enabling devices SPI2_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB W25QXX_CS=1; //Cancel selected delay_us(3); //Waiting for TRES1 }