Problems with custom external loader for W25Q16 spi flash.
Hello everyone, I've got custom-made board with STM32F407VE and W25Q16 SPI flash with TFT Display installed.
So I've decided to develop my own external loader for SPI flash for storing images in my TouchGFX project. I've managed to read data from flash with st-link utility and stm32cube programmer but encountered some problems.
- Somehow I can erase one sector at a time. But if I decide to erase multiple sectors, only the first sector in sequence will be erased. This works in st-link utility.
- In STM32CubeProgrammer, erase functions doesn't work at all, but I can read the data in memory.
And because of these issues I can't write data to flash, And I don't even know if write function will work, and I still need to figure out how to use it in TouchGFX project.
Edit: It turned out I'm able to erase one sector in stm32cubeprogrammer if I don't do anything except erasing after connecting. If I touch anything before erase command, It fails. Still can't erase multiple sectors at once.
Please help…
Here are my functions I found in st-link utility folder (stm32cubeprogrammer has the same source code).
The sector erase for external loader:
int SectorErase (uint32_t EraseStartAddress ,uint32_t EraseEndAddress)
{
EraseStartAddress &= 0x0FFFFFFF;
EraseEndAddress &= 0x0FFFFFFF;
__set_PRIMASK(0);
EraseStartAddress = EraseStartAddress - EraseStartAddress % w25qxx.SectorSize;
while (EraseEndAddress>=EraseStartAddress)
{
W25qxx_EraseSector(EraseStartAddress);
EraseStartAddress += w25qxx.SectorSize;
}
__set_PRIMASK(1); //enable interrupts
return 1;
}Erase sector funtion for spi flash
void W25qxx_EraseSector(uint32_t SectorAddr)
{
while(w25qxx.Lock==1)
W25qxx_Delay(1);
w25qxx.Lock=1;
#if (_W25QXX_DEBUG==1)
uint32_t StartTime=HAL_GetTick();
printf("w25qxx EraseSector %d Begin...\r\n",SectorAddr);
#endif
W25qxx_WaitForWriteEnd();
//SectorAddr = SectorAddr * w25qxx.SectorSize;
W25qxx_WriteEnable();
HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_RESET);
W25qxx_Spi(0x20);
if(w25qxx.ID>=W25Q256) W25qxx_Spi((SectorAddr & 0xFF000000) >> 24);
W25qxx_Spi((SectorAddr & 0xFF0000) >> 16);
W25qxx_Spi((SectorAddr & 0xFF00) >> 8);
W25qxx_Spi(SectorAddr & 0xFF);
HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_SET);
W25qxx_WaitForWriteEnd();
#if (_W25QXX_DEBUG==1)
printf("w25qxx EraseSector done after %d ms\r\n",HAL_GetTick()-StartTime);
#endif
W25qxx_Delay(1);
w25qxx.Lock=0;
}Write function for external loader:
int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)
{
W25qxx_WriteByte(buffer, Address, Size);
return 1;
}Write function flash
void W25qxx_WriteByte(uint8_t *pBuffer, uint32_t WriteAddr_inBytes, uint32_t ByteNum)
{
while(w25qxx.Lock==1)
W25qxx_Delay(1);
w25qxx.Lock=1;
#if (_W25QXX_DEBUG==1)
uint32_t StartTime=HAL_GetTick();
printf("w25qxx WriteByte 0x%02X at address %d begin...",pBuffer,WriteAddr_inBytes);
#endif
W25qxx_WaitForWriteEnd();
W25qxx_WriteEnable();
HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_RESET);
W25qxx_Spi(0x02);
if(w25qxx.ID>=W25Q256)
W25qxx_Spi((WriteAddr_inBytes & 0xFF000000) >> 24);
W25qxx_Spi((WriteAddr_inBytes & 0xFF0000) >> 16);
W25qxx_Spi((WriteAddr_inBytes & 0xFF00) >> 8);
W25qxx_Spi(WriteAddr_inBytes & 0xFF);
//W25qxx_Spi(pBuffer);
HAL_SPI_Transmit(&_W25QXX_SPI,pBuffer,ByteNum,5000);
HAL_GPIO_WritePin(_W25QXX_CS_GPIO,_W25QXX_CS_PIN,GPIO_PIN_SET);
W25qxx_WaitForWriteEnd();
#if (_W25QXX_DEBUG==1)
printf("w25qxx WriteByte done after %d ms\r\n",HAL_GetTick()-StartTime);
#endif
w25qxx.Lock=0;
}Here's CubeProgrammer erase fail screenshot
