2021-05-01 10:03 AM
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.
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
Solved! Go to Solution.
2021-05-14 07:15 AM
Solved.
Init() function called every time before other functions. So SystemClockConfig was called several times, causing a hard fault. I've removed it from Init and erase, read and write operations work fine, but it looks like verify isn't working correctly.
2021-05-14 07:15 AM
Solved.
Init() function called every time before other functions. So SystemClockConfig was called several times, causing a hard fault. I've removed it from Init and erase, read and write operations work fine, but it looks like verify isn't working correctly.
2021-06-21 06:14 AM
Hello @AksultanK ,
Good Day!
We have been working on exactly the same configuration and we found that no one has yet implemented an external loader for SPI flash (no Quad).
We are also facing similar issues.
Our loader isn't even able to communicate with the SPI flash.
Could you please share your loader_src and Dev_info files with me?
Thanking You.
2021-06-21 11:14 AM
Sure, here is archive with the CubeIDE project. But please be aware, there are some lines that I have no clue what they do. At some point I just started copying lines from examples in hope it will work, so it's a not the best example, but it works somehow. Still couldn't make it work in TouchGFX.
2021-06-21 08:04 PM
Thanks a lot, @AksultanK.
I really appreciate your help.
I would update you with the outcome.
2021-06-22 10:14 PM
Hello AksultanK,
We got it working and can upload and verify data with this loader file.
Thanks again for your help.
We are now working on using it along with Toughgfx. Hope to get it working soon.
2021-06-22 11:54 PM
Great! Glad I could help. Please share the results.
2023-05-28 08:57 AM
Hi,
I have been trying to program W25Q16 external flash for Fast Read Dual Out mode. In this mode, basically both the lines MISO and MOSI become input for the host (STM32 in this case) and data can be read at double the speed. My SPI is running at 40MHz and in Normal read mode with DMA I am getting the correct bandwidth. I am able to read out 20KB in roughly 4.150 milliseconds.
Now, when i try to send the instruction to perform Fast Read Dual Output as mentioned in page 30 of this user manual https://datasheet.lcsc.com/lcsc/1912111437_Winbond-Elec-W25Q128JVSIQ_C113767.pdf
I start getting incorrect Data. I have written some predefined values to 512Byte space in flash for the comparison. When I do a normal read, as mentioned above, the data stays correct. However, with Fast Read Dual Out, the data gets corrupted.
What i am not able to understand is that, does it require special steps to configure GPIOs before we do fast read dual output? Or am i missing anything specific which is not mentioned in the manual. If you have already done something similar, kindly guide me. My SPI initialization values are:
inSPIHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
inSPIHandle->Init.CLKPhase = SPI_PHASE_1EDGE;
inSPIHandle->Init.CLKPolarity = SPI_POLARITY_LOW;
inSPIHandle->Init.CRCPolynomial = SPI_CRCPR_CRCPOLY;
inSPIHandle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
inSPIHandle->Init.DataSize = SPI_DATASIZE_8BIT;
inSPIHandle->Init.Direction = SPI_DIRECTION_2LINES;
inSPIHandle->Init.FirstBit = SPI_FIRSTBIT_MSB;
inSPIHandle->Init.Mode = SPI_MODE_MASTER;
inSPIHandle->Init.NSS = SPI_NSS_SOFT;
inSPIHandle->Init.TIMode = SPI_TIMODE_DISABLE;
I will be looking forward to your reply.
2023-05-28 04:29 PM
Topic as own thread. STM32 model not specified. https://community.st.com/s/question/0D53W00002HW5CtSAL/how-to-perform-w25q16-fast-read-dual-output-
2023-05-28 09:01 PM
I have asked in multiple places in the hope that people who have experience with this flash, might have already done it.