I'm working with an ATmega328P and I wanted to interface with the flash memory writing data to it with the macros provided by avr-libc. This is the memory map for my chip:

ATmega memory map
(source: avr-tutorials.com)

I don't understand where the program code is exactly located when compiled. What I mean is: How can I be sure the address I use in boot_page_fill and boot_page_write is not used for the program code? Do I need to use the "–section-start" linker option to move the program code to a specific location and be sure the flash page I'm going to use doesn't overwrite that code?

NOTE: The data to write in the flash is unknown at compile time.

  • \$\begingroup\$ nongnu.org/avr-libc/user-manual/FAQ.html#faq_reloc_code \$\endgroup\$ Oct 9, 2014 at 5:01
  • \$\begingroup\$ As I said, I already read that! but my question still unclear. What's the relation between the flash pages location I'm gonna write on and the program code location? \$\endgroup\$
    – Worakls
    Oct 9, 2014 at 5:13
  • \$\begingroup\$ Whatever you tell the linker. If you don't want them to collide then you need to make sure that they don't. \$\endgroup\$ Oct 9, 2014 at 5:16
  • \$\begingroup\$ boot_page_xxxx functions are called by bootloader running in boot flash section. I.e. normally you are uploading binary image into application flash section. You don't need care about sections etc. You just need pass binary to bootloader, typically via serial/USB or read it from external flash disk (SPI). Or do you try to implement bootloader which can update itself? \$\endgroup\$
    – TMa
    Oct 9, 2014 at 6:18
  • 2
    \$\begingroup\$ "Normally" the program code is located at address 0. As already mentioned, you can tell the linker to use a different address. After reset, the controller executes code starting at address 0 by default. You can set fuses to tell the controller to execute code from the boot flash section first. The boot section code then has to make sure to jump to address 0 after it is done. In every case, you would have to know your code size and calculate where it is safe to write to the flash without overwriting the application code. Note that it is only possible to write flash from the boot flash section! \$\endgroup\$
    – Rev
    Oct 9, 2014 at 6:29

1 Answer 1


Unless you tune your linker, the program will always start at address 0 and grow up. Additionally, if you have a bootloader, it will start at one of predefined addresses (either 0xF80, 0xF00, 0E00 or 0xC00, see table 26-7 in datasheet), and usually go to the top of the memory.

When people use flash memory for data, they usually put it as high as they can. So:

(1) Determine the memory top -- this depends on bootloader that you have. If you have Optiboot, it usually takes 512 or 256 words: https://code.google.com/p/optiboot/wiki/HowOptibootWorks , so we will assume it starts at 0xE00.

(2) Determine how much data you need. Lets say you need 256 (0x100) bytes. This means you will place your datablock at 0xE00 - 0x100 = 0xD00. You can pass values between 0xD00 and 0xDFE to boot_page_* functions.

(3) Write your program.

(4) Check how much space it occupies. It can take up to (0xD00 - 1) = 3328 bytes. When I compile from command-line, I use 'avr-size' for that:

$ avr-size -C --mcu=atmega328 firmware.elf
AVR Memory Usage
Device: atmega328

Program:     904 bytes (2.8% Full)
(.text + .data + .bootloader)

Data:          2 bytes (0.1% Full)
(.data + .bss + .noinit)

Look at 'program' section -- only 904 bytes are used, plenty of space left. If you see a number of 3328 or more there, make your program shorter. Otherwise, the program will compile and upload, but it will crash randomly.


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.