/******************************************************************************* * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved. * @file w25qxx.c * @author UartTFT Application Team * @version V1.0.0 * @date 2023-02-24 * @brief Nor Flash Library Functions ********************************************************************************/ #include "w25qxx.h" uint8_t W25Q256 = 0; /******************************************************************************** * Function Name : LT_W25qxx_ReadSR * Description : Read the value of the register. * Input : - SRx:Register address - 3 status registers - W25X_READ_SR1: address 0x05 BIT 7 6 5 4 3 2 1 0 SPR RV TB BP2 BP1 BP0 WEL BUSY - W25X_READ_SR2: address 0x35 - W25X_READ_SR3: address 0x15 * Output : None * Return : None *********************************************************************************/ uint8_t LT_W25qxx_ReadSR(void) { uint8_t byte = 0; nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_ReadStatusReg); byte = SPI_Master_FIFO_Data_Put(0Xff); nSS_Inactive(); return byte; } /******************************************************************************** * Function Name : LT_W25qxx_Write_Enable * Description : Write Enable(set WEL to 1). * Input : None * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_Write_Enable(void) { nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_WriteEnable); nSS_Inactive(); } /******************************************************************************** * Function Name : LT_W25QXX_Write_Disable * Description : Write Disable * Input : None * Output : None * Return : None *********************************************************************************/ void LT_W25QXX_Write_Disable(void) { nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_WriteDisable); nSS_Inactive(); } /******************************************************************************** * Function Name : LT_W25qxx_Wait_Busy * Description : Wait for BUSY bit to clear. * Input : None * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_Wait_Busy(void) { while ((LT_W25qxx_ReadSR() & 0x01) == 0x01) ; } /******************************************************************************** * Function Name : LT_W25qxx_ReadID * Description : Read W25qxx ID. * Input : None * Output : None * Return : Flash ID *********************************************************************************/ uint16_t LT_W25qxx_ReadID(void) { uint16_t Temp = 0; nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_ManufactDeviceID); SPI_Master_FIFO_Data_Put(0x00); SPI_Master_FIFO_Data_Put(0x00); SPI_Master_FIFO_Data_Put(0x00); Temp |= SPI_Master_FIFO_Data_Put(0xFF) << 8; Temp |= SPI_Master_FIFO_Data_Put(0xFF); nSS_Inactive(); return Temp; } /******************************************************************************** * Function Name : LT_W25qxx_Read * Description : Read data of specified length from the specified address. * Input : - pBuffer: buffer for save data - ReadAddr: Start address of reading data - NumByteToRead: number bytes to read * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) { uint16_t i; nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_ReadData); if (W25Q256) SPI_Master_FIFO_Data_Put((uint8_t)((ReadAddr) >> 24)); SPI_Master_FIFO_Data_Put((uint8_t)((ReadAddr) >> 16)); SPI_Master_FIFO_Data_Put((uint8_t)((ReadAddr) >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)ReadAddr); for (i = 0; i < NumByteToRead; i++) { pBuffer[i] = SPI_Master_FIFO_Data_Put(0XFF); } nSS_Inactive(); } /******************************************************************************** * Function Name : LT_W25QXX_Write_Page * Description : On a page, write data of specified length at the specified address. * Input : - pBuffer: data start address - WriteAddr: Start address of writing data - NumByteToWrite: number bytes to write(max one page:256 bytes) * Output : None * Return : None *********************************************************************************/ void LT_W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint16_t i; LT_W25qxx_Write_Enable(); nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_PageProgram); if (W25Q256) SPI_Master_FIFO_Data_Put((uint8_t)((WriteAddr) >> 24)); SPI_Master_FIFO_Data_Put((uint8_t)((WriteAddr) >> 16)); SPI_Master_FIFO_Data_Put((uint8_t)((WriteAddr) >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)WriteAddr); LCD_CmdWrite(0xB8); SS_RESET; SPI2_ReadWriteByte(0x80); for (i = 0; i < NumByteToWrite; i++) { SPI2_ReadWriteByte(pBuffer[i]); } SS_SET; nSS_Inactive(); LT_W25qxx_Wait_Busy(); } /******************************************************************************** * Function Name : LT_W25qxx_Write * Description : Write SPI FLASH without inspection. You must ensure that all the data written in the address range is 0XFF, otherwise the data written in non-0XFF will fail. With auto-feed function * Input : - LT_W25qxx_Write: data start address - WriteAddr: Start address of writing data - NumByteToWrite: number bytes to write(max 0xFFFF bytes) * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint16_t pageremain; pageremain = 256 - WriteAddr % 256; if (NumByteToWrite <= pageremain) pageremain = NumByteToWrite; while (1) { LT_W25QXX_Write_Page(pBuffer, WriteAddr, pageremain); if (NumByteToWrite == pageremain) break; else { pBuffer += pageremain; WriteAddr += pageremain; NumByteToWrite -= pageremain; if (NumByteToWrite > 256) pageremain = 256; else pageremain = NumByteToWrite; } } } /******************************************************************************** * Function Name : LT_W25qxx_Erase_Chip * Description : Full Erase. * Input : None * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_Erase_Chip(void) { LT_W25qxx_Write_Enable(); LT_W25qxx_Wait_Busy(); nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_ChipErase); nSS_Inactive(); LT_W25qxx_Wait_Busy(); } /******************************************************************************** * Function Name : LT_W25qxx_Erase_Sector * Description : Erase a sector (4*1024 bytes). * Input : - addr:sector address * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_Erase_Sector(uint32_t Dst_Addr) { Dst_Addr *= 4096; LT_W25qxx_Write_Enable(); LT_W25qxx_Wait_Busy(); nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_SectorErase); if (W25Q256) SPI_Master_FIFO_Data_Put((uint8_t)((Dst_Addr) >> 24)); SPI_Master_FIFO_Data_Put((uint8_t)((Dst_Addr) >> 16)); SPI_Master_FIFO_Data_Put((uint8_t)((Dst_Addr) >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)Dst_Addr); nSS_Inactive(); LT_W25qxx_Wait_Busy(); } /******************************************************************************** * Function Name : LT_W25qxx_BlockErase64KB * Description : Erase a block (64*1024 bytes). * Input : - addr:block address * Output : None * Return : None *********************************************************************************/ void LT_W25qxx_BlockErase64KB(uint32_t addr) { addr *= 65536; LT_W25qxx_Write_Enable(); LT_W25qxx_Wait_Busy(); nSS_Active(); SPI_Master_FIFO_Data_Put(W25X_BlockErase); if (W25Q256) SPI_Master_FIFO_Data_Put((uint8_t)((addr) >> 24)); SPI_Master_FIFO_Data_Put((uint8_t)((addr) >> 16)); SPI_Master_FIFO_Data_Put((uint8_t)((addr) >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)addr); nSS_Inactive(); LT_W25qxx_Wait_Busy(); } void LT_W25QXX_Enter_4Byte_AddressMode(void) { nSS_Active(); SPI_Master_FIFO_Data_Put(0xB7); nSS_Inactive(); }