Skip to main content
Graduate
September 30, 2023
Solved

STM32 F7: lock flash CR and avoid bus fault

  • September 30, 2023
  • 4 replies
  • 4338 views

Hi,

On a STM32 F7, I would like to lock access to the FLASH_CR by writing a wrong key to the FLASH_KEYR register. Writing a wrong key results in a bus fault (disabling the bus fault raises it to a hard fault).

Could someone help me with a way to write a wrong key to FLASH_KEYR and mask the bus fault? I do not want to mask all bus faults (just this once when writing the wrong key).

__set_FAULTMASK(1);
FLASH->KEYR = 0;
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
__set_FAULTMASK(0);

This only works when stepping through a debugger but not in the regular cases.

Any suggestions would be greatly appreciated.
Thank you.

    This topic has been closed for replies.
    Best answer by waclawek.jan

    Read out some FLASH register after you've written FLASH_KEYR and before reenabling the fault.

    JW

    4 replies

    Super User
    September 30, 2023

    Read out some FLASH register after you've written FLASH_KEYR and before reenabling the fault.

    JW

    LeeKAuthor
    Graduate
    October 1, 2023

    Hi,

    Did you mean something like this?

    __set_FAULTMASK(1);
    FLASH->KEYR = 0;
    variable = FLASH->CR;
    SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
    __set_FAULTMASK(0);

    Wondering how this disables the bus fault.

    Super User
    October 1, 2023

    And does it?

    JW

    LeeKAuthor
    Graduate
    October 2, 2023

    Nope. Still enters the bus fault handler.

    Super User
    October 2, 2023

    Need to mask (ignore) bus faults: the snippet below is for STM32H7 :

     

     

    uint32_t mask = __get_FAULTMASK();
    __disable_fault_irq();
    SCB->CCR |= SCB_CCR_BFHFNMIGN_Msk;
    __DSB();
    /* do something */
    __DSB();
    
    if (SCB->SHCSR & SCB_SHCSR_BUSFAULTPENDED_Msk) {
     // oops it caused bus fault
     SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
    }
    
    SCB->CCR &= ~SCB_CCR_BFHFNMIGN_Msk;
    __set_FAULTMASK(mask);
    __enable_fault_irq();

     

     

     

     

    Super User
    October 2, 2023

    > Need to mask (ignore) bus faults:

    That's what I assume __set_FAULTMASK() in the original snippet does. I have no idea what all those macros/functions you are using resolve into, but I tried to interpret the "works while single stepping" as "the usual timing stuff, fault from bus system reached via later than code clearing/reenabling fault executed.

    There still may be hope in this hypothesis, maybe stuffing additional DSBs as in Pavel's code both before and after the lines writing to FLASH register (although I'd retain the readback, too).

    JW

     

    LeeKAuthor
    Graduate
    October 2, 2023

    Apologize waclawek.jan
    adding a FLASH register read (an extra ldr got added in assembly) actually solved the issue. I had some older debug code which was masking your solution.

    I will try adding additional DSBs as you and Pavel suggested.