cancel
Showing results for 
Search instead for 
Did you mean: 

QUADSPI FLASH on STM32H747I-DISCO

ALevc.1
Associate III

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

1 ACCEPTED SOLUTION

Accepted Solutions

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
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

5 REPLIES 5
ALevc.1
Associate III

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.

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
Up vote any posts that you find helpful, it shows what's working..
ALevc.1
Associate III

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
Associate III

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
Associate III

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