Skip to main content
Associate II
July 5, 2024
Question

STM32H750IB getting into persistent problem with SCB_EnableDCache

  • July 5, 2024
  • 4 replies
  • 5736 views

Hi, We've been using a board (the Daisy Seed) that has an STM32H750IB and external QSPI flash chip.

We're having an issue with some of the boards somehow getting into a persistent (across reset. power cycle, and chip erase) state whereby the SCB_EnableDCache function is taking several seconds to execute.  Even stranger, when DCaching is disabled, then the QSPI init call takes several seconds.   Most of the boards are working fine, but somehow something happens and the board/chip will start doing this.  In one case, it just as randomly stopped doing it. 

    Could some kind of un-initialized variable be causing this?

     Also, we're using an older version of CMSIS code (Ver 5.0.1), has anything been fixed or changed in the newer versions?

 

4 replies

Pavel A.
July 5, 2024

Do you use the "speculative execution" workaround with the MPU? If not, try it. Also check whether your STM32H750 are revision Y?

TallMikeAuthor
Associate II
July 5, 2024

Hi, and thanks for the response.  I don't think it' the Y revision, at least none of the letters on the part number were a 'Y', how do we know for sure?

Regarding the 'speculative execution' workaround, specifically how do I do it?  I'll give it a try.

 

Pavel A.
July 5, 2024

See AN4838 section 3.4 Cortex-M7 constraint speculative prefetch.

Rev. Y can be detected from code: 

// Returns false if unsupported MCU
bool is_supported_mcu(void)
{
 if (HAL_GetDEVID() != 0x450)
 {
 // Not STM32H75... - unsupported
 return false;
 }
 if (HAL_GetREVID() < 0x2000)
 {
 // This is how rev. Y detected in system_stm32h7xx.c in CubeH7 examples
 return false;
 }
 return true;
}
Tesla DeLorean
Guru
July 5, 2024

Unfortunately the stripped schematic is next to useless

https://electro-smith.com/products/daisy-seed   https://daisy.nyc3.cdn.digitaloceanspaces.com/products/seed/ES_Daisy_Seed_Rev7.pdf

 

I don't think the caching should be that broken, setting up the MPU rules,enabling the QSPI Memory Mapping, should be sufficient for DCache to work properly.

Show the minimal code bringing up the memory

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
TallMikeAuthor
Associate II
July 5, 2024

Thanks for your response, and yes, the schematic isn't very helpful,  though I think it's a pretty standard design.

The strangest aspect of this issue is that it's working fine for most boards and most people most of the time.  It happened to me once on one board, and then after doing a Chip Erase, it went back to a 'working' state, and now it randomly started happening on another board and I haven't been able to get it back by chip erase, etc.  So that's the most puzzling part.  This board has been out for several years now, so it's obviously not a very common problem, though several other people have reported it.

 

In terms of the code, it's the Blink example from the DaisyExamples:  https://github.com/electro-smith/libDaisy

Here's the memory initialization code:  (libDaisy\src\sys\system.cpp)

void System::ConfigureMpu()
{
 MPU_Region_InitTypeDef MPU_InitStruct;
 HAL_MPU_Disable();
 // Configure RAM D2 (SRAM1) as non cacheable
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.BaseAddress = 0x30000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER0;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
 MPU_InitStruct.SubRegionDisable = 0x00;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER1;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
 MPU_InitStruct.BaseAddress = 0xC0000000;
 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 // Configure the backup SRAM region as non-cacheable
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER2;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
 MPU_InitStruct.Size = MPU_REGION_SIZE_4KB;
 MPU_InitStruct.BaseAddress = 0x38800000;
 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

 

And here's the overall init function: (libDaisy\src\sys\system.cpp)

As far as I can tell, it's doing the 'if (!config.skip_clocks)' code.

void System::Init(const System::Config& config)
{
 cfg_ = config;
 HAL_Init();
 if(!config.skip_clocks)
 {
 ConfigureClocks();
 ConfigureMpu();
 }
 dsy_dma_init();
 dsy_i2c_global_init();
 dsy_spi_global_init();
 dsy_uart_global_init();

 // Initialize Caches
 if(config.use_dcache)
 SCB_EnableDCache();
 if(config.use_icache)
 SCB_EnableICache();

 // Configure and start highspeed timer.
 // TIM 2 counter UP (defaults to fastest tick/longest period).
 TimerHandle::Config timcfg;
 timcfg.periph = TimerHandle::Config::Peripheral::TIM_2;
 timcfg.dir = TimerHandle::Config::CounterDir::UP;
 tim_.Init(timcfg);
 tim_.Start();

 // Initialize the true random number generator
 Random::Init();
}

 

 

TallMikeAuthor
Associate II
July 5, 2024

Update: Interesting and unsettling new data point:
I plugged and unplugged the Daisy Seed board (stand-alone, using the on-board USB port) about 20 times, and it suddenly started behaving again!

TallMikeAuthor
Associate II
July 25, 2024

Just to follow up: It appears that the EnableDCache was a Red Herring and the real issue appears to be with the QSPI flash sometimes randomly getting set to Write Protect mode due to some tweaky startup/GPIO timing.