Skip to main content
Graduate II
July 3, 2024
Question

Hard Fault calling SCB_DisableDCache() or SCB_CleanDCache()

  • July 3, 2024
  • 1 reply
  • 1896 views

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

 

 

    This topic has been closed for replies.

    1 reply

    ST Employee
    July 8, 2024

    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

    iTTyAuthor
    Graduate II
    July 22, 2024

    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