AnsweredAssumed Answered

Can't remove write protection from FLASH pages 0 and 1 on STM32F103!

Question asked by grimes.robert on Dec 10, 2015
Latest reply on Dec 15, 2015 by Clive One
Okay, we have a bootloader that we want to replace programmatically, as it is not practical to get access to the debug ports.  I've done this successfully with a STM32F071, but have not been able to get it working on a STM32F103.  So the concept is to use the bootloader to load an app that "simply" copies a block of data over the bootloader - hence, the bootloader is replaced.   Here is an outline of the approach (the printStatus function reports the FLASH_x result to a terminal for viewing).

01.// Reset - The Option Bytes are copied for the processor's use
02. 
03.// In Bootloader
04.  // Write protect bootloader in first four pages
05.  FLASH_Unlock();
06.  if (FLASH_GetWriteProtectionOptionByte() == 0xffffffff) {
07.    FLASH_EnableWriteProtection(FLASH_WRProt_Pages0to1 | FLASH_WRProt_Pages2to3);
08.  }
09.  FLASH_Lock();
10. 
11.// Point 1 - At this point, the WP bits in the Option Bytes are set,
12.//           but what the processor uses may vary; bootloader relocates vector table here and jumps to the app
13. 
14.// In App, check for WP active
15.  FLASH_Unlock();
16.  FLASH_ClearFlag( . . . );
17. 
18.  WRPR_Value = FLASH_GetWriteProtectionOptionByte();
19.  ProtectedPages = ~(WRPR_Value | BL_FLASH_PAGES);     // BL_FLASH_PAGES = 3, meaning pages 0 - 3
20.  protected = ((WRPR_Value | (~BL_FLASH_PAGES)) != 0xFFFFFFFF );
21. 
22.// If WP active, unprotect and reboot to cause the OB loader to run
23.  if (protected) {
24.    FLASH_EraseOptionBytes();
25.    NVIC_SystemReset();  // Reset to load new option bytes
26. 
27.    // Point 2. Reset occurs
28.  }
29. 
30.  // Point 3. After reset and the bootloader writing to the OB, we get here, because the
31.  //          protected variable is now false this time.
32. 
33.  // Erase the four pages
34.  int i;
35.  uint32_t page = 0x08000000;
36.  for (i = 0; i < 4; ++4) {
37.    FLASH_ClearFlag( . . . );
38.    printStatus(FLASH_ErasePage(page);  // Point 4 - page 0 and 1 fail with WPERR, page 2 and 3 succeed!
39.    page += 0x800;
40.  }
41. 
42.  // Copy the data
43.  uint16_t* src = start of image;
44.  uint32_t dest;
45.  for (dest = 0x08000000; dest < 0x08002000; dest += 2) {
46.    printStatus(FLASH_ProgramHalfWord(dest, src++);  // Point 5 - of course, this fails for pages 0 and 1
47.  }

So the odd thing is that, while the bootloader turns on WP for pages 0 - 3, and the app turns it off for 0 - 3, after the reset, 0 and 1 remain protected, and 2 and 3 are not!

I know the bootloader indeed turns on WP for pages 0 - 3, as I can verify that with ST-LINK.  I know the app turns off WP for pages 2 and 3, as they are erased.  I know that if the OB are erased, then all WP should be off!  Finally, if I use a version of the bootloader that doesn't turn on WP, then the page erasing and programming work correctly!

So the crux of the problem seems to be that pages 0 and 1 are handled specially, somehow?  But I cannot find any references to such unusual behavior.

Help, please!

Outcomes