2020-04-28 06:22 AM
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.
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
Solved! Go to Solution.
2020-04-28 06:49 AM
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;
}
2020-04-28 06:25 AM
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.
2020-04-28 06:49 AM
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;
}
2020-04-28 07:03 AM
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.
2020-04-28 07:50 AM
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?
2020-04-28 08:46 AM
@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.