2022-07-21 07:04 AM
Hello,
I am working with STM32H743BI and trying to write then read a QSPI FLASH "mt25qu01gbbb". I first use the STM32 software example "QSPI_ReadWrite_IT" (adapted with cube configuration) to start discovering QSPI on my hardware. Then I made a small evolution that consist on write incremented values on more than one page.
First page seems to be write correctly :
But something wrong is appening for second page :
Did anyone encoutered this problem ? Thank in advance for your help
Please find attached my project.
Solved! Go to Solution.
2022-07-22 09:15 AM
Isn't that the Address data, 24-bit at 1-bit?
The Micron part you've mentioned should be switched into 32-bit addressing mode.
The addressing mode should be in bit 0 of the FLAGS STATUS, ie should read 0x81 for a READY, 4-BYTE ADDRESSING mode
24-bit -> 16MByte -> 128Mbit this is the default/legacy mode of QSPI, so boot loaders can do a generic read method, and subsequently you kick the devices into the 4-byte addressing modes to access the entire array, and where appropriate enable the pins for 4-pin IO operation (different from the 4-bit command/data modes, but enabling of at the pin/interface, and not as Write Protect, Reset, etc)
2022-07-21 07:09 AM
Write only up to 256 bytes such that you don't cross 256-byte page boundaries.
ie if you start 192 bytes into the frame you can only write 64 bytes that remain
0x900000C0 [0x40]
0x90000100 [0x100]
0x90000200 [0x100]
Decompose the writes, and wait for device to come ready.
The 01G device is a dual die device, you should ensure both complete.
2022-07-21 09:45 AM
Thank you DeLorean for your help,
The software is respecting the "256-byte page boundaries", the sequence executed is :
1) erase first sector of flash request and wait for end of erase,
2) request to write the 256 bytes of page of the flash and wait for end of program,
3) request to read data write during step 2) and wait for data reception,
4) comparaison between write and read data
=> until step 4 everything is ok, then steps 2) to 4) are executed again and comparaison between write and read data is incorrect.
You are true the root cause could be caused by the dual die architecture of this component but there are not a lot of détail about it in the datasheet. Do you have any idea of the difference that I need to introduce because of this subtility ?
Regards
2022-07-21 11:23 AM
Dual Die
Don't use the AutoPolling methods, they don't work the way you need.
For Micron devices in the MT25 and MT35 families you need to do TWO separated reads of the FLAG STATUS REGISTER (0x70) and BOTH need to flag READY
For the Quad Die (02G) you need to read FOUR times, and again all must be READY
Also, CHIP ERASE doesn't work, you have to use the DIE ERASE command, addressing the specific parts. ie DIE ERASE (0x0000000) and DIE ERASE (0x4000000) for the 64MB (512Mbit) die
2022-07-22 03:34 AM
2022-07-22 08:37 AM
Text removed because erronous.
2022-07-22 09:15 AM
Isn't that the Address data, 24-bit at 1-bit?
The Micron part you've mentioned should be switched into 32-bit addressing mode.
The addressing mode should be in bit 0 of the FLAGS STATUS, ie should read 0x81 for a READY, 4-BYTE ADDRESSING mode
24-bit -> 16MByte -> 128Mbit this is the default/legacy mode of QSPI, so boot loaders can do a generic read method, and subsequently you kick the devices into the 4-byte addressing modes to access the entire array, and where appropriate enable the pins for 4-pin IO operation (different from the 4-bit command/data modes, but enabling of at the pin/interface, and not as Write Protect, Reset, etc)
2022-07-22 09:22 AM
/**
* @brief Writes an amount of data to the QSPI memory.
* @param pData : Pointer to data to be written
* @param WriteAddr : Write start address
* @param Size : Size of data to write
* @retval QSPI memory status
*/
uint8_t BSP_QSPI_Write(uint8_t *pData, uint32_t WriteAddr, uint32_t Size)
{
QSPI_CommandTypeDef sCommand = {0}; // clear random stack content
uint32_t end_addr, current_size, current_addr;
/* Calculation of the size between the write address and the end of the page */
current_size = PAGE_SIZE - (WriteAddr % PAGE_SIZE); // Deblock on page size 256 byte aligned/bufferred
/* Check if the size of the data is less than the remaining place in the page */
if (current_size > Size)
{
current_size = Size;
}
/* Initialize the adress variables */
current_addr = WriteAddr;
end_addr = WriteAddr + Size;
/* Initialize the program command */
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.Instruction = QUAD_PAGE_PROG_CMD;
sCommand.AddressMode = QSPI_ADDRESS_4_LINES; // depends on cmd/mode
sCommand.AddressSize = QSPI_ADDRESS_24_BITS; // depends on part size/config
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = QSPI_DATA_4_LINES; // cmd/mode
sCommand.DummyCycles = 0; // watch these
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Perform the write page by page */
do
{
sCommand.Address = current_addr;
sCommand.NbData = current_size;
/* Enable write operations */
if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
{
return QSPI_ERROR;
}
/* Configure the command */
if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Transmission of the data */
if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Configure automatic polling mode to wait for end of program */
if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK) // This needs to be replaced by STATUS FLAGS REGISTER variant on Micron's (all die must complete)
{
return QSPI_ERROR;
}
/* Update the address and size variables for next page programming */
current_addr += current_size;
pData += current_size;
current_size = ((current_addr + PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : PAGE_SIZE;
}
while (current_addr < end_addr);
return QSPI_OK;
}
I'll find something Micron specific later, but would strongly recommend partitioning/compartmentalizing this functionality so there aren't drop-thru dependencies like your example