Skip to main content
Visitor II
January 4, 2021
Question

STM32H7B3I-DK OctoSPI Memory Mapped Mode disable/enable problem

  • January 4, 2021
  • 7 replies
  • 5159 views

I've created a project using STM32H7B3I-DK eval board with all settings default, unmodified, taken from TouchGFX. UI menu is working fine with some resources stored in OSPI Flash memory.

Now I wish to store some data in this OSPI memory. The procedure should be to disable Memory Mapped Mode, erase, write and enable Memory Mapped Mode again. All this I do with task switch disabled so that TouchGFX doesn't access OSPI Flash during the process.

I have problems with switching from Memory Mapped Mode to Indirect Mode and returning to MMP again.

I have modified MX_OCTOSPI1_Init() function by adding a test loop at the end to use it as a test procedure (memory settings are not modified).

static void MX_OCTOSPI1_Init(void)

{

 /* USER CODE BEGIN OCTOSPI1_Init 0 */

 /* USER CODE END OCTOSPI1_Init 0 */

 /* USER CODE BEGIN OCTOSPI1_Init 1 */

 /* USER CODE END OCTOSPI1_Init 1 */

 /* OCTOSPI1 parameter configuration*/

 hospi1.Instance = OCTOSPI1;

 hospi1.Init.FifoThreshold = 1;

 hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;

 hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;

 hospi1.Init.DeviceSize = 26;

 hospi1.Init.ChipSelectHighTime = 2;

 hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;

 hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;

 hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;

 hospi1.Init.ClockPrescaler = 3;

 hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;

 hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;

 hospi1.Init.ChipSelectBoundary = 0;

 hospi1.Init.ClkChipSelectHighTime = 0;

 hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;

 hospi1.Init.MaxTran = 0;

 hospi1.Init.Refresh = 0;

 if (HAL_OSPI_Init(&hospi1) != HAL_OK)

 {

   Error_Handler();

 }

 /* USER CODE BEGIN OCTOSPI1_Init 2 */

 BSP_OSPI_NOR_Init_t Flash;

 Flash.InterfaceMode = BSP_OSPI_NOR_OPI_MODE;

 Flash.TransferRate = BSP_OSPI_NOR_DTR_TRANSFER;

 BSP_OSPI_NOR_DeInit(0);

 int32_t RetVal = BSP_OSPI_NOR_Init(0, &Flash);

 if(RetVal != BSP_ERROR_NONE)

 {

   Error_Handler();

 }

 RetVal = BSP_OSPI_NOR_EnableMemoryMappedMode(0);

 if(RetVal != BSP_ERROR_NONE)

 {

   Error_Handler();

 }

//test loop

 #define BLOCK_SIZE 4096

 static uint8_t blockBuf[BLOCK_SIZE];

 for(int i = 5; i < 15; i++)

 {

   bool ok = true;

   if(BSP_OSPI_NOR_DisableMemoryMappedMode(0) != BSP_ERROR_NONE) ok = false;

   if(BSP_OSPI_NOR_Erase_Block(0, 0, MX25LM51245G_ERASE_4K) != BSP_ERROR_NONE) ok = false;

   if(BSP_OSPI_NOR_EnableMemoryMappedMode(0) != BSP_ERROR_NONE) ok = false;

   memcpy(blockBuf, (uint8_t*)0x90000000, BLOCK_SIZE);

   //now I expect to see 0xff... in the buffer

   if(BSP_OSPI_NOR_DisableMemoryMappedMode(0) != BSP_ERROR_NONE) ok = false;

   memset(blockBuf, i, BLOCK_SIZE); //put some data to the buffer

   if(BSP_OSPI_NOR_Write(0, blockBuf, 0, BLOCK_SIZE) != BSP_ERROR_NONE) ok = false;

   memset(blockBuf, 0, BLOCK_SIZE); //clear buffer

   if(BSP_OSPI_NOR_EnableMemoryMappedMode(0) != BSP_ERROR_NONE) ok = false;

   memcpy(blockBuf, (uint8_t*)0x90000000, BLOCK_SIZE);

   //now I expect to see data in the buffer, but I see 0xff...

 }

 /* USER CODE END OCTOSPI1_Init 2 */

}

I can see memory block being erased, but not written. If I remove Memory Mapped Mode enter/exit functions memory erase and write works fine.

