cancel
Showing results for 
Search instead for 
Did you mean: 

BSP_QSPI_Read on STM32H757I-EVAL from MT25TL01G misses first 6 bytes

PDiet.5
Associate II

I'm trying to do a simple read/write on the MT25TL01G flash that's present on the STM32H757I-EVAL evaluation board. However, when I'm using BSP_QSPI_Read, I'm missing the first 6 bytes of data. Reading via memory mapped mode works as expected.

Here's my initialization code. The QSPI clock should be running at 200MHz, according to CubeMX.

  /* QUADSPI parameter configuration*/
  hqspi.Instance = QUADSPI;
  hqspi.Init.ClockPrescaler = 3;
  hqspi.Init.FifoThreshold = 1;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
  hqspi.Init.FlashSize = 26;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
  if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN QUADSPI_Init 2 */
 
  BSP_QSPI_DeInit(0);
 
  BSP_QSPI_Init_t init ;
  init.InterfaceMode  = MT25TL01G_QPI_MODE;
  init.TransferRate   = MT25TL01G_DTR_TRANSFER;
  init.DualFlashMode  = MT25TL01G_DUALFLASH_ENABLE;
 
  if(BSP_QSPI_Init(0,&init) != BSP_ERROR_NONE)
  {
    Error_Handler();
  }
  if(BSP_QSPI_EnableMemoryMappedMode(0) != BSP_ERROR_NONE)
  {
    Error_Handler();
  }
  HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
  /* USER CODE END QUADSPI_Init 2 */

Here's my code for read/write:

uint32_t address = 0;
char * writeData = "123456Hello world!";
char data[50] = {};
size_t size = strlen(writeData);
 
char qspi_data[50] = {};
memcpy(qspi_data, (void*)(QSPI_BASE_ADDRESS + address), size);
printf("Read via MemMap: %s\r\n", qspi_data); // works as expected (if it has been written already)
 
// Disable MemoryMappedMode
BSP_QSPI_DisableMemoryMappedMode(0);
 
// Erase sector
BSP_QSPI_EraseBlock(0, address, BSP_QSPI_ERASE_8K);
 
// Write data
BSP_QSPI_Write(0, (uint8_t*)writeData, address, size);
 
// Read data
BSP_QSPI_Read(0, (uint8_t*)data, address, size)
 
printf("Read %s from QSPI\r\n", data); // prints: "Hello world!" instead of "123456Hello world!"

All the BSP_QSPI_* function calls return without error.

What am I doing wrong?

1 ACCEPTED SOLUTION

Accepted Solutions
PDiet.5
Associate II

By changing the dummy cycles I did manage to fix this, but it caused the QSPI / flash to lock up when changing to and from memory mapped mode and other troubles.

I believe that the problem was caused by BSP_QSPI_DisableMemoryMappedMode/BSP_QSPI_EnableMemoryMappedMode not working as expected?

Instead, I used the following code to change from memory mapped mode to indirect mode and vice versa by resetting the HAL and the MT25TL01G each time.

Memory mapped to indirect:

extern QSPI_HandleTypeDef hqspi;
 
    HAL_QSPI_DeInit(&hqspi);
    hqspi.Instance = QUADSPI;
    hqspi.Init.ClockPrescaler = 3;
    hqspi.Init.FifoThreshold = 1;
    hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
    hqspi.Init.FlashSize = 26;
    hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
    hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
    hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
    if (HAL_QSPI_Init(&hqspi) != HAL_OK)
    {
        Error_Handler();
    }
 
    if (BSP_QSPI_DisableMemoryMappedMode(0) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
 
    BSP_QSPI_DeInit(0);
 
    BSP_QSPI_Init_t init;
    init.InterfaceMode = MT25TL01G_QPI_MODE;
    init.TransferRate = MT25TL01G_DTR_TRANSFER;
    init.DualFlashMode = MT25TL01G_DUALFLASH_ENABLE;
 
    extern BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER];
    QSPI_Ctx[0].IsInitialized = QSPI_ACCESS_NONE;
 
    if (BSP_QSPI_Init(0, &init) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }

Indirect to memory mapped:

