2020-10-13 06:24 PM
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.
2020-10-14 07:17 AM
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
2020-10-14 08:37 AM
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.
2020-10-15 06:54 AM
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
2020-10-16 06:30 AM
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.
2020-10-16 09:55 AM
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
2020-10-16 09:21 PM
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.
2020-10-17 03:56 PM
Will this example work on the STM32F746G Discovery board?
2020-10-17 09:00 PM
Hi Imen,
Well, it is working, the Rx and Tx callback functions are firing and I can measure the time it takes to read and write QSPI flash memory. One thing, the Reading and writing of QSPI flash memory without DMA, doesn't cause the callbacks to execute. I am assuming that I probably need to disable the DMA channel for that to work? I am posting a code snippet of the case statements for writing and reading QSPI flash memory. The transfer rate seems a little slow. The write to flash is 127KB/s and reading flash is 632KB/s. Does this seem right?
switch (button) {// button is set in the GPIO callback function according to what button is pressed
case 1: // if 1 command ( command to write a const string to the QSPI Flash memory )
DWT->CYCCNT = 0;
start = DWT->CYCCNT; // get the core cycle count and store it in start variable
TxCplt = 0;
QspiWriteDataDMA(0, sizeof(aTxBuffer), aTxBuffer);
while (TxCplt ==0); // add this condition
finish = DWT->CYCCNT; // get the core cycle count and store it in finish variable
totalmS = (finish - start); // calculate the time it took in core cycles to send 140KB's
sprintf(result, " %d B/s ", CalcQSPITransRate(totalmS));// calculate transfer speed in bytes/second
ssd1306_SetCursor(2, 0);
ssd1306_WriteString("QSPI flash write:", Font_7x10, White);
ssd1306_SetCursor(0, 11);
ssd1306_WriteString(result, Font_7x10, White);
ssd1306_UpdateScreen();
button = 0;
break;
case 2: // if 2 command, read the QSPI Flash memory and send what was read to the USB
DWT->CYCCNT = 0;
start = DWT->CYCCNT; // get the core cycle count and store it in start variable
RxCplt = 0;
QspiReadDataDMA(0, sizeof(aDST_Buffer), aDST_Buffer);
while (RxCplt ==0); // add this condition
finish = DWT->CYCCNT; // get the core cycle count and store it in finish variable
totalmS = (finish - start); // calculate the time it took in core cycles to send 140KB's
sprintf(result, " %d B/s ", CalcQSPITransRate(totalmS));// calculate transfer speed in bytes/second
ssd1306_SetCursor(2, 22);
ssd1306_WriteString("QSPI flash read:", Font_7x10, White);
ssd1306_SetCursor(0, 33);
ssd1306_WriteString(result, Font_7x10, White);
ssd1306_UpdateScreen();
button = 0;
break;
Question, if I wanted to right the last page of the QSPI Flash memory, would I use 255 as the address?
Thanks so much for your help with this!
2020-10-17 09:01 PM
Now I am reading 1.4 MB/s.