0

I want to initialize local (const) array:

void foo() {
    const uint8_t arr[] = {1, 2, 3, 4, 5};
}

And for that initialization I pay 5 bytes of global RAM: those 5 constants are being copied to RAM at the start of the program and stay there forever. The question is why? Couldn't the compiler just initialize the array directly from the FLASH when I call the function? I can't use that right-hand temporary array anywhere else anyway, it must be destroyd right after ; and yet it persists in RAM at all times after the startup. Now I have to do something like

void foo() {
    static const uint8_t init_arr[] PROGMEM = {1, 2, 3, 4, 5};
    uint8_t arr[5];
    copy_from_prog_function(arr, init_arr, 5);
}

And on top of that, now I can't even have my arr to be const!

Is there more elegant solution to this problem?

Alex Cat
  • 21
  • 4
  • I would suspect this is related to some Harvard architecture nonsense. In which case you are essentially asking "is there any elegent ways to use AVR" - and as for all other 8-bitters on the market, the answer is no. Might want to consider switching to a 21th century CPU core like ARM. – Lundin Oct 24 '17 at 06:53
  • @Lundin gcc has a very nice extension called "named address spaces". BTW I do not use AVRs for years as there are much more powerful and cheaper 32 bits micros on the marker – 0___________ Oct 24 '17 at 09:13

1 Answers1

1

As you probably know, AVR is a harvard architecture -- the program resides in a different address space than the data and instructions to access it are different. C doesn't have means for different address spaces, so you have to use compiler extensions (like this PROGMEM macro) here.

As program memory can only be read byte-wise (and is a bit slower than RAM because it's backed by flash), the compiler will never put data there automatically. See also Data in Program Space of the avr-libc documentation, especially the "Note on const".

That said, if the array is const anyways, why don't you declare it static? Then the compiler wouldn't create code to copy it on the stack, you'd access it directly, but still in RAM.

If you want it to reside in program memory, just declare it like in your second example and access the individual elements using the pgm_read_byte() macro, no need to copy the whole array yourself.

As suggested by PeterJ_01, with newer AVR toolchains, you can even use a simpler syntax for direct flash accesses, so the code looks "nicer".

  • 1
    It is a bit obsolete way. Newer (ie less than 5 years old) gcc versions have extension called "named address spaces" and the access is much easier. Just use __flash prefix const uint6_t __flash a[] = {1,2,3,4,5}. For more details http://www.rowleydownload.co.uk/arm/documentation/gnu/gcc/Named-Address-Spaces.html – 0___________ Oct 24 '17 at 08:19
  • @PeterJ_01 nice syntactic sugar, haven't seen it yet. Anyways, it boils down to the same mechanisms, just makes the code easier on the eyes :) –  Oct 24 '17 at 08:32
  • It is of course - but actually it makes access easier and more C :). The pointer handling is much much easier as well. Now it a problem of the compiler not the coder. – 0___________ Oct 24 '17 at 08:52
  • @PeterJ_01 where that feature was added? I have compiler that shipped with atmel studio 7 and "avg-gcc --version" reports 5.4.0. I tryed to download "latest" toolchain from microchip.com, but gcc version there is 4.9.2. Both of them does not know "__flash" keyword. If that feature realy exists in the latest versions of gcc that would help me a lot. Could you maybe post a link to such compiler? – Alex Cat Oct 24 '17 at 09:25
  • 1
    I just compiled with the AS7. No problems at all. Do not look at the IDE as VisualStudio (AS is the visual studio + some extensions) does not know anything about gcc extensions and it makes them "red" on the screen – 0___________ Oct 24 '17 at 09:36
  • 1
    I realized that this feature is supported only in C, but not C++. Shame. I won't give up c++ just for that and I can't imagine anyone would. – Alex Cat Oct 24 '17 at 09:59
  • @AlexCat well, I'd never start with C++ on an AVR, but that's most of the time a matter of taste ;) Nevertheless, you double-tagged here, so I'm leaving the hint about this "nicer" syntax in my answer. –  Oct 24 '17 at 10:05
  • Yeah, the answer is valid, I was imprecise because I thought it wouldn't matter. – Alex Cat Oct 24 '17 at 10:12