AnsweredAssumed Answered

STM32F7 Flash Code Readout Protection

Question asked by Danish Ali on Aug 7, 2017
Latest reply on May 7, 2018 by Jorge Guzman

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();
#if 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;
#elif PROCESSOR_FAMILY == PROCESSOR_STM32F7 
    if (status == FLASH_COMPLETE) 
        *(__IO uint8_t*)OPTCR_BYTE1_ADDRESS = OB_RDP_LEVEL_1; 
    FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;  
#endif /* 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) {
#if 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);
#elif 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);
#endif /* 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

Outcomes