Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Program option bytes on STM32G4xx
#1
I've previously been working with STM32F411 but recently switched to STM32G473, so I need to learn new things.
STM32G473 have dual-bank FLASH, configurable via the option bytes as single- or dual-bank. Factory default is dual-bank.
I will use singe-bank mode and therefore need to somehow program the option bytes.

My first attempt was to embed the option bytes via the source code into the .hex file, to be flashed when writing/updating the firmware on the CPU. I was able to do this with the help of the linker script. STM32CubeProgrammer will take the generated .hex file and write the option bytes along with the rest of the firmware. This works. I copy/paste the code here in case someone else have use for it:

In the source code:
Code:
#include <stdint.h>
#include "stm32g4xx_hal.h"

/// User and read protection option bytes
#define OPTR_CONTENT \
  (1 << 31) |
  OB_IRH_ENABLE |
  OB_NRST_MODE_INPUT_ONLY |

...

/// Option byte array (single-bank or bank 1) located at the correct address in memory based on the section definition in the linker script
uint32_t application_option_bytes_singlebank_or_bank1[6 * 2] __attribute__((section(".option_bytes_bank1_section"))) =
{
  (uint32_t)(OPTR_CONTENT),          ~(uint32_t)(OPTR_CONTENT),
  (uint32_t)(PCROP1_START_CONTENT),  ~(uint32_t)(PCROP1_START_CONTENT),
  (uint32_t)(PCROP1_END_CONTENT),    ~(uint32_t)(PCROP1_END_CONTENT),
  (uint32_t)(WRP1A_CONTENT),         ~(uint32_t)(WRP1A_CONTENT),
  (uint32_t)(WRP2A_CONTENT),         ~(uint32_t)(WRP2A_CONTENT),
  (uint32_t)(SEC1_CONTENT),          ~(uint32_t)(SEC1_CONTENT),
};

/// Option byte array (bank 2) located at the correct address in memory based on the section definition in the linker script
uint32_t application_option_bytes_bank2[5 * 2] __attribute__((section(".option_bytes_bank2_section"))) =
{
  (uint32_t)(PCROP2_START_CONTENT),  ~(uint32_t)(PCROP2_START_CONTENT),
  (uint32_t)(PCROP2_END_CONTENT),    ~(uint32_t)(PCROP2_END_CONTENT),
  (uint32_t)(WRP1B_CONTENT),         ~(uint32_t)(WRP1B_CONTENT),
  (uint32_t)(WRP2B_CONTENT),         ~(uint32_t)(WRP2B_CONTENT),
  (uint32_t)(SEC2_CONTENT),          ~(uint32_t)(SEC2_CONTENT),
};


In the linker script:

Code:
MEMORY
{
...
  OPT_B1 (rw) : ORIGIN = 0x1FFF7800, LENGTH = 48              /* Options bytes single-bank or bank 1 */
  OPT_B2 (rw) : ORIGIN = 0x1FFFF808, LENGTH = 40              /* Options bytes bank 2 */
...
}

SECTIONS
{
...
  /* Options bytes single-bank or bank 1 */
  .option_bytes_bank1_section :
  {
      KEEP(*(.option_bytes_bank1_section*))
  } > OPT_B1

  /* Options bytes bank 2 */
  .option_bytes_bank2_section :
  {
      KEEP(*(.option_bytes_bank2_section*))
  } > OPT_B2

...
}

BUT, unfortunately this does not work with EBlink 4.7 in EmBitz 2.50:

Quote:EBlink version 4.7-[13] by Gerard Zagema

Interface USB# : 54FF6A066684565547522187
Interface type : STlink/V2
STlink connect : Under reset
Target voltage : 3.25V
Interface speed: 4000KHz
Target detected: Cortex-M4 (r0p1) with FPv4_SP
HW breakpoints : 6
HW watchpoints : 4
Fault unwind  : Active break (level 2)
STmicro family : STM32G47/48xx
Detected FLASH : 0x80000
Configured RAM : 0x20000
Reset: system
Try to flash a non-flash region! Address 0x1FFF7800
Try to flash a non-flash region! Address 0x1FFFF808
Checking current flash content
Flash programming done
Flash verify done
Flasher starts target
Reset: system


And I guess the reason is in EBlink/scripts/stmicro/stm32gx.script
Quote://///////////////////////////////////////////////////
//
//                  STM32Gx
//
// ToDo: - option programming
//

I've looked briefly at the script code and I would not know where to start, if I try to implement this myself.
Are there any plans of implementing this anytime soon?

