Skip to main content
HPham.1590
Associate III
September 14, 2020
Question

[QuadSPI] [TouchGFX] Can not Write and Read data from External Flash on STM32F746 Discovery

  • September 14, 2020
  • 4 replies
  • 1102 views

Hello, I'm using STM32F746 Discovery Kit with Touch GFX.

I want to Write and Read data from N25Q512A External Flash using QSPI.

I have tried the ST's Example on Github but it's not working for me (https://github.com/STMicroelectronics/STM32CubeF7),

I found that my program has a bit different from the example.

The different come from TouchGFX. When using TouchGFX, QuadSPI has been enabled and using for this library and the hqspi.Init.ClockPrescaler = 1 ( the ST's example is 2).

(I think the different clock is not affected)

Below is my functions, anyone can tell me what is wrong?

Many thanhs,

Hieu.

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 */
}
HAL_StatusTypeDef WriteDataToQuadSPI(QSPI_HandleTypeDef QSPIHandle, uint32_t address, uint8_t * aTxBuffer)
{
	QSPI_CommandTypeDef sCommand;
	sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
	sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
	sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
	sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
	sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
	/* Enable write operations ------------------------------------------- */
	QSPI_WriteEnable(&QSPIHandle);
	/* Erasing Sequence -------------------------------------------------- */
	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(&QSPIHandle, &sCommand,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
	{
		return HAL_ERROR;
	}
	/* Configure automatic polling mode to wait for end of erase ------- */
	QSPI_AutoPollingMemReady(&QSPIHandle);
	/* Enable write operations ----------------------------------------- */
	QSPI_WriteEnable(&QSPIHandle);
 /* Writing Sequence ------------------------------------------------ */
 sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
 sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
 sCommand.DataMode = QSPI_DATA_4_LINES;
 sCommand.NbData = BUFFERSIZE;
 
 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 	return HAL_ERROR;
 }
 
 if (HAL_QSPI_Transmit(&QSPIHandle, aTxBuffer,HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 	return HAL_ERROR;
 }
 /* Configure automatic polling mode to wait for end of program ----- */
 QSPI_AutoPollingMemReady(&QSPIHandle);
 return HAL_OK;
}
uint8_t * ReadDataFromQuadSPI(QSPI_HandleTypeDef QSPIHandle, uint32_t address)
{
	uint8_t * aRxBuffer;
	QSPI_CommandTypeDef sCommand;
	sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
	sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
	sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
	sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
	sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
 /* Configure Volatile Configuration register (with new dummy cycles) */
 QSPI_DummyCyclesCfg(&QSPIHandle);
 
 /* Reading Sequence ------------------------------------------------ */
 sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;
 sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD;
 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 	aRxBuffer[0] = 1;
 }
 
 if (HAL_QSPI_Receive_IT(&QSPIHandle, aRxBuffer) != HAL_OK)
 {
 	aRxBuffer[0] = 1;
 }
 return aRxBuffer;
}
static void QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi)
{
 QSPI_CommandTypeDef sCommand;
 QSPI_AutoPollingTypeDef sConfig;
 
 /* Enable write operations ------------------------------------------ */
 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
 sCommand.Instruction = WRITE_ENABLE_CMD;
 sCommand.AddressMode = QSPI_ADDRESS_NONE;
 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
 sCommand.DataMode = QSPI_DATA_NONE;
 sCommand.DummyCycles = 0;
 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
 
 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Configure automatic polling mode to wait for write enabling ---- */
 sConfig.Match = 0x02;
 sConfig.Mask = 0x02;
 sConfig.MatchMode = QSPI_MATCH_MODE_AND;
 sConfig.StatusBytesSize = 1;
 sConfig.Interval = 0x10;
 sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
 
 sCommand.Instruction = READ_STATUS_REG_CMD;
 sCommand.DataMode = QSPI_DATA_1_LINE;
 
 if (HAL_QSPI_AutoPolling(&QSPIHandle, &sCommand, &sConfig, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
}
 
/**
 * @brief This function reads the SR of the memory and awaits the EOP.
 * @param hqspi: QSPI handle
 * @retval None
 */
static void QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi)
{
 QSPI_CommandTypeDef sCommand;
 QSPI_AutoPollingTypeDef sConfig;
 
 /* Configure automatic polling mode to wait for memory ready ------ */
 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
 sCommand.Instruction = READ_STATUS_REG_CMD;
 sCommand.AddressMode = QSPI_ADDRESS_NONE;
 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
 sCommand.DataMode = QSPI_DATA_1_LINE;
 sCommand.DummyCycles = 0;
 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
 
 sConfig.Match = 0x00;
 sConfig.Mask = 0x01;
 sConfig.MatchMode = QSPI_MATCH_MODE_AND;
 sConfig.StatusBytesSize = 1;
 sConfig.Interval = 0x10;
 sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
 
 if (HAL_QSPI_AutoPolling_IT(&QSPIHandle, &sCommand, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
}
 
/**
 * @brief This function configures the dummy cycles on memory side.
 * @param hqspi: QSPI handle
 * @retval None
 */
static void QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
{
 QSPI_CommandTypeDef sCommand;
 uint8_t reg;
 
 /* Read Volatile Configuration register --------------------------- */
 sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
 sCommand.Instruction = READ_VOL_CFG_REG_CMD;
 sCommand.AddressMode = QSPI_ADDRESS_NONE;
 sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
 sCommand.DataMode = QSPI_DATA_1_LINE;
 sCommand.DummyCycles = 0;
 sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
 sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
 sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
 sCommand.NbData = 1;
 
 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 
 if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 
 /* Enable write operations ---------------------------------------- */
 QSPI_WriteEnable(&QSPIHandle);
 
 /* Write Volatile Configuration register (with new dummy cycles) -- */
 sCommand.Instruction = WRITE_VOL_CFG_REG_CMD;
 MODIFY_REG(reg, 0xF0, (DUMMY_CLOCK_CYCLES_READ_QUAD << POSITION_VAL(0xF0)));
 
 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 
 if (HAL_QSPI_Transmit(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
}

This topic has been closed for replies.

4 replies

Martin KJELDSEN
Principal III
September 14, 2020

For TouchGFX applications we require the flash chip to be memory mapped so we can simply point to a position in the chips memory range. When you read and write using the BSP functions you cannot have the chip in memory mapped mode. Try removing:

BSP_QSPI_MemoryMappedMode();

HPham.1590
Associate III
September 15, 2020

Many thanks for your reply,

As your suggestion, I tried to remove this line, but my program ran into HardFault_Handler.

So may I make some mistake in any step?

Tesla DeLorean
Guru
September 14, 2020

24-bit addressing isn't going to be sufficient for a 64MB memory​

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
HPham.1590
Associate III
September 15, 2020

Hello Clive,

I have tried to replace 24-bit addressing by 32-bit address, but it's still not working.

I think it's not the root cause because in the ST's Example what I referred, 24-bit address is still used.