cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F765 / OTA / Flash Banks start address wrong (?) / linker script + multiple builds

Christophe Beugnet
Associate II

Hi,

[NOTE : this message has several parts, because it took me time to write, time to check what I wrote, time to check again "The Internet", just in case. And guess what : I found some solutions to some of the problems. But I prefer to share my whole pain, I want others to suffer too, so I'm not altering/correcting what I wrote yesterday ... After that, I'll gladly appear dumb with answers than the other way around]

==================================================================

[DAY 1 : after several weeks of ... You'll see]

Could you explain why I’m struggling that much implementing OTA ?
I’ll admit easily that I’m not the top of the top embedded devs. But my stupidity has limits, I hope.
And after the few weeks I spent reading documentations, examples, and testing, I expected to be coding the download and writing in flash of a new FW version already.
Far from that. So please accept my apologies in advance if the following reflect how pissed I am to waste so much time on something that should be straightforward.

Context : I’m using an STM32F769I-DISCO on one side, and a custom board based on a STM32F765VGT6 (dev ID 0x451 ; rev ID : Rev Z). I used the discovery to get familiar with the concepts, but now, I’m using only the custom board.
In the following explanations, BHuCP means “BY HAND, using STM32CubeProgrammer” (CubeProg in short).

So far, the best result I got is :

  •  build 2 FWs that I can easily distinguish by their own serial (UART7) traces
  • I modified the Option Bytes : nDBANK is unchecked (→ dual bank) and nDBOOT is checked (→ dual boot disabled)
  • I can flash each FW BHuCP, at their respective addresses / Flash Bank (with problems, more often than not; there's a specific description below)
  • I can select either bank by modifying BHuCP, the Option Bytes BOOT_ADD0, pointing the first or second FW, which boots properly, and display its distinctive messages to confirm which one is running

Before continuing, please confirm : I must set a proper line

FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K


in the linker script ? This one is the default.

I need to set the length at 512K (half the 1 MB of the F765). And I would need one line/one setting/one linker script for boot address (ORIGIN) of bank 1, and another for boot address (ORIGIN) of bank 2, correct ? Or can a FW build with ORIGIN = 0x8000000 boot from the bank 2 ?

Now, why am I complaining ?

Because of the following :

  • I don’t remember in which document, neither if it applies to the F769 or F765 (or both?), I read something about BOOT0. Do we agree that the HW bank selection is ignored (BOOT0 pin) and nDBOOT is useless ? This question is not really important, I have no use for an HW FW selection, OTA requires SW selection of the boot bank
  • if I found and read the proper documents, an F765 as 1 MB of flash. It is confirmed by CubeProg when connected. According to AN4826, bank 1 starts at 0x08000000 and bank 2 at 0x08080000. This seems wrong, because I can’t flash at 0x08080000. Instead, my 2nd FW can be flashed, and runs (sometimes), at 0x08100000 (512 kB further). But this address should be correct only for the F769 and its 2 MB flash, not the F765 and its 1 MB flash. What’s going on ?
  • by the way, when flashing bank 2 with CubeProg, sometimes, I get a verify error. I could not understand why, nor be sure how to successfully, or fail to, flash bank 2 again (disconnect/reconnect ? Reset ? Power cycle ?)
  • as far as I understand OTA, the running FW should be aware of the bank it's running from, shall download the new one, and flash it in the “other bank”, and, after some checks (CRC, signature perhaps, etc. I know, probably small chunk by small chunk), configure the MCU boot address (Option Bytes) to point the “other bank”, and eventually, restart. How do I do that [EDIT: partially answered below, in DAY 2] ? Then again, I read documents, and I guessed, more than understood, that there may be two solutions :
    • calls to HAL_EnableMemorySwappingBank() and HAL_DisableMemorySwappingBank(). Not working so far, the MCU freezes. I read that the switch may be immediately effective, meaning that the MCU retrieves instruction from the new bank at once (which can lead to disaster, obviously). Also, using the instruction cache may be mandatory to counter this problem. But I still can't get it working this way
    • through the Option Bytes : calls to HAL_FLASHEx_OBGetConfig(…) and HAL_FLASHEx_OBProgram(…). I can read the config, BootAddr0 and BootAddr1 are as I configured them BHuCP. I tried to swap them, to set OptionType to OPTIONBYTE_BOOTADDR_0 | OPTIONBYTE_BOOTADDR_1, and then call HAL_FLASHEx_OBProgram(…) to apply the change. But when I read the config again, just after applying the changes: nothing, the swap if completely ignored, and the MCU boots from the same bank.

So, what am I missing ? Obviously, an OTA cannot require the client to install STM32CubeProgrammer to alter Option Bytes or flash the new FW. How do I alter the boot address of the MCU ?

If you allow me one more question …

STM bought Atollic TrueSTUDIO in 2017, right ? Which has been made free for STM products (thanks STM for that), and now combines the IDE and CubeMX.

And this is the IDE of choice from STM for STM products, right ?

So, how do you explain that the examples I find from your own website are made for (from the top of my head) Keil, IAR and OpenSTM32 ?

I know I can import projects in CubeIDE, but that does not end well every time, especially for the two example projects for the F769I-DISCO with LED1 blinky from bank 1 / LED2 blinky from bank 2. Why can’t we have examples with CubeIDE projects that integrate immediately, without struggles, in your own IDE ?

I would be ashamed and relieved at the same time if you point me to a document that explain how to properly do an OTA. But I'm afraid that may not be as simple as that.

==================================================================

[DAY 2 : after a lucky search. Yes, after decades of internet searches, I still think I'll only find pertinent results with luck]

I just discovered the existence of the HAL functions HAL_FLASH_OB_Unlock(), HAL_FLASH_OB_Lock() and HAL_FLASH_OB_Launch().
I determined that this should be the proper order of the call sequence :

res = HAL_FLASH_OB_Unlock();
displayHALStatus(res, "HAL_FLASH_OB_Unlock()");
if( res == HAL_OK )
{
    MSG_INFO("Writing swapped Boot bytes\n");
    MSG_INFO(" BootAddr0: 0x"); MSG_INFO_uint32_hex(optionBytes.BootAddr0, 4); MSG_INFO(" => "); MSG_INFO(obBootAddrToStr(optionBytes.BootAddr0)); MSG_INFO("\n");
    MSG_INFO(" BootAddr1: 0x"); MSG_INFO_uint32_hex(optionBytes.BootAddr1, 4); MSG_INFO(" => "); MSG_INFO(obBootAddrToStr(optionBytes.BootAddr1)); MSG_INFO("\n");
    HAL_FLASHEx_OBProgram(& optionBytes);

    res = HAL_FLASH_OB_Launch();
    displayHALStatus(res, "HAL_FLASH_OB_Launch()");

    res = HAL_FLASH_OB_Lock();
    displayHALStatus(res, "HAL_FLASH_OB_Lock()");
}​

 

In short : unlock, program, launch, lock. Correct ?

After struggling again with CubeProg to flash the bank 2 FW, I'm able to :

  • run a FW from bank 1
  • swap BootAddr0 / BootAddr1 and reset
  • which runs the FW from bank 2
  • swap again to run again from bank 1

At last, some progress.

I'll make some more tests, and a pause, to wait for your answers, before coding the download of a new FW into the inactive flash bank.

==================================================================

[DAY 2 - 1/2 : the struggles with CubeProg]

Apart from the confirmation/invalidation of the bank 2 start address I'm using, here is today's first flash session :

Bad.good.lucky.flash-with.comments.png

 

==================================================================

[DAY 2 - 3/4 : additional question]

If the answer to the question "does ORIGIN need to be set to the actual bank start address ?" is "yes", this means that there must be a linker script for bank 1, and another for bank 2, right ?

  • this would mean that an OTA means two FWs, one for bank 1 and one for bank 2. As far as my tests go, I'd say yes, one build with "ORIGIN = 0x8000000" and another with "ORIGIN = 0x8100000"
  • is there a way to automate the builds, to produce the two FWs at the end of the same build ? Either from CubeIDE or command line, or both
  • what would be the best/correct way for a FW to check from which bank it is running, in order to flash any new FW in the "other bank" ?
  • in which document can I find the complete explanations of the following BOOT_ADD0/1 values :

 

/** @defgroup FLASHEx_Boot_Address FLASH Boot Address
  * @{
  */
#define OB_BOOTADDR_ITCM_RAM         ((uint32_t)0x0000U)  /*!< Boot from ITCM RAM (0x00000000)                 */
#define OB_BOOTADDR_SYSTEM           ((uint32_t)0x0040U)  /*!< Boot from System memory bootloader (0x00100000) */
#define OB_BOOTADDR_ITCM_FLASH       ((uint32_t)0x0080U)  /*!< Boot from Flash on ITCM interface (0x00200000)  */
#define OB_BOOTADDR_AXIM_FLASH       ((uint32_t)0x2000U)  /*!< Boot from Flash on AXIM interface (0x08000000)  */
#define OB_BOOTADDR_DTCM_RAM         ((uint32_t)0x8000U)  /*!< Boot from DTCM RAM (0x20000000)                 */
#define OB_BOOTADDR_SRAM1            ((uint32_t)0x8004U)  /*!< Boot from SRAM1 (0x20010000)                    */
#if (SRAM2_BASE == 0x2003C000U)
#define OB_BOOTADDR_SRAM2            ((uint32_t)0x800FU)  /*!< Boot from SRAM2 (0x2003C000)                    */
#else
#define OB_BOOTADDR_SRAM2            ((uint32_t)0x8013U)  /*!< Boot from SRAM2 (0x2004C000)                    */
#endif /* SRAM2_BASE == 0x2003C000U */
/**
  * @}
  */
​

Especially why 0x2040 means 0x08100000, 0x2020 means 0x08080000 and 0x2000 means 0x08000000 ?

And is there a problem using 0x80 to boot from 0x08000000

==================================================================

[DAY 2 - conclusion]

I know I can be far from diplomatic or correct when reporting such problems when I'm still pissed ... Again, sorry for the form.
If you could get past that, thank you for any help, corrections of my mistakes, indications of better documents, anything

Regards

0 REPLIES 0