cancel
Showing results for 
Search instead for 
Did you mean: 

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

rubenax97
Associate

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 :)

1 ACCEPTED SOLUTION

Accepted Solutions
rubenax97
Associate

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.

View solution in original post

2 REPLIES 2
KDJEM.1
ST Employee

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.

rubenax97
Associate

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.