0
\$\begingroup\$

I have struggled to understand this code but I can't understand the little endian for loop. Why is it necessary? And how could I read the page back? One byte at a time as an array? Is it even possible? Code from here

#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
void boot_program_page(uint32_t page, uint8_t *buf) {
    uint16_t i;
    uint8_t sreg;
    // Disable interrupts.
    sreg = SREG;
    cli();
    eeprom_busy_wait();
    boot_page_erase(page);
    boot_spm_busy_wait(); // Wait until the memory is erased.
    for (i = 0; i < SPM_PAGESIZE; i += 2) {
        // Set up little-endian word.
        uint16_t w = *buf++;
        w += (*buf++) << 8;
        boot_page_fill (page + i, w);
    }
    boot_page_write(page); // Store buffer in flash page.
    boot_spm_busy_wait(); // Wait until the memory is written.
    // Reenable RWW-section again. We need this if we want to jump back
    // to the application after bootloading.
    boot_rww_enable();
    // Re-enable interrupts (if they were ever enabled).
    SREG = sreg;
}
\$\endgroup\$
3
  • 2
    \$\begingroup\$ You found the code somewhere, perhaps they explain why it does that. read the ATMEGA328P datasheet about it's flash memory and program space, and try to find notes/comments on this issue. I suggest doing a "find" search on the datasheet for "endian" to find any comments about this particular issue you cannot understand \$\endgroup\$
    – KyranF
    Oct 7, 2014 at 6:31
  • \$\begingroup\$ Can you include a link to where you found the code? \$\endgroup\$
    – David
    Oct 7, 2014 at 7:21
  • \$\begingroup\$ The code above can be found at: nongnu.org/avr-libc/user-manual/group__avr__boot.html \$\endgroup\$
    – zmechanic
    Nov 22, 2017 at 23:26

1 Answer 1

1
\$\begingroup\$

I searched the datasheet, there is nothing about endian-ness. The issue might just be how you write to the flash memory. It seems to write to flash memory the 'words' are two bytes long, but the address itself is per byte. The original programmer was obviously a good kid, and read this part of the AVR-libc reference: "Note The address is a byte address. The data is a word. The AVR writes data to the buffer a word at a time, but addresses the buffer per byte! So, increment your address by 2 between calls, and send 2 data bytes in a word format! The LSB of the data is written to the lower address; the MSB of the data is written to the higher address."

source

The first half (byte) of 'w' is the byte pointed at by the dereferenced pointer 'buf' which is then incremented by 1 (by the ++). The second half of the word 'w' is done by this line " w += (*buf++) << 8" and what this does is adds the upper half (which is the contents of the address pointed to by 'buf' at the next byte) by shifting the byte left 8 bits. This puts it in the upper half, as I said.

You now have 'w' which contains two bytes of data, as a 'word' ready to be written with boot_page_fill function, a function from the AVR-Libc library.

If you ever do not understand the inputs to functions you should always try to look up the reference and see the comments that I found and showed above.

\$\endgroup\$
5
  • \$\begingroup\$ I did read the documentation and the datasheet but some concepts wasn't clear at all. And how can I read the memory back? For example, the next time I turn on the chip. I don't find any C function or MACRO neither the datasheet or avr-libc. \$\endgroup\$
    – Worakls
    Oct 7, 2014 at 17:11
  • \$\begingroup\$ @Worakls: Not even here? \$\endgroup\$ Oct 7, 2014 at 17:21
  • \$\begingroup\$ "The LSB of the data is written to the lower address; the MSB of the data is written to the higher address." - that is a description of little-endian organization. \$\endgroup\$ Oct 7, 2014 at 19:38
  • \$\begingroup\$ @Worakls you can read program space memory but you need special instructions from the provided libraries, because it's outside of the normal address space \$\endgroup\$
    – KyranF
    Oct 7, 2014 at 19:50
  • \$\begingroup\$ I read there's 256 pages of 128 bytes each one. But in Atmega328p what address have each page? It's correct to say "page_address = number_of_page * page_size" ? And does the program code start exactly at the end of the pages? \$\endgroup\$
    – Worakls
    Oct 9, 2014 at 0:14

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.