Skip to main content
Visitor II
February 1, 2024
Solved

STM32H730: Enabling caching on OCTOSPI RAM crashes the program

  • February 1, 2024
  • 4 replies
  • 2578 views

Dear Community,

I've got STM32H730 with ext Flash on OCTOSPI2 and ext RAM (s70kl1283) on OCTOSPI1.

I call  SCB_EnableICache(); and  SCB_EnableDCache(); early in main, then I configure the MPU.

I've got no problems executing code from ext Flash/OCTOSPI2 when MPU is configured as follows:

MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = OCTOSPI2_BASE;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER4;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

It has a big, measurable impact on the execution speed compared to non-cached OCTOSPI2 MPU configuration.

I can also execute code from ext RAM on OCTOSPI1 if I set MPU parameters as above, but disable buffering, caching and sharing. I tried enabling caching, enabling all options, playing with TEX LEVEL (basically trying to use various setting combinations from MPU docu in relevant Programmers Manual). I either crash on any RAM access or crash on RAM execution, depending on tested MPU settings (I didn't note precisely which setting set causes which outcome). And the CPU gets seemingly stuck in HAL TICK isr, doesn't even signal any MPU or whatever fault.

I tried invalidating cache after setting the MPU, configuring the MPU both when in bootloader or external image (when in external image, the MPU config fcn actually executes from within ITCM and problems start on 1st ext ram access).

I haven't noticed anything relevant in Errata sheet.

I'm quite lost in what direction should I investigate. 

 

Can those problems result from a different place- namely wrongly configuring OCTISPI1 parameters for the RAM chip? I'm pretty sure thy're OK but maybe I'm overlooking something here (I also tried setting the Refresh to 0). I'm operating the RAM chip at its defaults.

hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThreshold = 1;
hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_APMEMORY;
hospi1.Init.DeviceSize = 24;
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_32_BYTES;
hospi1.Init.ClockPrescaler = 4;
hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
hospi1.Init.ChipSelectBoundary = 10;
hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;
hospi1.Init.MaxTran = 0;
hospi1.Init.Refresh = 200;
if (HAL_OSPI_Init(&hospi1) != HAL_OK)
{
Error_Handler();
}
sOspiManagerCfg.ClkPort = 1;
sOspiManagerCfg.DQSPort = 1;
sOspiManagerCfg.NCSPort = 1;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}

 

I'd be grateful for any tips what could I check more or what I may be doing wrong.

 

PS- now that I think of it, the "stuck in HAL tick isr" without fault may be because I got to the point where bootloader jumps to ext ram, but waits indefinitely to fetch instructions for some reason. VTOR is not remapped yet so still points to bootloader ISRs so HAL tick gets fired periodically. Which would be weird because I do call HAL_SuspendTick before jumping, but well... As I said I'm a bit lost here.

    This topic has been closed for replies.
    Best answer by KDJEM.1

    Hello @sirpietruch and welcome to the community :),

    I think this issue is due to wrong sequence "I call  SCB_EnableICache(); and  SCB_EnableDCache(); early in main, then I configure the MPU." 

    The correct sequence is to configure MPU firstly, then enable cache.

    It is recommend to configure MPU before enabling the caches. This is because the MPU settings can be affect the behavior of the caches. 

    I think Level 1 cache on STM32F7 Series and STM32H7 Series application note can help to use cache.

    Thank you.

    Kaouthar

    4 replies

    Graduate II
    February 1, 2024

    It crashed or it faulted?

    Output details from fault. 

    Watch use of DCache Invalidate, can cause failure, use By Address variant to limit damaging behavior 

    Visitor II
    February 1, 2024

    Thank you for response, I used the By Address on entire OCTOSPI1 address space but that didn't change the behavior.

    And I'm afraid I don't have any fault output because there's no fault. Under debugger, it kind of looks to me as if the CPU was stuck waiting indefinitely for the bus transfer to complete, I'm not getting any mem/hard fault- Segger Ozone doesn't detect any, and I also don't see any in SCB registers.

     
    Wondering if there needs to be any alignment between memory wrap size and some cache requirements, because for external RAM on OCTOSPI1 (so the problematic memory) I have
    hospi1.Init.WrapSize = HAL_OSPI_WRAP_32_BYTES;
     
    and for external Flash on OCTOSPI2 I have
    hospi2.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
     
    KDJEM.1Answer
    Technical Moderator
    February 1, 2024

    Hello @sirpietruch and welcome to the community :),

    I think this issue is due to wrong sequence "I call  SCB_EnableICache(); and  SCB_EnableDCache(); early in main, then I configure the MPU." 

    The correct sequence is to configure MPU firstly, then enable cache.

    It is recommend to configure MPU before enabling the caches. This is because the MPU settings can be affect the behavior of the caches. 

    I think Level 1 cache on STM32F7 Series and STM32H7 Series application note can help to use cache.

    Thank you.

    Kaouthar

    Visitor II
    February 1, 2024

    Thank you very much!

    I will try this approach next time I have the chance to (which is next Monday) and will report back.

    If there's any more tips on what could I check as well, please write.

    Technical Moderator
    February 5, 2024

    Hi @sirpietruch ,

    Thank you for coming back to the Community and sharing the update.

    What do you mean by "ext ram execution unstable" ?

    Do you have a corrupted data? Can you please share a screenshot describing the issue?

    Please take a look at wrap errata in the errata sheet may help you.

    Thank you.

    Kaouthar

    Visitor II
    February 5, 2024

    Hi!

    Unfortunately I don't have any data to share, it's just when I apply the correct ordering of initialization but still have the wrap set to 32B I can spin in some text function located in external RAM for a while and then the debugger connection gets lost- therefore I can't read any possible fault details.

    It may be possible that the point 2.7.2 from Errata sheet applies (I had REFRESH set at 200), and definitely not 2.7.3, as I'm not using those registers at all.

    The problem disappears if I don't use the wrap function, just use linear bursts. It would be possible to do some investigation on the 2.7.2 from errata sheet but I'm afraid I don't have the time for it at the moment and just not using wrap is satisfactory.

    Thank you for your help!