2021-03-19 04:37 AM
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?
Solved! Go to Solution.
2021-05-20 02:12 AM
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.
2021-03-19 09:55 AM
Too many dummy cycles, wrong address width/size setting? ie mismatch in understanding of SW/HW on STM32 side and QSPI device
2021-05-20 02:12 AM
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.
2021-10-28 05:15 AM
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.
2021-10-28 05:40 AM
The data sheet should detail the frequency vs dummy cycles to allow the memory to do an initial fetch into its page buffer.
It 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.
2021-10-28 06:10 AM
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....