extern QSPI_HandleTypeDef hqspi;
 
    HAL_QSPI_DeInit(&hqspi);
    hqspi.Instance = QUADSPI;
    hqspi.Init.ClockPrescaler = 3;
    hqspi.Init.FifoThreshold = 1;
    hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
    hqspi.Init.FlashSize = 26;
    hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
    hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
    hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
    if (HAL_QSPI_Init(&hqspi) != HAL_OK)
    {
        Error_Handler();
    }
 
    BSP_QSPI_DeInit(0);
 
    BSP_QSPI_Init_t init;
    init.InterfaceMode = MT25TL01G_QPI_MODE;
    init.TransferRate = MT25TL01G_DTR_TRANSFER;
    init.DualFlashMode = MT25TL01G_DUALFLASH_ENABLE;
 
    extern BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER];
    QSPI_Ctx[0].IsInitialized = QSPI_ACCESS_NONE;
 
    if (BSP_QSPI_Init(0, &init) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
    if (BSP_QSPI_EnableMemoryMappedMode(0) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
    HAL_NVIC_DisableIRQ(QUADSPI_IRQn);

The key point was to set

extern BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER];
    QSPI_Ctx[0].IsInitialized = QSPI_ACCESS_NONE;

before calling BSP_QSPI_Init(), to get the BSP driver to properly re-initialize the MT25TL01G driver.

I realize this is probably not the most efficient or elegant solution, but I did not have any more time to dig any deeper and was just happy I got it working somehow.

View solution in original post

5 REPLIES 5

Too many dummy cycles, wrong address width/size setting? ie mismatch in understanding of SW/HW on STM32 side and QSPI device

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

By changing the dummy cycles I did manage to fix this, but it caused the QSPI / flash to lock up when changing to and from memory mapped mode and other troubles.

I believe that the problem was caused by BSP_QSPI_DisableMemoryMappedMode/BSP_QSPI_EnableMemoryMappedMode not working as expected?

Instead, I used the following code to change from memory mapped mode to indirect mode and vice versa by resetting the HAL and the MT25TL01G each time.

Memory mapped to indirect:

extern QSPI_HandleTypeDef hqspi;
 
    HAL_QSPI_DeInit(&hqspi);
    hqspi.Instance = QUADSPI;
    hqspi.Init.ClockPrescaler = 3;
    hqspi.Init.FifoThreshold = 1;
    hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
    hqspi.Init.FlashSize = 26;
    hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
    hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
    hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
    if (HAL_QSPI_Init(&hqspi) != HAL_OK)
    {
        Error_Handler();
    }
 
    if (BSP_QSPI_DisableMemoryMappedMode(0) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
 
    BSP_QSPI_DeInit(0);
 
    BSP_QSPI_Init_t init;
    init.InterfaceMode = MT25TL01G_QPI_MODE;
    init.TransferRate = MT25TL01G_DTR_TRANSFER;
    init.DualFlashMode = MT25TL01G_DUALFLASH_ENABLE;
 
    extern BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER];
    QSPI_Ctx[0].IsInitialized = QSPI_ACCESS_NONE;
 
    if (BSP_QSPI_Init(0, &init) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }

Indirect to memory mapped:

extern QSPI_HandleTypeDef hqspi;
 
    HAL_QSPI_DeInit(&hqspi);
    hqspi.Instance = QUADSPI;
    hqspi.Init.ClockPrescaler = 3;
    hqspi.Init.FifoThreshold = 1;
    hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
    hqspi.Init.FlashSize = 26;
    hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
    hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
    hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
    if (HAL_QSPI_Init(&hqspi) != HAL_OK)
    {
        Error_Handler();
    }
 
    BSP_QSPI_DeInit(0);
 
    BSP_QSPI_Init_t init;
    init.InterfaceMode = MT25TL01G_QPI_MODE;
    init.TransferRate = MT25TL01G_DTR_TRANSFER;
    init.DualFlashMode = MT25TL01G_DUALFLASH_ENABLE;
 
    extern BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER];
    QSPI_Ctx[0].IsInitialized = QSPI_ACCESS_NONE;
 
    if (BSP_QSPI_Init(0, &init) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
    if (BSP_QSPI_EnableMemoryMappedMode(0) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
    HAL_NVIC_DisableIRQ(QUADSPI_IRQn);

The key point was to set

extern BSP_QSPI_Ctx_t QSPI_Ctx[QSPI_INSTANCES_NUMBER];
    QSPI_Ctx[0].IsInitialized = QSPI_ACCESS_NONE;

before calling BSP_QSPI_Init(), to get the BSP driver to properly re-initialize the MT25TL01G driver.

I realize this is probably not the most efficient or elegant solution, but I did not have any more time to dig any deeper and was just happy I got it working somehow.

Roberto C
Associate III

Hi PDiet.5 

I'm having same troubles.

Could you better explain how and where you changed the dummy cycles to solve the missing 6 bytes?

What value you used to solve it?.

Thnx in advance

Roberto.

The data sheet should detail the frequency vs dummy cycles to allow the memory to do an initial fetch into its page buffer.

I​t has a 0 to 15 range programmed into a register on the memory side, and then specified on the READ command instance.

Usually there's a Set/Program Dummy Cycles in the initialization code, so both memory and MCU have a consistent expectation.​

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

Thnx for infos!

..but before to change it I tried to implement the above functions ("Memory mapped to indirect" and "indirect to Memory mapped") and it seems to solve also the original trouble in this question ("missing first 6 bytes")..

Still investigating over it....