cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 QSPI FLASH write issue

sylvain77176
Associate II

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 :

0693W00000QLm9HQAT.pngBut something wrong is appening for second page :

0693W00000QLm3sQAD.pngDid anyone encoutered this problem ? Thank in advance for your help

Please find attached my project.

1 ACCEPTED SOLUTION

Accepted Solutions

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)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

7 REPLIES 7

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sylvain77176
Associate II

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

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sylvain77176
Associate II

Hello and thank you again for your help!

I am now doing TWO separated reads of the FLAG STATUS REGISTER (0x70) and waiting for the flag READY. The behaviour is the same as yersterday. Am I missing something ?

my modifications :

0693W00000QLtQtQAL.pngRegards

sylvain77176
Associate II

Text removed because erronous.

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)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
/**
  * @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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..