XSPI in Single-Mode on STM32H5xx reads more than 32-byte in DMA mode
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 :)

