cancel
Showing results for 
Search instead for 
Did you mean: 

How to make QSPI transmission without delay between Command and Data?

Irek
Associate III

I need to communicate with FPGA by QuadSPI. I use the NUCLEO-H743ZI2 and FreeRTOS with STM32Cub IDE.
So my code to write data to FPGA looks next:

uint32_t qspi_write(const uint8_t* RXbuf, uint8_t* TXbuf, uint16_t* tx_length) { sCommand.InstructionMode = QSPI_INSTRUCTION_NONE; /* Specifies the Instruction Mode: value of @ref QSPI_InstructionMode */ sCommand.Instruction = 0; /* Specifies the Instruction to be sent: value (8-bit) between 0x00 and 0xFF */ sCommand.AddressMode = QSPI_ADDRESS_4_LINES; /* Specifies the Address Mode: value of @ref QSPI_AddressMode */ sCommand.AddressSize = QSPI_ADDRESS_32_BITS; /* Specifies the Address Size: value of @ref QSPI_AddressSize */ sCommand.Address = *(uint32_t *) RXbuf; /* Specifies the Address to be sent (Size from 1 to 4 bytes according AddressSize): value (32-bits) between 0x0 and 0xFFFFFFFF */ sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; /* Specifies the Alternate Bytes Mode: value of @ref QSPI_AlternateBytesMode */ sCommand.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS; /* Specifies the Alternate Bytes Size: value of @ref QSPI_AlternateBytesSize */ sCommand.AlternateBytes = 0; /* Specifies the Alternate Bytes to be sent (Size from 1 to 4 bytes according AlternateBytesSize): value (32-bits) between 0x0 and 0xFFFFFFFF */ sCommand.DummyCycles = 1; /* Specifies the Number of Dummy Cycles: number between 0 and 31 */ sCommand.DataMode = QSPI_DATA_4_LINES; /* Specifies the Data Mode (used for dummy cycles and data phases): value of @ref QSPI_DataMode */ sCommand.NbData = (uint32_t) *tx_length; /* Specifies the number of bytes to transfer: value between 0 and 0xFFFFFFFF (0 means undefined length until end of memory)*/ sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; /* Specifies the double data rate mode for address, alternate byte and data phase: value of @ref QSPI_DdrMode */ sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; /* Specifies if the DDR hold is enabled: value of @ref QSPI_DdrHoldHalfCycle */ sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Specifies the send instruction only once mode: value of @ref QSPI_SIOOMode */ configPRINTF( ("qspi: Command to Address = 0x%08x\n", sCommand.Address) ); HAL_StatusTypeDef result = HAL_QSPI_Command(&hqspi, &sCommand, QSPI_TIMEOUT_VALUE); if ( result != HAL_OK ) { qspi_error_handler(result); return result; } configPRINTF( ("qspi: Transmit NbData = %d\n", (uint16_t) *tx_length) ); // result = HAL_QSPI_Transmit(&hqspi, TXbuf, QSPI_TIMEOUT_VALUE); result = HAL_QSPI_Transmit_IT(&hqspi, TXbuf); if ( result != HAL_OK ) { qspi_error_handler(result); return result; } return HAL_QSPI_ERROR_NONE; }
View more

As result, I see by Logic Analyser the next picture:
Untitled.png
The first burst of clocks corresponds to the transmission if Command, the 2nd - to the Data. The gap between two bursts  is about 0.76 mks in the case of using of HAL_QSPI_Transmit_IT and 1.5 mks in case of HAL_QSPI_Transmit which is somehow strange.
But the main question how I have to organize QSPI transmission without delay between Command and Data?


14 REPLIES 14
CTapp.1
Senior II

Possibly a silly question, but how long does the call to configPRINTF() take?

@CTapp.1 
If I comment the all configPRINTF() in the code the gap between burst do not change - this I tested before writing a post. 
I should mention that my previous project on the same board was used MBed OS - and there was not any gap inside QSPI transmissions. So STM32H7 hardware is able to transmit without any gap/delay. So how to program the same in the FreeRTOS?

 

urbito
Senior II

i am on the same page as CTapp.1, you should not have those "prints" on a transmission, normally those kind of prints add a delay around 50/100ms.

Irek
Associate III

@urbito :
Ok, I have to repeat test. Here is results: 

Code:

// configPRINTF( ("qspi: Command to Address = 0x%08x\n", sCommand.Address) ); HAL_StatusTypeDef result = HAL_QSPI_Command(&hqspi, &sCommand, QSPI_TIMEOUT_VALUE); // if ( result != HAL_OK ) { // qspi_error_handler(result); // return result; // } // configPRINTF( ("qspi: Transmit NbData = %d\n", (uint16_t) *tx_length) ); // result = HAL_QSPI_Transmit(&hqspi, TXbuf, QSPI_TIMEOUT_VALUE); result = HAL_QSPI_Transmit_IT(&hqspi, TXbuf); // if ( result != HAL_OK ) { // qspi_error_handler(result); // return result; // } return HAL_QSPI_ERROR_NONE;

Logic Analyser:
Untitled.png

Inspect HAL_QSPI_Command source and construct a multi-byte variant 

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

I tried to combine the HAL_QSPI_Command and HAL_QSPI_Transmit functions in a single function without additional conditional checks or __HAL_LOCK like functions use.
The result is the same - I see the gap between Command and Data sections during QSPI transmission. 

I looked the MBed's realization of the qspi.write - they use same HAL functions:

if (HAL_QSPI_Command(&obj->handle, &st_command, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { status = QSPI_STATUS_ERROR; } else { if (HAL_QSPI_Transmit(&obj->handle, (uint8_t *)data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { status = QSPI_STATUS_ERROR; } }

So obviously either I or FreeRTOS configure some QSPI registers in a wrong way. But I did not find in STM's manuals any explanation about delay between Command and Data transmission.

Any idea what should I check now?

 

 

Could it be that FreeRTOS performs a task switch after the command is initiated and the task waits for completion ?

Irek
Associate III

@Ozone 
I don't think so - as I understand it, FreeRTOS switches tasks using Ticks, which is 1 ms. In this case gap between Command and Data is 0.8-1.6 mks - much smaller. But I am just beginner in using FreeRTOS so I do not know many details... 

Many RTOSes switch to other tasks if the currently running one is waiting for a signal/event to occur.
A lot depends on configuration and task setup.