2020-09-16 01:09 AM
Hello, I'm using STM32F746NG Discovery Kit.
I'm trying to Write/Read data to/from External Flash using QuadSPI with BSP driver.
Below is my simple function, I don't know why It's can not write to the memory.
I really don't know exactly how to determine the block address and the Read/Write Address, can anyone help me to correct it?
Many thanks,
Hieu
uint8_t * pData = "Hello World";
int i;
if (BSP_QSPI_Erase_Block(0x90000000) == QSPI_OK)
{
if(BSP_QSPI_Write(pData, 0x90000000, 12) == QSPI_OK)
{
i = 1;
}
}
static void MX_QUADSPI_Init(void)
{
/* USER CODE BEGIN QUADSPI_Init 0 */
/* USER CODE END QUADSPI_Init 0 */
/* USER CODE BEGIN QUADSPI_Init 1 */
/* USER CODE END QUADSPI_Init 1 */
/* QUADSPI parameter configuration*/
hqspi.Instance = QUADSPI;
// HAL_QSPI_DeInit(&QSPIHandle); //User Code
hqspi.Init.ClockPrescaler = 1;
// hqspi.Init.ClockPrescaler = 2;//User Code
hqspi.Init.FifoThreshold = 4;
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
hqspi.Init.FlashSize = 24;
// QSPIHandle.Init.FlashSize = POSITION_VAL(0x1000000) - 1; //User Code
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;
// QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE; //User Code
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
if (HAL_QSPI_Init(&hqspi) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN QUADSPI_Init 2 */
BSP_QSPI_Init();
BSP_QSPI_MemoryMappedMode();
// This line below is disabled to test Write to external flash function
// HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
/* USER CODE END QUADSPI_Init 2 */
}
Solved! Go to Solution.
2020-09-18 10:08 AM
But are you writing it a lot? If it is configuration data perhaps manage it before bring it up in Memory Mapped Mode
Direct Mode is where you interact with the QSPI at a command/peripheral level rather than mapped into the ARM's address space.
STM32Cube_FW_F7_V1.16.0\Drivers\BSP\STM32746G-Discovery\stm32746g_discovery_qspi.c
/**
* @brief Reads an amount of data from the QSPI memory.
* @param pData: Pointer to data to be read
* @param ReadAddr: Read start address
* @param Size: Size of data to read
* @retval QSPI memory status
*/
uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
QSPI_CommandTypeDef s_command;
/* Initialize the read command */
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
s_command.Instruction = QUAD_INOUT_FAST_READ_CMD;
s_command.AddressMode = QSPI_ADDRESS_4_LINES;
s_command.AddressSize = QSPI_ADDRESS_24_BITS;
s_command.Address = ReadAddr;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = QSPI_DATA_4_LINES;
s_command.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD;
s_command.NbData = Size;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Set S# timing for Read command */
MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_3_CYCLE);
/* Reception of the data */
if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Restore S# timing for nonRead commands */
MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_6_CYCLE);
return QSPI_OK;
}
2020-09-18 05:26 AM
Hello,
Your Flash is in Memory Mapped Mode, therefore it is read only. You have to leave the Memory Mapped Mode to be able to write in your external Flash.
/Alexandre
2020-09-18 07:03 AM
Many thanks for your Reply, Alexandre.
I tried to remove BSP_QSPI_MemoryMappedMode(); line but my program jump to hardfault.
So have any way available to Disable this mode to read/write and Enable it after that?
Hieu
2020-09-18 08:47 AM
Execute-In-Place uses the Memory Mapped Mode, as does bus level data access, if turned off, and you're dependent on it, the system will Hard Fault.
You CANNOT use Write/Erase and Memory Mapped mode CONCURRENTLY
You could Read and Write concurrently in Direct Mode, here you'd need manage access to the QSPI like you would a mass storage device (Hard Drive)
Why and how much data do you need to write into memory?
eMMC or SD Cards are better solutions to data storage, for example data logging.
2020-09-18 08:59 AM
Hmm my data has size about 500B-1KB, so i think SD card is not necessary. In case Direct Mode which you mentioned above, have you the document or example about this?
Many thanks,
Hieu
2020-09-18 10:08 AM
But are you writing it a lot? If it is configuration data perhaps manage it before bring it up in Memory Mapped Mode
Direct Mode is where you interact with the QSPI at a command/peripheral level rather than mapped into the ARM's address space.
STM32Cube_FW_F7_V1.16.0\Drivers\BSP\STM32746G-Discovery\stm32746g_discovery_qspi.c
/**
* @brief Reads an amount of data from the QSPI memory.
* @param pData: Pointer to data to be read
* @param ReadAddr: Read start address
* @param Size: Size of data to read
* @retval QSPI memory status
*/
uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
QSPI_CommandTypeDef s_command;
/* Initialize the read command */
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
s_command.Instruction = QUAD_INOUT_FAST_READ_CMD;
s_command.AddressMode = QSPI_ADDRESS_4_LINES;
s_command.AddressSize = QSPI_ADDRESS_24_BITS;
s_command.Address = ReadAddr;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = QSPI_DATA_4_LINES;
s_command.DummyCycles = N25Q128A_DUMMY_CYCLES_READ_QUAD;
s_command.NbData = Size;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Set S# timing for Read command */
MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_3_CYCLE);
/* Reception of the data */
if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return QSPI_ERROR;
}
/* Restore S# timing for nonRead commands */
MODIFY_REG(QSPIHandle.Instance->DCR, QUADSPI_DCR_CSHT, QSPI_CS_HIGH_TIME_6_CYCLE);
return QSPI_OK;
}
2020-09-18 10:26 AM
Yeb, it's a config file but It will be received in runtime and it need to be saved and use in the next restart. So can you give me other idea to deal with it? Thank you for your DirectMode example, I'll try it tomorrow. This is the first time I work with QSPI, it's will become very hard without yours support.
Hieu
2020-09-18 12:35 PM
If you have a sector free on the F746 you could use that
On QSPI you have the HAL_QSPI_DeInit() and also the BSP has QSPI_ResetMemory()
I think that the HAL could be fixed to back it out of memory mapped mode, but that would take some billable time to test/demonstrate.
2020-09-19 01:30 AM
"If you have a sector free on the F746 you could use that" you mean Internal Flash? I'll reading about it.
I also have a bit confuse about the affection to TouchGFX when I call QSPI_DeInit and ResetMemory, so can I use TouchGFX normally after I call these function and init QSPI again?
Hieu
2020-09-19 10:13 AM
I'm afraid your going to have to test/experiment on your own time.
TouchGFX has expectations about the QSPI, you'll need to restore these once you've performed the erase/write operations.