3
\$\begingroup\$

Is there a way to find the last address or last page of the program which is stored in an STM32(F1) using a HAL (or LL?) function?

Background: I'm using EEPROM emulation in Flash and this works great. I changed the library from a hardcoded page to be used for EEPROM emulation to a variable one, to be able to implement wear leveling.

However, to know which pages can be used, I need to know where the program 'stops', i.e. the last address or page used by the program being executed, not to overwrite the program itself.

Also I'm a bit confused about the pages used and the size of each page. I'm using this library:

https://github.com/nimaltd/EEPROM/blob/master/eeprom.c (credits to Nima Askari).

Which defines for STM32F103C8T6 (low density F1) 1 KB page sizes and a max page of 31. Why 31? I would expect 63 as it has 64 KB. Although I noticed when using page 15, it overwrote my program which is around 30 KB in size. (this part is solved, see my answer below).

Of course I can use the size of the program (see below), but this varies while I program, and besides it's too tedious to change/calculate the page number every time, I might forget it too.

arm-none-eabi-size   FuzzTester3.elf 
   text    data     bss     dec     hex filename
  26632     236    3104   29972    7514 FuzzTester3.elf
\$\endgroup\$
9
  • 1
    \$\begingroup\$ Your compiler might define a name for the last address used by code and/or const data sections. I know in the one I use, it has definitions for the end of code, something like __text_end__ and const data __rodata_end__. I can extern these in my C code - something like extern uint32_t *__rodata_end__; and then use these 'variables' in my code. Once the compiler & linker finish doing their jobs, these values are then automatically substituted into my code where needed. \$\endgroup\$
    – brhans
    Commented May 9, 2020 at 0:20
  • \$\begingroup\$ @brhans that sounds useful, however I cannot find them (I'm using STM32CubeIDE \$\endgroup\$ Commented May 9, 2020 at 1:11
  • 1
    \$\begingroup\$ I've tried out a simple project in STM32CubeIDE, and with all the default settings it looks like it provides a symbol called __fini_array_end at the last used location in Flash. So you'd probably declare it as extern uint32_t __fini_array_end; in your code and then use &__fini_array_end to work out the start of the next page to use as simulated EEPROM \$\endgroup\$
    – brhans
    Commented May 9, 2020 at 3:04
  • 1
    \$\begingroup\$ It would depend on how your sections are arranged in flash. The default project which STM32CubeIDE created for me put that at the end. So you'll have to look at your map file to see what symbol is at the end for your project and use that instead. Somewhere down near the end of your .map file you'll see the addresses of the symbols change from the 0x0800xxxx range (Flash) to 0x2000xxxx (RAM). You might find some others like __init_array_end, __preinit_array_end, etc. \$\endgroup\$
    – brhans
    Commented May 9, 2020 at 14:37
  • 1
    \$\begingroup\$ .data, .bss, etc should be in RAM in the 0x2000xxx range. You're looking for the last symbol in Flash in the 0x0800xxxx range. \$\endgroup\$
    – brhans
    Commented May 9, 2020 at 14:50

2 Answers 2

4
\$\begingroup\$

Your compiler might define a name for the last address used by code and/or const data sections. I know in the one I use, it has definitions for the end of code, something like __text_end__ and const data __rodata_end__. I can extern these in my C code - something like extern uint32_t __rodata_end__; and then use these 'variables' in my code. Once the compiler & linker finish doing their jobs, these values are then automatically substituted into my code where needed.

I've tried out a simple project in STM32CubeIDE, and with all the default settings it looks like it provides a symbol called __fini_array_end at the last used location in Flash. So you'd probably declare it as extern uint32_t __fini_array_end; in your code and then use &__fini_array_end to work out the start of the next page to use as simulated EEPROM.

Depending on how your project's linker is configures, you might find a different arrangement of sections in flash. The default project which STM32CubeIDE created for me put __fini_array_end at the end. So you'll have to look at your map file to see what symbol is at the end for your project and use that instead. Somewhere down near the end of your .map file you'll see the addresses of the symbols change from the 0x080xxxxx range (Flash) to 0x2000xxxx (RAM). You might find some others like __init_array_end, __preinit_array_end, etc.

If you're looking through the .map file and see the .data, .bss and other sections in the 0x2000xxxx range then you've gone too far and need to scroll back up a little to get back to the end of the 0x080xxxxx range.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks and guiding me through the steps ... __rodata_end__ is undefined, however, I need __fini_array_end__ which works. \$\endgroup\$ Commented May 9, 2020 at 15:24
2
\$\begingroup\$

Note this only answers the max page 31 issue. My main issue (finding the last address or last page is not solved.

By coincidence searching in hal_stm32f1xx_hal_flash_ex.h, I found the following code (removed irrelevant parts):

/* Low Density */
#if (defined(STM32F101x6) || defined(STM32F102x6) || defined(STM32F103x6))
...

/* Medium Density */
#if (defined(STM32F100xB) || defined(STM32F101xB) || defined(STM32F102xB) || defined(STM32F103xB))
...

/* High Density */
#if (defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F103xE))
...

/* XL Density */
#if defined(FLASH_BANK2_END)

/* Connectivity Line */
#if (defined(STM32F105xC) || defined(STM32F107xC))
...

The model I use (STM32F103C8T6) is NOT within this list, and when I search in the preprocessor definitions, I see STM32F10CxB is defined. Which is strange because this model has 128 KB and mine has 64 KB. I selected mine as Low Density which seems not to be the case, and this was defined as 31 pages (i.e. 32 KB).

So except for the slightly misleading HAL generation, I can use 64 KB (I verified this).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.