Skip to main content
ALevc.1
Associate III
April 28, 2020
Solved

QUADSPI FLASH on STM32H747I-DISCO

  • April 28, 2020
  • 5 replies
  • 2688 views

I just would like to write/read to/from external flash on the development board and will really appreciate a hint how to make the easiest way.

I have configured QUADSPI interface only for M7:

QUADSPI Mode: Dual bank with qaurd lines

Chip Select for Dual Bank: Enable Chip Select 1 for both banks.

0693W000000WaIFQA0.png

And use example application for STM32H7h7-EVAL board.

Right now the flash erasing command fails:

	 sCommand.Instruction = SECTOR_ERASE_CMD;
	 sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
	 sCommand.Address = address;
	 sCommand.DataMode = QSPI_DATA_NONE;
	 sCommand.DummyCycles = 0;
 
	 if (HAL_QSPI_Command_IT(&QSPIHandle, &sCommand) != HAL_OK)
	 {
	 Error_Handler();
	 }

I'll appreciate any hints about this topic. May be there is a QSPI example for the STM32H747I-DISCO? Couldn't find it in the downloaded repo.

Best Regards,

Anton

This topic has been closed for replies.
Best answer by Tesla DeLorean

Fails how?

Try using the BSP code, and without interrupts.

Make sure the chip isn't in 4-bit address mode.

Make sure the sCommand structure is clean.

MT25TL01G_BlockErase(&hqspi, QSPI_Ctx[Instance].InterfaceMode, BlockAddress, BlockSize)

STM32Cube_FW_H7_V1.7.0\Drivers\BSP\STM32H747I-DISCO\stm32h747i_discovery_qspi.c

STM32Cube_FW_H7_V1.7.0\Drivers\BSP\Components\mt25tl01g\mt25tl01g.c

/**

 * @brief Erases the specified block of the QSPI memory.

 *     MT25TL01G support 4K, 32K, 64K size block erase commands.

 *     SPI/QPI; 1-1-0/4-4-0

 * @param Ctx Component object pointer

 * @param Mode Interface mode

 * @param BlockAddress Block address to erase

 * @retval QSPI memory status

 */

int32_t MT25TL01G_BlockErase(QSPI_HandleTypeDef *Ctx, MT25TL01G_Interface_t Mode ,uint32_t BlockAddress, MT25TL01G_Erase_t BlockSize)

