Skip to main content
Ehill.16
Senior
October 14, 2020
Question

DMA QSPI transmit and receive complete

  • October 14, 2020
  • 4 replies
  • 3518 views

I need to know when a DMA QSPI flash transmit and receive are complete. How do I use the QSPI_DMATxCplt and QSPI_DMARxCplt functions. 

This topic has been closed for replies.

4 replies

ST Technical Moderator
October 14, 2020

Hello @Ehill.16​ ,

This QSPI DMA function is used for transmitting data: HAL_QSPI_Transmit_DMA(&QSPIHandle, aTxBuffer) != HAL_OK,

 if (HAL_QSPI_Transmit_DMA(&QSPIHandle, aTxBuffer) != HAL_OK)
 {
 Error_Handler();
 }
 
 step++;
 }
 break;
 
 case 3:
 if(TxCplt != 0)
 {
 TxCplt = 0;
 StatusMatch = 0;
 
 /* Configure automatic polling mode to wait for end of program ----- */ 
 QSPI_AutoPollingMemReady(&QSPIHandle);
 
 step++;
 }

Then, an interruption will be generated, and the HAL_QSPI_RxCpltCallback() function will be called:

void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi)
{
 RxCplt++;
}

Note that you should add the HAL_QSPI_RxCpltCallback() function in the main.c.

I recommend you to refer to the QSPI_ReadWrite_DMA example in the STM32CubeF7 MCU package and get inspired or re-use the available sections : STM32Cube_FW_F7_Vx.xx.x\Projects\STM32F769I_EVAL\Examples\QSPI\QSPI_ReadWrite_DMA

This example describes how to erase part of a QSPI memory, write data in DMA mode, read data in DMA mode.

I hope my answer is helpful.

Please select my answer as Best if it fully answered your question.

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Ehill.16
Ehill.16Author
Senior
October 14, 2020

Thanks for the reply.

I added the QSPI_AutoPollingMemRead line to the QspiReadDataDMA function:

uint8_t QspiReadDataDMA(uint32_t address, uint32_t size, uint8_t *pData) {
	QSPI_CommandTypeDef s_command;
	QSPI_AutoPollingTypeDef s_config;
 
	/* 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 = address;
	s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
	s_command.AlternateBytes = 0;
	s_command.AlternateBytesSize = 0;
	s_command.DataMode = QSPI_DATA_4_LINES; // QSPI_DATA_4_LINES
	s_command.DummyCycles = 0;
	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 */
	printf("HAL_QSPI_Command\n");
	if (HAL_QSPI_Command(&hqspi, &s_command,
	HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
		printf("HAL_ERROR\n");
		return HAL_ERROR;
	}
 
	/* Reception of the data */
	printf("HAL_QSPI_Receive\n");
	if (HAL_QSPI_Receive_DMA(&hqspi, pData) != HAL_OK) {
		printf("HAL_ERROR\n"); // Timeout after 5000mS
		return HAL_ERROR;
	}
 
 /* Configure automatic polling mode to wait for end of program ----- */
 QSPI_AutoPollingMemReady(&hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
 
 
	return HAL_OK;
}

Here is the callback function:

void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi) {
	/* Prevent unused argument(s) compilation warning */
	//UNUSED(hqspi);
	RxCplt = 1;
}

This callback function never executes when the QspiReadDataDMA function is called.

ST Technical Moderator
October 15, 2020

Hello @Ehill.16​ ,

1- You should add this condition: while (RxCplt ==0); because the read transaction take time. So, you need to make sure that the read transaction has been completed before checking if the memory is ready (automatic polling mode): QSPI_AutoPollingMemReady(&hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);

uint8_t QspiReadDataDMA(uint32_t address, uint32_t size, uint8_t *pData) {
	QSPI_CommandTypeDef s_command;
	QSPI_AutoPollingTypeDef s_config;
 
	/* 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 = address;
	s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
	s_command.AlternateBytes = 0;
	s_command.AlternateBytesSize = 0;
	s_command.DataMode = QSPI_DATA_4_LINES; // QSPI_DATA_4_LINES
	s_command.DummyCycles = 0;
	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 */
	printf("HAL_QSPI_Command\n");
	if (HAL_QSPI_Command(&hqspi, &s_command,
	HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
		printf("HAL_ERROR\n");
		return HAL_ERROR;
	}
 
	/* Reception of the data */
	printf("HAL_QSPI_Receive\n");
	if (HAL_QSPI_Receive_DMA(&hqspi, pData) != HAL_OK) {
		printf("HAL_ERROR\n"); // Timeout after 5000mS
		return HAL_ERROR;
	}
 
while (RxCplt ==0); // add this condition 
 
 /* Configure automatic polling mode to wait for end of program ----- */
 QSPI_AutoPollingMemReady(&hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);
 
	return HAL_OK;
}

2 - Don't modify the HAL_QSPI_RxCpltCallback() function in the stm32f7xx_hal_qspi.c, you should add this function in the main.c :

void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi)
{
 RxCplt++;
}

I hope that is clear now for you.

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Ehill.16
Ehill.16Author
Senior
October 16, 2020

Thanks for your reply. I did add that while condition but the HAL_QSPI_RxCpltCallback never executes! I don't understand why. I am using the stm32746g_discovery_qspi.c initialization function.

ST Technical Moderator
October 16, 2020

Try to debug and localize where the code hangs/stop and the kind of message gives.

I suggest to start with the QSPI example available under STM32CubeF7 MCU package, to confirm if the problem here seems related to your hardware or software environment: STM32Cube_FW_F7_Vx.xx.x\Projects\STM32F769I_EVAL\Examples\QSPI\QSPI_ReadWrite_DMA

If the issue still exist, you can share you project code, to check your configuration setting.

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
Ehill.16
Ehill.16Author
Senior
October 17, 2020

The program works so far as writing to, reading from, and erasing the QUADSPI flash memory. For some reason the global QSPI interrupt is not firing and consequently either is the rx complete or the tx complete interrupts.

Ehill.16
Ehill.16Author
Senior
October 19, 2020

I am seeing a 1.6 MB/s transfer rate for writing the QSPI flash using HAL_QSPI_Transmit_DMA, and 38.7 MB/s reading the QSPI flash using HAL_QSPI_Receive_DMA. This seems about right.

But I can't measure the transfer rate using HAL_QSPI_Transmit and HAL_QSPI_Receive because the HAL_QSPI_TxCpltCallback and HAL_QSPI_RxCpltCallback are not triggered.

What do I need to do to get the callbacks to work with HAL_QSPI_Transmit and HAL_QSPI_Receive ?