cancel
Showing results for 
Search instead for 
Did you mean: 

[TouchGFX] Can not write to External flash using QuasSPI while running with TouchGFX

HPham.1590
Senior

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 */
}

1 ACCEPTED SOLUTION

Accepted Solutions

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;

}

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

19 REPLIES 19
Alexandre RENOUX
Principal

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

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

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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​

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;

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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​

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

"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

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..