QSPI migration from STM32F7 to STM32H7
Hi Folks,
I've been asked to look at a problem we are having migrating from the STM32F7 to STM32H7. We are seeing a problem when communicating with the QUAD SPI chip (Micron MT25QL256ABA).
(I've very familiar with SPI communications and microcontrollers, but new to STM32.)
I looked at section 2.4 of the Errata file for the H7 chip: https://www.st.com/resource/en/errata_sheet/dm00368411-stm32h742xi-g-and-stm32h743xi-g-device-limitations-stmicroelectronics.pdf but honestly I'm still going up the learning curve for this chip.
We have a sample program that writes data to the QSPI and then reads it back in MemoryMappedMode. Strangely the program runs through the tests 5 times and then fails to read the data back for comparison. Here is a section of the code that consistently fails:
// +++++++ START MULTI-SECTOR TEST ++++++++++
// Erase a sector then write a sector
// Notes: EraseSector command may be size dependent.
// EndAddress parameter is ignored.
// Need to re-init to exit Memory Mapped Mode from previous test
CSP_QUADSPI_Init();
for (var = 0; var < SECTOR_COUNT; var++)
{
if (CSP_QSPI_EraseSector(var * MEMORY_SECTOR_SIZE,
(var + 1) * MEMORY_SECTOR_SIZE - 1) != HAL_OK)
{
while (1); //breakpoint - error detected
}
Wait_For_QUADSPI();
if (CSP_QSPI_WriteMemory(upCountBuffer, var * MEMORY_SECTOR_SIZE,
sizeof(upCountBuffer)) != HAL_OK)
{
while (1); //breakpoint - error detected
}
if (CSP_QSPI_EraseSector(0x1000000 + (var * MEMORY_SECTOR_SIZE),
0x1000000 + (var * MEMORY_SECTOR_SIZE) + (MEMORY_SECTOR_SIZE - 1)) != HAL_OK)
{
while (1); //breakpoint - error detected
}
Wait_For_QUADSPI();
if (CSP_QSPI_WriteMemory(downCountBuffer, 0x1000000 + (var * MEMORY_SECTOR_SIZE),
sizeof(downCountBuffer)) != HAL_OK)
{
while (1); //breakpoint - error detected
}
}
if (CSP_QSPI_EnableMemoryMappedMode() != HAL_OK)
{
while (1); //breakpoint - error detected
}
HAL_Delay(10);
//Wait_For_QUADSPI();
// xxCountBuffer[] (size of one sector) is bulk compared against a written sector.
// This comparison occurs, sector by sector for SECTOR_COUNT number of times.
for (var = 0; var < SECTOR_COUNT; var++)
{
memcpy( upCountBuffer_read,
(uint8_t*) (0x90000000 + (var * MEMORY_SECTOR_SIZE)), MEMORY_SECTOR_SIZE);
if (memcmp(upCountBuffer, upCountBuffer_read, MEMORY_SECTOR_SIZE) != HAL_OK)
{
while (1); //breakpoint - error detected - otherwise QSPI works properly
}
if (memcmp(upCountBuffer,
(uint8_t*) (0x90000000 + (var * MEMORY_SECTOR_SIZE)),
MEMORY_SECTOR_SIZE) != HAL_OK)
{
while (1); //breakpoint - error detected - otherwise QSPI works properly
}
memcpy( downCountBuffer_read,
(uint8_t*) (0x90000000 + 0x1000000 + (var * MEMORY_SECTOR_SIZE)),
MEMORY_SECTOR_SIZE);
if (memcmp(downCountBuffer, downCountBuffer_read, MEMORY_SECTOR_SIZE) != HAL_OK)
{
while (1); //breakpoint - error detected - otherwise QSPI works properly
}
if (memcmp(downCountBuffer,
(uint8_t*) (0x90000000 + 0x1000000 + (var * MEMORY_SECTOR_SIZE)),
MEMORY_SECTOR_SIZE) != HAL_OK)
{
while (1); //breakpoint - error detected - otherwise QSPI works properly
}
}Note the Wait_For_QUADSPI() is as follows:
void Wait_For_QUADSPI(void)
{
HAL_Delay(10);
int count = 0;
HAL_QSPI_StateTypeDef iState;
//return;
while (1)
{
iState = HAL_QSPI_GetState(&hqspi);
switch (iState)
{
case HAL_QSPI_STATE_RESET:
break;
case HAL_QSPI_STATE_READY:
return;
case HAL_QSPI_STATE_BUSY:
break;
case HAL_QSPI_STATE_BUSY_INDIRECT_TX:
break;
case HAL_QSPI_STATE_BUSY_INDIRECT_RX:
break;
case HAL_QSPI_STATE_BUSY_AUTO_POLLING:
break;
case HAL_QSPI_STATE_BUSY_MEM_MAPPED:
count++;
if (count>10)
{
//HAL_QSPI_Abort(&hqspi);/// do I need to reinit?
return;
}
break;
case HAL_QSPI_STATE_ABORT:
break;
case HAL_QSPI_STATE_ERROR:
break;
default:
break;
}
HAL_Delay(10);
}
}In previous tests it would hang if I called the above function after EnableMemoryMappedMode so I tried to abort but that didn't help. So I commented out that part and now use a hardcoded delay of 10mSec after Enableing Memory Mapped mode.
Here is the EnableMemoryMappedMode code. Note I tried with and without timeout enabled.
uint8_t CSP_QSPI_EnableMemoryMappedMode(void) {
QSPI_CommandTypeDef sCommand;
QSPI_MemoryMappedTypeDef sMemMappedCfg;
/* Enable Memory-Mapped mode-------------------------------------------------- */
/***** Assuming QUAD MODE is enabled *****/
/***** Assuming 4-byte address mode ******/
sCommand.InstructionMode = QSPI_INSTRUCTION_4_LINES;
//sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
sCommand.AddressSize = QSPI_ADDRESS_32_BITS;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
sCommand.AddressMode = QSPI_ADDRESS_4_LINES;
sCommand.DataMode = QSPI_DATA_4_LINES;
sCommand.NbData = 1;
sCommand.Address = 0;
//sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;
sCommand.Instruction = QUAD_4BYTE_OUT_FAST_READ_CMD;
sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD;
sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_ENABLE; ///QSPI_TIMEOUT_COUNTER_DISABLE; RRS
if (HAL_QSPI_MemoryMapped(&hqspi, &sCommand, &sMemMappedCfg) != HAL_OK) {
return HAL_ERROR;
}
return HAL_OK;
}Anyway, I wanted to reach out and see if there were others who had a similar issue and can share some code with how you got around the problem (ie how you implemented the suggestions in the Errata pdf.)
thanks much!
Bob