cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 Flash Code Readout Protection

Danish1
Lead II
Posted on August 07, 2017 at 12:40

Are there any examples of enabling (level 1) and disabling code readout protection for stm32f7?

I have just tried this on an stm32f767 based on code that worked for stm32f4xx and I seem to have 'bricked' the microcontroller - my Rowley Crossconnect JTAG debugger cannot connect any more.

Enabling read-out protection with the following sequence seemed to work (although I did not get the log message I expected):

__attribute__ ((section('.fast')))

// attribute fast forces this code to be in RAM

void enableReadProtection(void) {    // this is destructive and hangs

    const char *rommessage = '\nCycle power to complete\n';

    char rammessage[40];

    char *message;

    FLASH_Status status = FLASH_COMPLETE;

    message = strcpy(rammessage, rommessage);

    logString('Enabling read-out protection: ');

    flush();

    NVIC->ICER[0] = 0xFFFFFFFF;

    NVIC->ICER[1] = 0xFFFFFFFF;

    NVIC->ICER[2] = 0xFFFFFFFF;

    ctl_global_interrupts_set(0);

//    FLASH_OB_Unlock();

    if((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != RESET) {     /* Authorizes the Option Byte register programming */

         FLASH->OPTKEYR = FLASH_OPT_KEY1;

         FLASH->OPTKEYR = FLASH_OPT_KEY2;

     }     status = FLASH_WaitForLastOperation_Fast();

&sharpif PROCESSOR_FAMILY == PROCESSOR_STM32F4 

    if(status == FLASH_COMPLETE) 

        *(__IO uint8_t*)OPTCR_BYTE1_ADDRESS = OB_RDP_Level_1; 

    *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= FLASH_OPTCR_OPTSTRT;

&sharpelif PROCESSOR_FAMILY == PROCESSOR_STM32F7 

    if (status == FLASH_COMPLETE) 

        *(__IO uint8_t*)OPTCR_BYTE1_ADDRESS = OB_RDP_LEVEL_1; 

    FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;  

&sharpendif /* PROCESSOR_FAMILY */    

/* Wait for last operation to be completed */ 

    status = FLASH_WaitForLastOperation_Fast();

//    FLASH_OB_Lock(); 

    FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;

// indicate completion 

    USART_TypeDef *usart_log = (USART_TypeDef *)bootloader_debug_usart; 

    while ((usart_log->USART_ISR_REGISTER & USART_ISR_REGISTER_TC) == 0) 

        { ; } 

    usart_log->USART_TDR_REGISTER = '0' + status; 

    while (*message != '\0') { 

        while ((usart_log->USART_ISR_REGISTER & USART_ISR_REGISTER_TC) == 0) 

            { ; } 

        usart_log->USART_TDR_REGISTER = *message++; 

    } 

    while (1) { 

// wait forever for manual power-cycling 

        __asm__ __volatile__ (' nop\n nop\n nop\n'); 

    }

}

And at this point I could disconnect and reattach the debugger. Although (of course) I was unable to download fresh code to FLASH.

So now I tried the following code (I couldn't find any examples directly aimed at readout protection in the Cube examples for F7 v1.7.0 so I loosely based it on the FLASH_PcropProtection example)

uint32_t SystemCoreClock; 

int main(void) {

&sharpif PROCESSOR_FAMILY == PROCESSOR_STM32F4

    FLASH_Status protector; 

    FLASH_OB_Unlock(); 

    FLASH_OB_WRPConfig(OB_WRP_Sector_All, DISABLE);

/*     protector = */FLASH_OB_RDPConfig(OB_RDP_Level_0); 

    protector = FLASH_OB_Launch(); 

    FLASH_OB_Lock(); 

    logU(protector);

&sharpelif PROCESSOR_FAMILY == PROCESSOR_STM32F7 

    SystemCoreClock = 16000000; 

    HAL_InitTick(TICK_INT_PRIORITY); 

    HAL_StatusTypeDef protector; 

    FLASH_OBProgramInitTypeDef obInit;     /* Allow Access to option bytes sector */ 

    HAL_FLASH_OB_Unlock();      /* Allow Access to Flash control registers and user Flash */ 

    HAL_FLASH_Unlock();

    obInit.OptionType = OPTIONBYTE_RDP; 

    obInit.WRPState   = OB_RDP_LEVEL_0; 

    HAL_FLASHEx_OBProgram(&obInit);      /* Start the Option Bytes programming process */ 

    protector = HAL_FLASH_OB_Launch();      /* Prevent Access to option bytes sector */     HAL_FLASH_OB_Lock();      /* Disable the Flash option control register access (recommended to protect     the option Bytes against possible unwanted operations)

*/     HAL_FLASH_Lock(); 

    logU(protector);

&sharpendif /* PROCESSOR_FAMILY */ 

    logString(' Unlock Complete\n'); 

    return 0;

}

And from that point on I couldn't attach / reattach the debugger. I've tried wiring BOOT0 to Vdd. So I guess this particular processor is 'bricked' (much as if I put readout protection to level 2).

For now I shall move to my next board, and (unless people can give any other suggestions) arrange to have a new processor fixed to my first board.

But am I doing wrong?

What should I be doing the set readout protection to level 1 and then back to level 0?

 - Danish

#stm32f7 #flash-rdp
4 REPLIES 4
Amel NASRI
ST Employee
Posted on August 07, 2017 at 15:16

Hi

Ali.Danish

‌,

Are you able to connect to your board and unlock it using the STLink Utility?

-Amel

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.

Posted on August 07, 2017 at 15:38

Thanks for your interest.

I haven't tried ST-Link because:

  1. I don't have an STLink JTAG/SWD debugger. (I guess I could get one to try to find out if that will fix the problem. I like the idea of an opto-isolated jtag interface if ever I do anything that involves high-voltages (to protect the PC) or small analog signals, and I think ST-Link/v2-ISOL one is the only one I've seen listed).
  2. My board is a custom board with breakout to standard 20-pin JTAG connector rather than one of the ST demo boards which has a 2nd microcontroller acting as the STLink hardware.
  3. Looking at the ST-Link User Manual UM0892 Revision 23 dated July 2017 section 1.2, I see stm32f7 is NOT in the list of parts it is designed to work with. This could be a typo.

One other thing I have not tried (but might be possible) is to tie BOOT0 high and see if I can connect over e.g. RS232 using the STM32 bootloader protocol. But I would have thought that when executing from the bootloader from power-on, JTAG should (to some extent) be enabled. Unless code-readout-protection level 2 was somehow invoked.

Does the bootloader spontaneously emit anything on coming-out-of reset on any of the interfaces, or only in response to incoming signals? (So I could look for activity on a specific pin with 'scope).

 - Danish

Jorge Guzman1
Associate
Posted on May 07, 2018 at 22:04

Ran into the very same problem recently with an STM32F303.

Its reference manual mentions:

'

If the read protection is set while the debugger is still connected through JTAG/SWD, apply a POR (power-on reset) instead of a system reset.

'

The solution is therefore to turn off the power to the STM32, and then turn it back on. Your firmware will then run just as well as before.
kirem
Associate II
Posted on May 07, 2018 at 22:51

Hi Danish,

From your example you might be using an uninitialised structure:

    FLASH_OBProgramInitTypeDef obInit;     /* Allow Access to option bytes sector */ 

    HAL_FLASH_OB_Unlock();      /* Allow Access to Flash control registers and user Flash */ 

    HAL_FLASH_Unlock();

    obInit.OptionType = OPTIONBYTE_RDP; 

    obInit.WRPState   = OB_RDP_LEVEL_0; 

    HAL_FLASHEx_OBProgram(&obInit);      /* Start the Option Bytes programming process */ 

obInit structure is as follows:

typedef struct

{

uint32_t OptionType; /*!< Option byte to be configured.

This parameter can be a value of @ref FLASHEx_Option_Type */

uint32_t WRPState; /*!< Write protection activation or deactivation.

This parameter can be a value of @ref FLASHEx_WRP_State */

uint32_t WRPSector; /*!< Specifies the sector(s) to be write protected.

The value of this parameter depend on device used within the same series */

uint32_t Banks; /*!< Select banks for WRP activation/deactivation of all sectors.

This parameter must be a value of @ref FLASHEx_Banks */

uint32_t RDPLevel; /*!< Set the read protection level.

This parameter can be a value of @ref FLASHEx_Option_Bytes_Read_Protection */

uint32_t BORLevel; /*!< Set the BOR Level.

This parameter can be a value of @ref FLASHEx_BOR_Reset_Level */

uint8_t USERConfig; /*!< Program the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. */

} FLASH_OBProgramInitTypeDef;

it's likely that the other fields in the structure are not set correctly.

did you resolve your problem?

Regards, Kirem