Skip to main content
Explorer II
December 13, 2024
Solved

XSPI in Single-Mode on STM32H5xx reads more than 32-byte in DMA mode

  • December 13, 2024
  • 2 replies
  • 1028 views

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.

rubenax97_0-1734083996268.png

 

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.

rubenax97_0-1734084782980.png

 

Thank you :)

    This topic has been closed for replies.
    Best answer by rubenax97

    Hey,

     

    After spending some time reviewing the OCTOSPI peripheral configuration, I realized that the memory size was configured incorrectly.

    rubenax97_0-1734098941912.png

    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.

    2 replies

    Technical Moderator
    December 13, 2024

    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

    rubenax97AuthorAnswer
    Explorer II
    December 13, 2024

    Hey,

     

    After spending some time reviewing the OCTOSPI peripheral configuration, I realized that the memory size was configured incorrectly.

    rubenax97_0-1734098941912.png

    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.