cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750IB getting into persistent problem with SCB_EnableDCache

TallMike
Associate III

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?

 

23 REPLIES 23
Pavel A.
Evangelist III

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

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
Up vote any posts that you find helpful, it shows what's working..

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.

 

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;
}

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();
}

 

 

Hi,

> how do we know for sure?

just look on your chip: is there a "single" V or Y on it ? (right/bottom in pic , here V .) 

AScha3_0-1720207337548.png

 

If you feel a post has answered your question, please click "Accept as Solution".

There's neither a V or Y or anything after the 'VQ'

 

Its somewhere... just a single letter, V or Y or Z ...

V:

AScha3_0-1720209926662.png

Z:

AScha3_1-1720210063031.png

 

If you feel a post has answered your question, please click "Accept as Solution".

VQ is the Fab/Diffusion Line,  "VQ" for ST Crolles CR300 (France)

An any case a quick, in-focus picture would clear this up quickly.

A large number of Y parts for the H74x/H75x have shipped in recent years.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..