Can't remove write protection from FLASH pages 0 and 1 on STM32F103!
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 STM32F 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).
// Reset - The Option Bytes are copied for the processor's use // In Bootloader
// Write protect bootloader in first four pages
FLASH_Unlock();
if (FLASH_GetWriteProtectionOptionByte() == 0xffffffff) {
FLASH_EnableWriteProtection(FLASH_WRProt_Pages0to1 | FLASH_WRProt_Pages2to3);
}
FLASH_Lock();
// Point 1 - At this point, the WP bits in the Option Bytes are set, // but what the processor uses may vary; bootloader relocates vector table here and jumps to the app // In App, check for WP activeFLASH_Unlock();
FLASH_ClearFlag( . . . );
WRPR_Value = FLASH_GetWriteProtectionOptionByte();
ProtectedPages = ~(WRPR_Value | BL_FLASH_PAGES); // BL_FLASH_PAGES = 3, meaning pages 0 - 3
protected = ((WRPR_Value | (~BL_FLASH_PAGES)) != 0xFFFFFFFF );
// If WP active, unprotect and reboot to cause the OB loader to runif (protected) {
FLASH_EraseOptionBytes();
NVIC_SystemReset(); // Reset to load new option bytes
// Point 2. Reset occurs
}
// Point 3. After reset and the bootloader writing to the OB, we get here, because the
// protected variable is now false this time.
// Erase the four pages
int i;
uint32_t page = 0x08000000;
for (i = 0; i < 4; ++4) {
FLASH_ClearFlag( . . . );
printStatus(FLASH_ErasePage(page); // Point 4 - page 0 and 1 fail with WPERR, page 2 and 3 succeed!
page += 0x800;
}
// Copy the data
uint16_t* src = start of image;
uint32_t dest;
for (dest = 0x08000000; dest < 0x08002000; dest += 2) {
printStatus(FLASH_ProgramHalfWord(dest, src++); // Point 5 - of course, this fails for pages 0 and 1
}
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!