On 07/03/2019 13:16, Freddie Chopin wrote: > Hello Segher! > > On Thu, 2019-03-07 at 06:08 -0600, Segher Boessenkool wrote: >> You probably should use a linker script for this. > > You think of anything better than placing each variable in its own > section and placing them manually in the linker script in the order I > like? I would like to avoid any messing with linker script if that's > possible... If there's nothing better I may end up using suffixes > ("section.1", "section.2", "section.3", ...) and sort the sections in > the linker script (`*(SORT(.section.*));`), but I would still prefer to > solve that in the source file only. The -fno-toplevel-reorder switch can be handy too - it will stop re-ordering within a translation unit. > >> The compiler can optimise away (some of) those variables even, or not >> always keep them in memory, etc., unless you use volatile on the >> vars. > > No worries, it won't optimize them away, there's also a header where > these variables are declared with `extern ...` (omitted that in the > example, as this doesn't change anything) and all of them will be used > in the project. I'm just concerned about their order. > "extern" does not affect whether they are optimised away or not - if the variables are declared at the file / namespace level without "static", they will have external linkage and be created within the translation unit. However, if you are using LTO or -fdata-sections and the --gc-sections linker option, variables that are not needed get eliminated. (Note that this could happen even if they are actually used, if the compiler can figure out that the storage is not needed.) I have seen people try to use section attributes and careful linker setups to get consistent memory layouts between program versions. (Usually it is eeprom, rather than battery backed ram, but the principle is the same.) It is often possible to get a reasonable solution - it is rarely possible to get a good and reliable solution that caters for all possibilities. Typically things break down when you want to add a new variable. My personal preference is to make a struct definition that holds /all/ the variables in the special area. This makes it easy to track, and easy to be sure that you have everything where you expect it. My struct here starts with some metadata - an indicator of the program type (if you have more than one program for the same card), a struct version number (so that a new program version can re-use old data while knowing that new data might not be properly initialised), and typically stamps and CRC's for allowing multiple versions of the data. (That is relevant for eeproms that take some time to store the data, when you might have a power fail during write - it is less relevant for battery backed ram.) This means you don't get to define your data neatly in the modules that use the data, but it does mean you have no problem with layouts or consistency.