/******************************************************************************* * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved. * @file w25n01.c * @author UartTFT Application Team * @version V1.0.0 * @date 2023-02-24 * @brief Nand Flash Library Functions ********************************************************************************/ #include "w25n01.h" #include "LT768.h" #include "LT768_Lib.h" #include "dmac_drv.h" #include "if_port.h" /******************************************************************************** * Function Name : W25N01GV_ReadID * Description : Read W25N01GV ID. * Input : None * Output : None * Return : Flash ID *********************************************************************************/ uint32_t W25N01GV_ReadID(void) { uint8_t Mfr_id = 0; uint8_t Device_idL = 0; uint8_t Device_idH = 0; uint32_t id = 0; nSS_Active(); SPI_Master_FIFO_Data_Put(0x9f); SPI_Master_FIFO_Data_Put(0xff); Mfr_id = SPI_Master_FIFO_Data_Put(0xff); Device_idH = SPI_Master_FIFO_Data_Put(0xff); Device_idL = SPI_Master_FIFO_Data_Put(0xff); nSS_Inactive(); id = Mfr_id; id = (id << 8) + Device_idH; id = (id << 8) + Device_idL; return id; } /******************************************************************************** * Function Name : W25N01GV_Write_Enable * Description : Enable to write. * Input : None * Output : None * Return : None *********************************************************************************/ void W25N01GV_Write_Enable(void) { nSS_Active(); SPI_Master_FIFO_Data_Put(W25N01GV_WriteEnable); nSS_Inactive(); } /******************************************************************************** * Function Name : W25N01GV_Write_Disable * Description : Disable to write. * Input : None * Output : None * Return : None *********************************************************************************/ void W25N01GV_Write_Disable(void) { nSS_Active(); SPI_Master_FIFO_Data_Put(W25N01GV_WriteDisable); nSS_Inactive(); } /******************************************************************************** * Function Name : W25N01GV_Write_SR * Description : Write the value of the register. * Input : - SRx:Register address - 3 status registers - Protection register 1: address 0xA0 - Configuration register 2: address 0xB0 - Status register 3: address 0xC0 (Read Only) * Output : None * Return : None *********************************************************************************/ void W25N01GV_Write_SR(uint8_t reg, uint8_t val) { nSS_Active(); // Enable SPI_Master_FIFO_Data_Put(W25N01GV_WriteStatusReg); // Send write status register command SPI_Master_FIFO_Data_Put(reg); // Register address SPI_Master_FIFO_Data_Put(val); // Write a byte nSS_Inactive(); // Disable } /******************************************************************************** * Function Name : W25N01GV_ReadSR * Description : Read the value of the register. * Input : - SRx:Register address - 3 status registers - Protection register 1: address 0xA0 - Configuration register 2: address 0xB0 - Status register 3: address 0xC0 (Read Only) * Output : None * Return : None *********************************************************************************/ uint8_t W25N01GV_ReadSR(uint8_t reg) { uint8_t byte = 0; nSS_Active(); // Enable SPI_Master_FIFO_Data_Put(W25N01GV_ReadStatusReg); // Send read status register command SPI_Master_FIFO_Data_Put(reg); // Register address byte = SPI_Master_FIFO_Data_Put(0Xff); // Read a byte nSS_Inactive(); // Disable return byte; } /******************************************************************************** * Function Name : W25N01GV_Wait_Busy * Description : Wait for BUSY bit to clear. * Input : None * Output : None * Return : None *********************************************************************************/ void W25N01GV_Wait_Busy(void) { while ((W25N01GV_ReadSR(0xC0) & 0x01) == 0x01) ; // Wait for BUSY bit to clear } /******************************************************************************** * Function Name : W25N01GV_Erase_Block * Description : W25N01 block erase(128K) * Input : block : block num * Output : None * Return : None *********************************************************************************/ void W25N01GV_Erase_Block(uint16_t block) { uint16_t addr = 0; addr = 64 * block; W25N01GV_Write_SR(0xa0, 0x00); // Turn off flash protection function W25N01GV_Write_Enable(); // SET WEL W25N01GV_Wait_Busy(); nSS_Active(); // Enable SPI_Master_FIFO_Data_Put(0xD8); // Send chip erase command SPI_Master_FIFO_Data_Put(0xff); // Send chip erase command SPI_Master_FIFO_Data_Put((uint8_t)(addr >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)(addr)); nSS_Inactive(); // Disable W25N01GV_Wait_Busy(); // Wait for chip erase to finish W25N01GV_Write_SR(0xa0, 0x7c); // Turn on flash protection function } /******************************************************************************** * Function Name : LT_W25N01GV_STD_Write_Page_DMA * Description : Write data at the specified address of W25N01 * Input : - pBuffer: data start address - PageNum: page - PageAddr: Page address - NumByteToWrite: number bytes to write(max one page:2048 bytes) * Output : None * Return : None *********************************************************************************/ void W25N01GV_WritePageAddr_Data(uint8_t *pBuffer, uint32_t PageNum, uint32_t PageAddr, uint16_t NumByteToWrite) { uint16_t i; // W25N01GV_Erase_Block(WriteAddr); W25N01GV_Write_SR(0xa0, 0x00); // Turn off flash protection function //------дBUFF------ W25N01GV_Write_Enable(); // SET WEL nSS_Active(); // Enabling device SPI_Master_FIFO_Data_Put(0x02); // Send the write BUFF command SPI_Master_FIFO_Data_Put((PageAddr) >> 8); // BUFF address SPI_Master_FIFO_Data_Put(PageAddr); LCD_CmdWrite(0xB8); SS_RESET; SPI2_ReadWriteByte(0x80); for (i = 0; i < NumByteToWrite; i++) SPI2_ReadWriteByte(pBuffer[i]); // Number of cyclic writes SS_SET; nSS_Inactive(); // Cancel film selection W25N01GV_Wait_Busy(); // Wait for writing to end //-------BUFF data writing flash-------- W25N01GV_Write_Enable(); nSS_Active(); SPI_Master_FIFO_Data_Put(0x10); // Send page write command SPI_Master_FIFO_Data_Put(0xff); // Send 16it address SPI_Master_FIFO_Data_Put((uint8_t)((PageNum) >> 8)); // Send 16it address SPI_Master_FIFO_Data_Put((uint8_t)(PageNum)); nSS_Inactive(); W25N01GV_Wait_Busy(); // Wait for writing to end W25N01GV_Write_SR(0xa0, 0x7c); // Turn on flash protection function } /******************************************************************************** * Function Name : W25N01GV_ReadPageAddr_Data * 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 W25N01GV_ReadPageAddr_Data(uint8_t *pBuffer, uint32_t PageNum, uint32_t PageAddr, uint16_t NumByteToRead) { uint16_t i; nSS_Active(); SPI_Master_FIFO_Data_Put(0x13); SPI_Master_FIFO_Data_Put(0x00); SPI_Master_FIFO_Data_Put((uint8_t)((PageNum) >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)(PageNum)); nSS_Inactive(); W25N01GV_Wait_Busy(); W25N01GV_Write_SR(0xb0, W25N01GV_ReadSR(0xb0) | 0x08); nSS_Active(); SPI_Master_FIFO_Data_Put(0x03); SPI_Master_FIFO_Data_Put((PageAddr) >> 8); SPI_Master_FIFO_Data_Put(PageAddr); SPI_Master_FIFO_Data_Put(0x00); SPI_CmdWrite(0xB8); for (i = 0; i < NumByteToRead; i++) { SPI_DataWrite(0xFF); pBuffer[i] = SPI_DataRead(); } nSS_Active(); //--------------------- LT768_SPI_Init(1, 1); W25N01GV_Wait_Busy(); } /******************************************************************************** * Function Name : W25N01GV_ReadPageAddr_Data * 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_W25N01_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) { uint16_t i; uint16_t page, endpage, remainder; remainder = ReadAddr % 2048; page = (ReadAddr / 2048); endpage = ((ReadAddr + NumByteToRead) / 2048); LT768_SPI_Init(1, 1); if (page == endpage) { W25N01GV_ReadPageAddr_Data(pBuffer, page, remainder, NumByteToRead); } else { W25N01GV_ReadPageAddr_Data(pBuffer, page, remainder, 2048 - remainder); for (i = 1; page + i < endpage; i++) { W25N01GV_ReadPageAddr_Data(&pBuffer[2048 * i - remainder], page + i, 0, 2048); } W25N01GV_ReadPageAddr_Data(&pBuffer[2048 * i - remainder], endpage, 0, NumByteToRead - (2048 * i - remainder)); } } void Write_Page(uint16_t page) { nSS_Active(); SPI_Master_FIFO_Data_Put(0x13); SPI_Master_FIFO_Data_Put(0x00); SPI_Master_FIFO_Data_Put((uint8_t)(page >> 8)); SPI_Master_FIFO_Data_Put((uint8_t)page); nSS_Inactive(); W25N01GV_Wait_Busy(); } // Configure BUF=1: continuous read mode void W25N01GV_ContinuousRead_Mode(void) { uint8_t statut = 0; statut = W25N01GV_ReadSR(0xb0); statut &= cClrb3; statut &= cClrb4; statut |= cSetb4; W25N01GV_Write_SR(0xb0, statut); } // Configure BUF=0: page reading mode void W25N01GV_PageRead_Mode(void) { uint8_t statut = 0; statut = W25N01GV_ReadSR(0xb0); statut |= cSetb3; statut |= cSetb4; W25N01GV_Write_SR(0xb0, statut); } void W25N01GV_BUF1Set(void) { uint8_t statut = 0; statut = W25N01GV_ReadSR(0xb0); statut |= cSetb3; statut &= cClrb4; // statut |= cSetb4; W25N01GV_Write_SR(0xb0, statut); }