2015-12-10 01:29 PM
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!2015-12-15 05:44 AM
Nobody has any ideas on this? It's got us rather stuck right now...
2015-12-15 09:10 AM
Nobody has any ideas on this? It's got us rather stuck right now...
Forums are an echo chamber for lost souls... I've got some thoughts on this, but it's been several years since I've mined into the F1 parts at this depth. Protection schemes and methods tend to fall into the area of vague documentation, examples and functionality, often purposefully so. You have to get in the trenches and fight with the issues/behaviour there. The logic here seems broken, and the immediate reset might perhaps be an issue
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 run
if (protected) {
FLASH_EraseOptionBytes();
NVIC_SystemReset(); // Reset to load new option bytes
// Point 2. Reset occurs
}
Instrument and confirm it's doing the option erase, and returns success. Perhaps dwell there, or power cycle.