cancel
Showing results for 
Search instead for 
Did you mean: 

Hard Fault calling SCB_DisableDCache() or SCB_CleanDCache()

iTTy
Associate III

Hi there.

As usual, I'm there with a new issue... :grinning_face_with_sweat:

Developing a custom Bootloader, I'm trying to disable both Instruction and Data chaches.

As I read on the ST AN4839, before deactivating the DCache, I would also Clean it.

No problem with the Icache, but I'm experiencing Hard Fault adding Dcache cleaning and/or disabling.

void DoJump2App(u32t uiAPPaddress)
{
	/*.-.-.| Local Varibles |.-.-.*/

	/*.-.-.| Execution |.-.-.*/
	SCB_DisableICache();
	SCB_CleanDCache();
	SCB_DisableDCache();
	
	uiResetKey = RESET_DRV_BTL_KEY;							// Clear RESET key
	pJump2App = (pFunction)(*(volatile u32t*)(uiAPPaddress + 4));

	__set_MSP(*(volatile u32t*)uiAPPaddress);				// Initialize user application's Stack Pointer
	__ISB();												// Instruction Synchronization Barrier
	pJump2App();
}

Above the example of the routine I'm testing.

To be noticed that:

  1. This routine is called just once in the main program after peripheral initialization (inside a more complex wrapping function)
  2. Cache memories are enabled in the main (as usual)
  3. If I move SCB_DisableDCache() and/or SCB_CleanDCache() functions call directly in the main program, prior this function, there is no problem...

What I'm mistaking?

Context: I'm working on a custom board quipped with an STM32H755BIT MCU, using CubeIDE 1.13.2, CubeMX6.9.2 and Firmware package STM32Cube FW_H7 V1.11.0

Thanks in advance for your support!

iTTy

 

 

2 REPLIES 2
STea
ST Employee

Hello @iTTy ,

You can try to add some memory barrier and instruction barrier instructions here is an example form which you can inspire:

void DoJump2App(uint32_t uiAPPaddress)
{
    /*.-.-.| Local Variables |.-.-.*/
    typedef void (*pFunction)(void);
    pFunction pJump2App;

    /*.-.-.| Execution |.-.-.*/
    __disable_irq(); // Disable interrupts

    // Disable ICache
    SCB_DisableICache();

    // Clean and disable DCache
    SCB_CleanDCache();
    __DSB(); // Data Synchronization Barrier
    SCB_DisableDCache();
    __DSB(); // Data Synchronization Barrier
    __ISB(); // Instruction Synchronization Barrier

    // Clear RESET key
    uiResetKey = RESET_DRV_BTL_KEY;

    // Set the jump address
    pJump2App = (pFunction)(*(volatile uint32_t*)(uiAPPaddress + 4));

    // Initialize user application's Stack Pointer
    __set_MSP(*(volatile uint32_t*)uiAPPaddress);

    // Instruction Synchronization Barrier
    __ISB();

    // Jump to application
    pJump2App();
}

 check also this article for tips on Hardfault debugging.
Regards

In order 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.
iTTy
Associate III

Hi @STea ,

thanks for your reply and for the interesting article you linked: I will study it better in next days!

Actually I didn't test your proposal because I moved misleading instruction in another place for "architectural" reasons...
I suppose, it will be anyway better to "bound" such instructions with synchronization boundaries as you proposed to improve the software reliability.

Anyway, for my understanding, what is the best practice/rationale to apply these boundaries? Where and when I should remember to apply them?

Thank you again,

iTTy