cancel
Showing results for 
Search instead for 
Did you mean: 

Recognizing a project by reading the flash

chriskuku
Senior III

 

It happens to from time to time that I have a flashed project in a hardware, e.g. a bluepill, but I forgot which source project was belonging to it in the STM32CubeIDE's project treeview.

Is there a way to write the name of the project by means of some C-macro in text form into the program as kind of a signature or even more safely, compute a checksum of the flash binary and write that checksum into the program (yes I know, this may become tricky since the checksum alters the checksum itself :)

Is there a common technique for this?

8 REPLIES 8
Andrew Neil
Super User

@chriskuku wrote:

Is there a way to write the name of the project by means of some C-macro in text form into the program as kind of a signature 


Sure there is - no need for macros; eg,

const char signature[] = "This is my Signature string";

The string will be readable in flash.

Better yet, have your code write it out to a UART on startup.

 

PS:

You could locate that string at a specific address, to make it easier to find; eg,

Locate Constant Data in Flash at Fixed Address

https://stackoverflow.com/a/54128613

Defining Variables at Absolute Addresses with gcc

GCC Documentation: Specifying Attributes of Variables

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

The least I'm demanding is an automatism that gets the project name as a string. (similar to __DATE__,__TIME__, __LINE__,__FILE__ macros in C). Or some Makefile construct, that does something like "echo "const char signature =\" `echo  $(PROJECT)` \";" >project.h". 


@Andrew Neil wrote:

@chriskuku wrote:

Is there a way to write the name of the project by means of some C-macro in text form into the program as kind of a signature 


Sure there is - no need for macros; eg,

const char signature[] = "This is my Signature string";

The string will be readable in flash.

 


No, it will not unless it is referenced in the program code. Normally all the non-referenced objects are removed during linking.

The solution is to use custom section name for the object and define this section in the link script with KEEP(). it may be put at the end of .isr_vector output section.

Code:

__attribute__((section(".my_sig")))const char sig[] = "My signature";

Link script modification to put the signature in a fixed location, right after exception vector table:

  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    KEEP(*(.my_sig))
    . = ALIGN(4);
  } >FLASH

 

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

@gbm wrote:


No, it will not unless it is referenced in the program code.


Right.

Normally, I do reference it - eg, as suggested, by outputting to a UART on startup.

Or there is some other comms/control interface where some sort if "identity" is returned.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
mfgkw
Senior II

I usually use something like the signature string as well.

But additionally I have my version control system update the content automatically. I use subversion usually, but other VCSs work similiar.

Probably all VCS are able to replace specific patterns in a file with some content, e.g. replace "$Rev: any text$" with "$Rev: 76 $" if the file is at revision 76 in the VCS.

In my C source it looks like this:

const char  *whoami __attribute__ ((section (".init")))  = "$HeadURL: svn+ssh://klaus@myserver.xxx/svn/stm32workspace/trunk/NUCLEO-F030R8_test_doubleprecision/Core/Src/main.c $  $Rev: 76 $ $Date: 2025-12-20 12:02:11 +0100 (Sa, 20. Dez 2025) $";

(no, my server is NOT myserver.xxx)

 

To make subversion do so it is necessary to set an attribute on the file like:

svn propset svn:keywords "Date Revision HeadURL Author Id" main.c

Other VCS require some similiar setting. Perforce requires in p4v to make a setting on the file properties in  "Change Filetype..."; check "+k" or "+ky" there. Git has no sequential rev numbers but arbitrary hashes instead, see https://stackoverflow.com/questions/1792838/how-do-i-enable-the-ident-string-for-a-git-repository (I try to avoid git...).

 

A note on the __attribute__ ((section (".init"))): It is a bit dirty admittedly. You can omit this if you really use the string somewhere in your program, e.g. write it to UART.

But if you do not use it gcc will drop the string. This can be avoided with __attribute((used)). Then the string goes into the object file, but will be dropped when flashing because it goes to a section like .rodata.whoami which has no KEEP in the linker config (*.ld). You could force the linker to keep it by fixing the ld file (see https://community.st.com/t5/stm32cubeide-mcus/used-attribute-appears-ineffective/td-p/692448 for a similiar problem with a BSS variable). But I am too lazy to adapt the ld file for this and want to have a simple setting in the C source only. This is why I abuse .init section for this with STM projects - this section will not be dropped by the linker.

Then the Id string will be found in the source, the object file, in the ELF and in the flash as well; see attached png.

The effort is really low: I copy the single code line from an existing project to main.c in a new project and set the file property with the VCS. That's all, the content of the Id string will be wrong until the VCS touches the file for the first time.

This workflow requires using a VCS. But if you do not use it up to now you should consider this anyway...

id.png

gbm
Principal

With the code as above, your string goes to .rodata section and a not-really-needed pointer object declared as a variable but really being a constant is placed in .init section. With some bad luck with a linker script it could even lead to some data corruption. ;)

I would definitely not recommend the technique presented above.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

You are right, the pointer wastes 4 Byte in .init section, and the string itself goes to .rodata resp. .rodata.whoami.

But why should there happen data corruption? With every entry the linker makes the section grow for the requested size.

You could place the string directly in the Flash with a simple change in the ld file to save the 4 byte pointer. But as I said I do not change the ld file on every simple program to do this. And I never failed because of 4 bytes in flash; if this happens I would shorten the string...

gbm
Principal

Right, no extra problems if .init input sections goes to .text output section like in ST linker scripts, just the extra pointer constant mimicking a variable. :)

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice