2024-12-13 02:04 AM - edited 2024-12-13 02:17 AM
Hi all,
The goal is to read an external Flash memory connected to XSPI in Single-Mode. In the future, I will configure as memory-mapped, to see it as an extension memory of the MCU.
I have already set up the XSPI peripherals with hdmarx and hdmatx channel configured correctly. Now I have a problem when trying to read more than 32 bytes in a cycle. The DMA peripheral is aligned to 4 bytes wide.
I have seen that HAL_XSPI_FLAG_TE is set, then HAL_XSPI_ErrorCallback() is triggered.
Just to be sure, I read this in the reference manual. It seems to be used only when XSPI FIFO is used to transfer data... but in my case I am using DMA transfer.
Here are the steps I just took to read the bytes from an external FLASH memory.
#define CHUNK_SIZE 64U // Chunk size for each transfer
int QSPI_Read(FLASH_S25FL_t* _ctx)
{
uint8_t buffer[256] = {0xFF}; // Example buffer
uint32_t totalBytes = sizeof(buffer); // Total bytes to transfer
uint32_t offset = 0; // Offset for each chunk
while (totalBytes > 0)
{
uint32_t chunkLength = (totalBytes >= CHUNK_SIZE) ? CHUNK_SIZE : totalBytes;
chunkLength -= (chunkLength % 4); // Ensure multiple of 4
XSPI_RegularCmdTypeDef s_command = {0};
s_command.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
s_command.Instruction = S25FLXXXL_CMD_FAST_READ; // Adjust with your read command
s_command.AddressMode = HAL_XSPI_ADDRESS_1_LINE;
s_command.Address = 0 + offset;
s_command.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
s_command.DataMode = HAL_XSPI_DATA_1_LINE;
s_command.DataLength = chunkLength;
s_command.DummyCycles = 0;
s_command.DQSMode = HAL_XSPI_DQS_DISABLE;
if (HAL_XSPI_Command(_ctx->xspi, &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
printf("Error in command transmission.\n");
break;
}
if (HAL_XSPI_Receive_DMA(_ctx->xspi, &buffer[offset]) != HAL_OK)
{
printf("Error in data reception.\n");
break;
}
while (!data_received)
; // Wait for the DMA transfer to complete
offset += chunkLength;
totalBytes -= chunkLength;
}
/* Debug: Check the received data */
LOG_INFO("FLASH_READ: ");
for (int i = 0; i < (int)(sizeof(buffer)); i++)
{
LOG_INFO("0x%02x ", buffer[i]);
}
LOG_INFON();
return S25FLXXXL_OK;
}
/**
* @brief Command completed callback.
* hospi: OSPI handle
* @retval None
*/
void HAL_XSPI_CmdCpltCallback(XSPI_HandleTypeDef* hxspi)
{
// Set the state to CMD_CFG for Receive phase
hxspi->State = HAL_XSPI_STATE_CMD_CFG;
cmd_complete = 1; // Set flag when command phase completes
}
/**
* @brief Rx Transfer completed callback.
* hospi: OSPI handle
* @retval None
*/
void HAL_XSPI_RxCpltCallback(XSPI_HandleTypeDef* hxspi)
{
data_received = 1; // Set flag when data reception completes
}
/**
* @brief Tx Transfer completed callback.
* hospi: OSPI handle
* @retval None
*/
void HAL_XSPI_TxCpltCallback(XSPI_HandleTypeDef* hospi) { TxCplt++; }
/**
* @brief Transfer Error callback.
* hospi: OSPI handle
* @retval None
*/
void HAL_XSPI_ErrorCallback(XSPI_HandleTypeDef* hospi) { Error_Handler(); }
Just to clarify, when I tried to read 32 bytes, I can see the frame on the XSPI peripheral... Here is a screenshot of the logic analyzer. When I tried to read more than 32 bytes, I cannot even see the frame on the MCU pins.
Thank you :)
Solved! Go to Solution.
2024-12-13 06:13 AM
Hey,
After spending some time reviewing the OCTOSPI peripheral configuration, I realized that the memory size was configured incorrectly.
After changing it, it seems I can send any number of bytes through the DMA peripheral.
Thank you. I hope this will at least be useful for other people.
2024-12-13 05:11 AM
Hello @rubenax97 and welcome to the community;
The FIFO is sized into the targeted product, typically either 32 or 64 bytes depending on the product.
For the STM32H5 series, the FIFO size is 32 bytes.
If the burst size is 32 bytes, the FIFO threshold should be set to 32 bytes. In the read operation, when the FIFO accumulates 32 bytes of data, it triggers an interrupt or a DMA transfer to read the data.
Note that it is recommended to set the FIFO threshold to half of the FIFO size buffer to ensure that there is always sufficient space in the FIFO for receiving or sending a new burst of data.
For more explanation, look at How to configure FIFO with the OCTOSPI interface FAQ.
Is my reply answer your question?
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-12-13 06:13 AM
Hey,
After spending some time reviewing the OCTOSPI peripheral configuration, I realized that the memory size was configured incorrectly.
After changing it, it seems I can send any number of bytes through the DMA peripheral.
Thank you. I hope this will at least be useful for other people.