I'm trying to add a serial number to the bootloader's flash area of Adafruit Feather m0 board. Seems like feather m0 0-0x2000 area on the flash is non writable by the arduino sketch. i wanted to add a serial number to address 0x2000 - 8 on the flash. The idea is for the data to be included in the bootloader elf\bin so i can easily flash it on devices and later on access it using flash address (0x2000 - 8) with NVMCTRL.

I've started out with this solution:

downloaded the code from samd21 arduino bootloader github directory and in ./bootloaders/zero edited the boololoader ld script, first the "Memory" section

FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x2000 /* First 8KB used by bootloader */
FLASHID (rx) : ORIGIN = 0x00002000 - 0x0008, LENGTH = 8

Then the 'sections' section:

.id_sec :

This should have saved some room in the end of the flash for the id. now in the main.c file:

__attribute__ ((section(".myid"))) const unsigned long ID = 0xdead1234;

Which should have saved the 0xdead1234 hex value in the (0x2000-8) address.

The issue is this: I compiled this code and linked it just fine, got .hex,.bin,.elf files. If i'm correct (unless they are somehow compressed) i should be able to see the code 0xdead in the binary. BUT i don't. After objdump on the binary(any of them) i can't find the 0xde 0xad in any order anywhere. The arm-none-eabi-size" --format=sysv -t -x build/.elf does not show the new section i added no where. Also i do wonder, as i said the 0x2000 address on the flash is non writable once i flashed with atmel-ice \j-link even the bootloader code cannot write to it, i did define in the ld script that i want that memory region part of the flash so i do expect that the compiler + linker + jlink flasher will know to write that data to the right place but not sure.

Anyone got some experience with it ? did it before ?

  • instead of 0xde 0xad, look for 0xed 0xda ... maybe it is stored in little endian
    – jsotola
    Commented May 2, 2018 at 5:58
  • Your question is amazingly hard to read. See How to ask a good question. Take a bit of time to make some paragraphs, spell "I" with a capital "I", and generally explain what you are trying to do.
    – Nick Gammon
    Commented May 2, 2018 at 6:14
  • @jsotola i did try that, well aware of the endianess. i basically tried just to use objdump and xxd and then grep it twice once for 'ed' and once for 'da' which should capture all possibilities. Commented May 2, 2018 at 6:17
  • 1
    Cross-posted here. The question looks better, however see See Is cross-posting a question on multiple Stack Exchange sites permitted if the question is on-topic for each site? - you have to decide which site you want to ask on. Stack Exchange does not want you to ask your question over multiple of its sites.
    – Nick Gammon
    Commented May 2, 2018 at 7:19
  • 1
    You know the samd21 already has a unique serial number that you can access.
    – Gerben
    Commented May 2, 2018 at 12:59

1 Answer 1


This is quite an easy fix, actually.

The problem here is the compiler doesn't think the const is used for anything - so it (quite rightly) throws it away.

All you need to do is tell the compiler that it's used and all should be good:

__attribute__((section(".myid"),used)) const unsigned long ID = 0xdead1234;

And when you compile:

build/.elf  :
section             size         addr
.vectors            0x40          0x0
.text             0x18d4         0x40
.data               0x5c   0x20000000
.bss               0x34c   0x2000005c
.id_sec              0x4       0x1ff8
.ARM.attributes     0x28          0x0
.comment            0x80          0x0
.debug_frame        0x68          0x0
Total             0x1dd0

Properly, though, you should make some more changes to the linker script to properly isolate those 8 bytes of flash (though you don't have to).

  1. You should reduce FLASH by 8 bytes.
  2. You should include the FLASHID length in the __sketch_vectors_ptr calculation.


  FLASH   (rx) : ORIGIN = 0x00000000, LENGTH = 0x1FF8 /* First 8KB used by bootloader */
  FLASHID (rx) : ORIGIN = 0x00001FF8, LENGTH = 8
  RAM    (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */



That way the compiled bootloader code can never be placed in the FLASHID area (not that it would at the moment, but if a new version of the bootloader were released that used 100% of the lower block of flash it would conflict).

Of course, if all you need is something unique to identify the board with, all AVR and SAMD devices that have built-in USB support have a unique ID number. This is intended to be used as the Serial Number for the USB, but could also be used for a MAC address for Ethernet (or for portions of it anyway) or other unique "node" addresses.

  • thanks! checking myself, if indeed i can see it i'll mark as the solution Commented May 2, 2018 at 10:44
  • @codeScriber note first the comment that the chip already has a unique ID. Next, if you want to serialize like this, after setting a default from the compiler, in practice you'd probably want to directly overwrite the values in the binary to be flashed (dd or many other tools can write at an offset) rather than recompile for each unit. Commented May 2, 2018 at 13:43
  • I do something similar to set a unique USERID value on PIC32 chips when programming a bootloader from a HEX file. Allocate it from a database, then filter the HEX file changing the values that need changing and recalculating the checksums.
    – Majenko
    Commented May 2, 2018 at 13:45
  • @ChrisStratton thanks that's exactly what i planned to do though i planned to use python script to do that... but no, i didn't know it had a serial and i did look for it! are you sure it's unique ? i actually looked for arm m0 unique id and not samd21, probably my mistake was there... Commented May 2, 2018 at 17:06
  • 1
    From the datasheet: "Each device has a unique 128-bit serial number....The uniqueness of the serial number is guaranteed only when using all 128 bits."
    – Craig
    Commented May 2, 2018 at 21:57

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.