{

 QSPI_CommandTypeDef s_command;

 switch(BlockSize)

 {

 default :

 case MT25TL01G_ERASE_4K :

  s_command.Instruction   = MT25TL01G_SUBSECTOR_ERASE_4_BYTE_ADDR_CMD_4K;

  break;

 case MT25TL01G_ERASE_32K :

  s_command.Instruction   = MT25TL01G_SUBSECTOR_ERASE_CMD_32K;

  break;

 case MT25TL01G_ERASE_64K :

  s_command.Instruction   = MT25TL01G_SECTOR_ERASE_4_BYTE_ADDR_CMD;

  break;

 case MT25TL01G_ERASE_CHIP :

  return MT25TL01G_ChipErase(Ctx, Mode);

 }

 /* Initialize the erase command */

 s_command.InstructionMode  = (Mode == MT25TL01G_QPI_MODE) ? QSPI_INSTRUCTION_4_LINES : QSPI_INSTRUCTION_1_LINE;

 s_command.AddressMode    = QSPI_ADDRESS_4_LINES;

 s_command.AddressSize    = QSPI_ADDRESS_32_BITS;

 s_command.Address      = BlockAddress;

 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

 s_command.DataMode     = QSPI_DATA_NONE;

 s_command.DummyCycles    = 0;

 s_command.DdrMode      = QSPI_DDR_MODE_DISABLE;

 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

 s_command.SIOOMode     = QSPI_SIOO_INST_EVERY_CMD;

 /* Send the command */

 MT25TL01G_WriteEnable(Ctx,Mode);

 if (HAL_QSPI_Command(Ctx, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

 {

  return MT25TL01G_ERROR_COMMAND;

 }

 MT25TL01G_AutoPollingMemReady(Ctx,Mode);

 return MT25TL01G_OK;

}

5 replies

ALevc.1
ALevc.1Author
Associate III
April 28, 2020

I have corrected the GPIOs in the IDE according to user manual for my board when I activate QSPI in the ide. But that was not good enough.

Tesla DeLorean
Tesla DeLoreanBest answer
Guru
April 28, 2020

Fails how?

Try using the BSP code, and without interrupts.

Make sure the chip isn't in 4-bit address mode.

Make sure the sCommand structure is clean.

MT25TL01G_BlockErase(&hqspi, QSPI_Ctx[Instance].InterfaceMode, BlockAddress, BlockSize)

STM32Cube_FW_H7_V1.7.0\Drivers\BSP\STM32H747I-DISCO\stm32h747i_discovery_qspi.c

STM32Cube_FW_H7_V1.7.0\Drivers\BSP\Components\mt25tl01g\mt25tl01g.c

/**

 * @brief Erases the specified block of the QSPI memory.

 *     MT25TL01G support 4K, 32K, 64K size block erase commands.

 *     SPI/QPI; 1-1-0/4-4-0

 * @param Ctx Component object pointer

 * @param Mode Interface mode

 * @param BlockAddress Block address to erase

 * @retval QSPI memory status

 */

int32_t MT25TL01G_BlockErase(QSPI_HandleTypeDef *Ctx, MT25TL01G_Interface_t Mode ,uint32_t BlockAddress, MT25TL01G_Erase_t BlockSize)

{

 QSPI_CommandTypeDef s_command;

 switch(BlockSize)

 {

 default :

 case MT25TL01G_ERASE_4K :

  s_command.Instruction   = MT25TL01G_SUBSECTOR_ERASE_4_BYTE_ADDR_CMD_4K;

  break;

 case MT25TL01G_ERASE_32K :

  s_command.Instruction   = MT25TL01G_SUBSECTOR_ERASE_CMD_32K;

  break;

 case MT25TL01G_ERASE_64K :

  s_command.Instruction   = MT25TL01G_SECTOR_ERASE_4_BYTE_ADDR_CMD;

  break;

 case MT25TL01G_ERASE_CHIP :

  return MT25TL01G_ChipErase(Ctx, Mode);

 }

 /* Initialize the erase command */

 s_command.InstructionMode  = (Mode == MT25TL01G_QPI_MODE) ? QSPI_INSTRUCTION_4_LINES : QSPI_INSTRUCTION_1_LINE;

 s_command.AddressMode    = QSPI_ADDRESS_4_LINES;

 s_command.AddressSize    = QSPI_ADDRESS_32_BITS;

 s_command.Address      = BlockAddress;

 s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

 s_command.DataMode     = QSPI_DATA_NONE;

 s_command.DummyCycles    = 0;

 s_command.DdrMode      = QSPI_DDR_MODE_DISABLE;

 s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

 s_command.SIOOMode     = QSPI_SIOO_INST_EVERY_CMD;

 /* Send the command */

 MT25TL01G_WriteEnable(Ctx,Mode);

 if (HAL_QSPI_Command(Ctx, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

 {

  return MT25TL01G_ERROR_COMMAND;

 }

 MT25TL01G_AutoPollingMemReady(Ctx,Mode);

 return MT25TL01G_OK;

}

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
ALevc.1
ALevc.1Author
Associate III
April 28, 2020

Oh. Thank you for the swift reply.

Falls like this:

There is a check for status In the HAL_QSPI_Command_IT

if(hqspi->State == HAL_QSPI_STATE_READY)

The dubugger shows that the vlue is "BUSY_AUTPOLLING". Without interrupts means just removing.

 HAL_NVIC_SetPriority(QUADSPI_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(QUADSPI_IRQn);

?

I am also curious wether default configuration generated by the is correct, when it writes flash szie is 1.

	QSPIHandle.Instance = QUADSPI;
	QSPIHandle.Init.ClockPrescaler = 255;
	QSPIHandle.Init.FifoThreshold = 1;
	QSPIHandle.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
	QSPIHandle.Init.FlashSize = 1;
	QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
	QSPIHandle.Init.ClockMode = QSPI_CLOCK_MODE_0;
	QSPIHandle.Init.DualFlash = QSPI_DUALFLASH_ENABLE;

Sorry :) I am totally newbie in the STM world.

ALevc.1
ALevc.1Author
Associate III
April 28, 2020

Well it helped to move 1 step further after I have disabled 4-bit address mode. Thanks a lot for the hint.

But now the example expects

void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi)
{
 StatusMatch++;
}

call to increment StatusMatch and it never happens.... @Community member​, Do you have an idea what direction to look?

ALevc.1
ALevc.1Author
Associate III
April 28, 2020

@Community member​ It took me some time to digest but I see now whoat you mean. I was not aware about the BSP package. Thanks a lot for the hint.