cancel
Showing results for 
Search instead for 
Did you mean: 

How to remove Read Protection (Level1->0) by an external SWD prgrammer?

gmravil
Associate II
Posted on February 23, 2015 at 12:25

I am making a stand-alone SWD programmer for STM32F1 and L1 families, based on STM32F103. For that I have used AN0062 ''

Programming Internal Flash

Over the Serial Wire Debug

Interface

'' by Silicon Labs. Everything works fine and the final touch I need to implement is the ability to re-program read-protected targets. However, the procedure to lower the Read Protection (RDP) from Level 1 to Level 0, described in the Reference Manual for STM32F1/L1 requires to read and write into Flash controller registers inside the target, that is prohibited by the Read Protection itself.

Does anybody knows a correct way to set the RDP to Level0 by means of an external custom SWD programmer?

Thanks!

#rdp #swd
7 REPLIES 7
damh
Associate II
Posted on February 23, 2015 at 13:12

Unlock RDP:

1. unlock flash

2. unlock option bytes

3. erase option bytes

4. write new read out protection value

5. reset (or for some systems: relaunch option bytes (with implicit reset))

6. program flash

[FLASH, RCC, PWR, ... are readable and writeable. With RDP, too]
gmravil
Associate II
Posted on February 24, 2015 at 06:16

Thanks for response, damh!

I just have tried it, with no success. As soon I start to unlock the Flash, i.e. read the FLASH->PECR register:

flash_PECR = readMem(FLASH_PECR_ADDR);

where

uint32_t readMem(uint32_t addr)

{

  uint32_t ret;

  writeAP(AP_TAR, addr);

  readAP(AP_DRW, &ret);

  readDP(DP_RDBUFF, &ret);

  return ret;

}

and

#define FLASH_PECR_ADDR        0x40023C04

i get the FAULT ack by SWD at the first

writeAP(AP_TAR, addr);

inside readMem().

Also, I have tried to write to the FLASH_PEKEYR_ADDR immediately without reading anything from the Flash controller inside the target. Also without success - the first use of  writeAP(AP_TAR, addr); causes the SWD's FAULT ack.

Some other things I did unsuccessfully try too:

. read (or write) OB_RDP_ADDR

. read FLASH_OBR_ADDR

. read RAM (0x20000000)

At the same time, the ST-LINK Utility removes the RDP on my target without a hitch.

Am I doing something wrong?

Thanks in advance!

damh
Associate II
Posted on February 24, 2015 at 06:53

hmm :\

you can try to write a small program to run from RAM. Can you read/write the RAM?
gmravil
Associate II
Posted on February 24, 2015 at 12:04

Sorry for misinformation.

It was my error. I forgot to clear SWD's error sticky bit after getting the first FAULT ack from a read-protected target. After clearing the sticky bit I got the access to the Flash controller registers on the target.

(BTW, the target is STM32F107/)

However, now I can't remove the Read Protection. Writing the RDP_Key (0x00A5) goes without errors, but after target's power-reseting the RDP is still enabled.

The code is:

FLASH_Status flashEraseAllOptionBytes(void)

{

    FLASH_Status status = FLASH_COMPLETE;

    status = flashWaitForLastOperation(EraseTimeout);

    if(status == FLASH_COMPLETE)

    {

        // Authorize the small information block programming

//        FLASH->OPTKEYR = FLASH_KEY1;

//        FLASH->OPTKEYR = FLASH_KEY2;

        writeMem((uint32_t)&(FLASH->OPTKEYR), FLASH_KEY1);

        writeMem((uint32_t)&(FLASH->OPTKEYR), FLASH_KEY2);

        uint32_t flash_CR;

        // if the previous operation is completed, proceed to erase the option bytes

//        FLASH->CR |= CR_OPTER_Set;

//        FLASH->CR |= CR_STRT_Set;

        flash_CR = readMem((uint32_t)&(FLASH->CR));

        flash_CR |= CR_OPTER_Set;

        writeMem((uint32_t)&(FLASH->CR), flash_CR);

        flash_CR |= CR_STRT_Set;

        writeMem((uint32_t)&(FLASH->CR), flash_CR);

        status = flashWaitForLastOperation(EraseTimeout);

        // Disable the OPTER Bit

//        FLASH->CR &= CR_OPTER_Reset;

        flash_CR = readMem((uint32_t)&(FLASH->CR));

        flash_CR &= CR_OPTER_Reset;

        writeMem((uint32_t)&(FLASH->CR), flash_CR);

        // Enable the Option Bytes Programming operation

//        FLASH->CR |= CR_OPTPG_Set;

        flash_CR = readMem((uint32_t)&(FLASH->CR));

        flash_CR |= CR_OPTPG_Set;

        writeMem((uint32_t)&(FLASH->CR), flash_CR);

        // Disable Read Protection

//        OB->RDP = 0x00;

        writeAP(AP_CSW, AP_CSW_DEFAULT_16);    // as STM32F1's FPEC works in 16-bit mode, switch to AHB-AP size to 16-bit

//        writeMem((uint32_t)&(OB->RDP), RDP_Key);

        writeMem(0x1FFFF800, 0x00A5);

        writeAP(AP_CSW, AP_CSW_DEFAULT);    // switch to AHB-AP size back to 32-bit

        status = flashWaitForLastOperation(EraseTimeout);

        flash_CR = readMem((uint32_t)&(FLASH->CR));

        flash_CR &= CR_OPTPG_Reset;

        writeMem((uint32_t)&(FLASH->CR), flash_CR);

    }

    return status;

}

Just in case, I also tried writing RDP_key = 0x5AA5, without success.

Will try to remove RDP on an STM32L1 in meanwhile...

Thanks for your time!

Posted on February 24, 2015 at 13:03

You miss Step#1

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gmravil
Associate II
Posted on February 24, 2015 at 13:09

Sorry again for posting too fast without checking manuals. 🙂

All I had to do was to unlock the FPEC itself before starting to work with the Option Byte Register.

static void flashUnlock(void)

{

    writeMem((uint32_t)&(FLASH->KEYR), FLASH_KEY1);

    writeMem((uint32_t)&(FLASH->KEYR), FLASH_KEY2);

}

Thanks again for your support!
peng jun
Associate II
Posted on July 15, 2018 at 04:59

Hi。From the  <PM0075  Programming manual>  , P15,Mass Erase  as below code is successful 。Now,I  want to Main Flash memory programming  ,  but  I don't  how to do it  .  Help  me.....

Thanks!

FLASH_Status flashEraseAllOptionBytes_STM32(void)

{

   FLASH_Status status = FLASH_COMPLETE;

   uint32_t flash_CR,flash_SR;

  flash_CR = readMem((uint32_t)&(FLASH->CR));

  flash_CR |= CR_MER_Set;

  writeMem((uint32_t)&(FLASH->CR), flash_CR);

  flash_CR |= CR_STRT_Set;

  writeMem((uint32_t)&(FLASH->CR), flash_CR);

  status = FLASH_WaitForLastOperation(((uint32_t)0x000B0000));

return 0x09;

}