Do you know a reason for that?

    This topic has been closed for replies.

    7 replies

    Visitor II
    February 23, 2021

    Hi Tomasz Ozon,

    I have exactely the same issue with this DK, did you get a reply for that please?

    Thanks

    Visitor II
    February 23, 2021
    Hi,
    I have not received any help from ST and I have not investigated this issue further (due to work on other project). But in future I will need to solve this problem.
    Explorer II
    February 24, 2021

    Didn't check what's inside BSP_OSPI_NOR_DisableMemoryMappedMode but:

    First, set ABORT bit and wait until BUSY gets cleared (with a reasonable timeout). If BUSY sticks at 1, clear EN and then set it again. If that still doesn't help, last resort would be to reset OctoSPI via RCC_AHB3RSTR register.

    I didn't encounter any similar problem yet, as I always do an ABORT before changing *anything*. When you skim through the errata sheets (not just the one for H7A/B !!!), there are suggestions mentioning the way via ABORT and EN.

    Another point: Avoid accessing the last few bytes of the external flash in memory mapped mode. On some devices this causes a complete stall of the interface, on some others only 0 is returned regardless of the actual contents.

    Visitor II
    February 26, 2021

    Hi,

    Please find bellow what is inside BSP_OSPI_NOR_DisableMemoryMappedMode :

    /**

     * @brief Exit form memory-mapped mode

     *     Only 1 Instance can running MMP mode. And it will lock system at this mode.

     * @param Instance OSPI instance

     * @retval BSP status

     */

    int32_t BSP_OSPI_NOR_DisableMemoryMappedMode(uint32_t Instance)

    {

     int32_t ret = BSP_ERROR_NONE;

     /* Check if the instance is supported */

     if(Instance >= OSPI_NOR_INSTANCES_NUMBER)

     {

      ret = BSP_ERROR_WRONG_PARAM;

     }

     else if(Ospi_Nor_Ctx[Instance].IsInitialized != OSPI_ACCESS_MMP)

     {

      ret = BSP_ERROR_OSPI_MMP_UNLOCK_FAILURE;

     }/* Abort MMP back to indirect mode */

     else if(HAL_OSPI_Abort(&hospi_nor[Instance]) != HAL_OK)

     {

      ret = BSP_ERROR_PERIPH_FAILURE;

     }

     else

     {

      /* Update OSPI context if all operations are well done */

      Ospi_Nor_Ctx[Instance].IsInitialized = OSPI_ACCESS_INDIRECT;

     }

     /* Return BSP status */

     return ret;

    }

    It seems that abord is well done.

    For your information I had a ticket on support, I get an answer few hours later asking me my company name, since no answer... Maybee the volume is not enough interesting to get an answer.

    Explorer II
    February 26, 2021

    "It seems that abord is well done." doesn't help to prove or disprove your conjecture that the memory mapped mode is causing the trouble. Did you acually *verify* (e.g. by single stepping and inspecting the SR) that the ABORT is indeed done as desired? What I meant is:

    1) Do an ABORT explicitly (in our own code) before any of your problematic program/erase operations. If this doesn't cure the problem

    2) Clear, then set EN (in your own code) in the same way. If this still doesn't help

    3) Reset the OSPI in the same way.

    If the problem still persists, it is most probably not related to the memory mapped mode. If if goes away, you have a workaround (and if you've got enough time, you might dig into the problem further).

    Visitor II
    February 26, 2021

    Ok, I will try another time with what you suggest and give you the result with more details on Monday. Thanks for your help.

    Visitor II
    April 1, 2021

    Hello,

    I get a reply from support, please find attached project.

    You need to insert the following API into int32_t BSP_OSPI_NOR_Erase_Block(uint32_t Instance, uint32_t BlockAddress, BSP_OSPI_NOR_Erase_t BlockSize)

    /* Issue Block Erase command */

    if(MX25LM51245G_BlockErase(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode, Ospi_Nor_Ctx[Instance].TransferRate, MX25LM51245G_4BYTES_SIZE, BlockAddress, BlockSize) != MX25LM51245G_OK)

    {

    ret = BSP_ERROR_COMPONENT_FAILURE;

    }

    /*insert this API*/

    if(MX25LM51245G_AutoPollingMemReady(&hospi_nor[Instance], Ospi_Nor_Ctx[Instance].InterfaceMode, Ospi_Nor_Ctx[Instance].TransferRate) != MX25LM51245G_OK)

    {

    ret = BSP_ERROR_COMPONENT_FAILURE;

    }

    Best regards,

    Grégory

    Visitor II
    April 1, 2021

    I do not know how to insert project, if you need it do not hesitate to contact me.

    Graduate II
    April 1, 2023

    Hi,

    I was having the same issue and the only solution I found is to Deinit and Re Init the perpheral again but force it to indirect mode!

        HAL_OSPI_DeInit(&hospi1);

        HAL_OSPI_Init(&hospi1);

    I don't know why Abort function doesn't work in OSPI while it is working perfectly in QSPI periph. Really biiig question???

    Inside HAL_OSPI_Init, you should set this instruction:

    /* Go to Indirect mode. Always Init as Indirect Mode */

       MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_TCEN | OCTOSPI_CR_FMODE),

          (0x00 | 0x00));

    I am using it for XIP but doesn't work with big frequencies as the switch takes place many times.

    Graduate II
    March 21, 2024

    Have the same issue here.
    The HAL_OSPI_Abort is not doing the right thing.
    The quick workaround in my case was just reinitialize the OctoSPI. Is a big penalty resource in terms of time to execute it.