What are my alternatives? Suggestions are appreciated as this is a new CPU for me and I'm learning.
At the moment I'm in development, and can set the options with STM32CubeProgrammer, but eventually I will be getting factory empty CPU's and by then I need to get them flashed as conveniently as possible, that was why I initially tried to embed the option bytes directly in the .hex file.
Reply
#2
What you have to do:

- Add at the end of the EBlink XML memory map the sector with the option base address and right length
- Give that sector a fake number e.g. 999 (something which is out of range of normal flash) 
- Give that sector a virtual attribute to exclude it from the EBlink caching algorithm (property sectype = virtual)
- In the EBlink erase function filter on sector number 999 to skip normal flash erase function
- In the EBlink flash write function filter on sector number 999 and jump to a new to create function e.g. "option_write"
- Create new "option_write" function with the right algorithm to program option bytes

Check the script code for the stm32h7 which supports option programming. e.g. Memory map H7:
Code:
const mem_template_H7 = @@"
<?xml version=\"1.0\"?> <memory-map>

    <snip...>
 
    <!-- option byte area (virtual sector) -->
    <memory type=\"flash\" start=\"0x1ff20000\" length=\"32\">
        <property name=\"blocksize\">32</property>
        <property name=\"secstart\">999</property>
        <property name=\"sectype\">virtual</property>
    </memory>
</memory-map>"

H7 erase function:
Code:
function flash_erase(sector, address)
{
    local regbase = FLASH_REG_BASE_B0 // first flash bank

    // Skip the virtual option sector
    if(sector == 999)
      return ERROR_OK
   
     <snip...>
}


H7 write function:
Code:
function flash_write(sector, address, buffer)
{
    local regbase = FLASH_REG_BASE_B0 // first flash bank

    // If this is the virtual option sector, go to options write function
    if(sector == 999)
      return option_write(buffer)

    <snip...>
}

H7 option_write:
Code:
function option_write(buffer)
{
   <snip...>
}


Last but not least, if everything works: share it.

P.s. It's not much work but currently I'm a bit busy.


Attached Files
.zip   stm32h7_options.zip (Size: 3.73 KB / Downloads: 70)
Reply
#3
Thank you very much! I will have a go at this.
Reply
#4
Remember:
The algorithm to program option bytes is for STmicro totally different than programming code flash.
Other keys to use etc etc Check MCU reference manual for the right Algorithm.

Tip:
To test your scripts you can just use printf statements to give debug feedback.
Reply
#5
I think I'm pretty close, I'm at the final step and need help with reconnecting to the target.
From the reference manual:
Quote:Option byte loading
After the BSY bit is cleared, all new options are updated into the Flash but they are not
applied to the system. They have effect on the system when they are loaded. Option bytes
loading (OBL) is performed in two cases:
– when OBL_LAUNCH bit is set in the Flash control register (FLASH_CR).
– after a power reset (BOR reset or exit from Standby/Shutdown modes).
Option byte loader performs a read of the options block and stores the data into internal
option registers. These internal registers configure the system and cannot be read with by
software. Setting OBL_LAUNCH generates a reset so the option byte loading is performed
under system reset.

So the CPU does a reset to take the new options into use when setting OBL_LAUNCH bit. 
I can see this as EBlink seems to loose connection with the target.
How do I tell EBlink to reconnect so the script can continue?
Attached is what I have so far.


Attached Files
.zip   stm32g4_options_scripts_v0.0.zip (Size: 5.63 KB / Downloads: 55)
Reply
#6
Great!

I will see if I can find a disco board to test it.
What do you mean with "EB is losing connection "?
Are you using EB as file flash tool or as GDB server?
Reply
#7
(I seem to have a different account at home)

"What do you mean with "EB is losing connection "?"
After setting the OBL_LAUNCH bit, I was relocking the option bytes, but EBlink then gave an error message and my guess was the relocking read-and-write failed because the CPU was reset. There is a comment in the code about this.

"Are you using EB as file flash tool or as GDB server?"
I'm so far using Flash menu to write the compiled .hex file to the traget.

BTW, as soon as I added those virtual sectors to the memory map, Flash verification started complaining about verification failing. Is there some script code needed to properly support verification?
Reply
#8
That's, most likely, because we can't just easily read options back.
I can solve this by introducing special read callbacks for virtual sectors. I will put it on my list for next EBlink version.

Thanks.
Reply
#9
Perhaps it is easier to introduce two additional optional properties for xml sectors. One for defining sector script write function and one for sector script read function.
All that filtering of fake sector numbers is not needed anymore when using function assignments to virtual scripts.
Reply
#10
That sounds like a good design!
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)