Skip to main content
PDiet.5
Associate
March 19, 2021
Solved

BSP_QSPI_Read on STM32H757I-EVAL from MT25TL01G misses first 6 bytes

  • March 19, 2021
  • 5 replies
  • 2437 views

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?

This topic has been closed for replies.
Best answer by PDiet.5

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.

5 replies

Tesla DeLorean
Guru
March 19, 2021

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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
PDiet.5
PDiet.5AuthorBest answer
Associate
May 20, 2021

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 II
October 28, 2021

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.

Tesla DeLorean
Guru
October 28, 2021

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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
Roberto C
Associate II
October 28, 2021

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....