Many thanks, Johann, for the clarification that your explanation has provided.
On 14.12.12 23:00, Georg-Johann Lay wrote: > The 64-bit ranges come from the ELPM instruction that takes the > 16-bits of Z-reg and concatenates RAMPZ as bits 16..23 to get a > 24-bit address. The common computer terms "paged" and "page aligned" seem to fit perfectly here. AIUI, the Z-reg is a page register, providing base 2^16 page addresses, and RAMPZ provides an address within the page. It is "page aligned", because any RAMPZ == 0 will always be 2^16 aligned in flash. The new linker script observes that constraint by starting each __flashN aligned to 0x10000 page boundaries, i.e. on 0xN0000. Up to now, I'd forgotten the other edge of the page, 0xNffff. I'll append a patch with everything including the assertions to do that. Please note that the address limit within each output section is relative, so they are all the same. ... > This means the compiler assumes that var is located in such a way > that all of its bytes are elements of [0x10000, 0x20000). That is a good explanation of "page alignment"¹. ;-) > The compiler puts var into section .progmem1.data to express this. And these input sections are caught by the output section which contains them, thus always matching up __flashN with .flashN. > If var is not located appropriately, the compiler still loads RAMPZ > with 1 and loads Z with the lower 16 bits of &var, but if var is at > 0x23456 the compiler will access 0x13456 instead and read garbage. There can be no risk of this happening, because the VMA specified on each .flashN, e.g.: .flash2 0x20000 : locks each __flashN to start at the beginning of a 0xN0000 page. ... Many thanks for the "stubs" explanation. I hadn't caught on to its relationship to trampolines. > .trampolines is subset of [EIND * 2^17, (1+EIND) * 2^17) .trampolines is subset of [EIND * 2^17, (1+EIND)] ? > EIND is set to 0 during startup. You can also set it to 1 in the > startup code and locate .trampolines appropriately. That optionality doesn't seem to be supported in the linker script. > Again, notice that the subset condition is trivially satisfied if > there are no stubs, i.e. .trampolines is empty. BTW: The compiler > does not set EIND in the program, and setting EIND by hand is not > supported. It's likely the user shreds the code if he sets EIND by > hand after the init stage. Ah, it's not used yet, then. ... > Maybe .trampolines needs some margin at the high end because it can > grow as the linker generates new stubs. I actually don't know. A minimum allocation, eaten when the .trampolines section grows, perhaps? That might speed up linking, but I figure it's pretty quick already. > Most of the stuff I know (or believe to know) comes from > reverse engineering when I tried to clean up EIND usage in avr-gcc > (PR50820) and to add some notes and caveats to the docs. Your knowledge is directly from the coalface, then - the most hard-earned and real kind. I'll try to make the linker scripts dance, to give us whatever you need to make that job easier. There's also an extra ALIGN(2) in this one, to stop an odd number of data bytes in __flashN from upsetting .text. (See, I have been doing more testing. :-) Erik ¹ Compare paragraph 2 at: http://en.wikipedia.org/wiki/Data_structure_alignment#Hardware_significance_of_alignment_requirements file: avr6.patch --- avr6.x-2.23 2012-12-13 13:42:18.000000000 +1100 +++ avr6.x-new 2012-12-15 21:55:31.000000000 +1100 @@ -70,13 +70,12 @@ .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } /* Internal text space or external memory. */ - .text : + .lowtext : { *(.vectors) KEEP(*(.vectors)) /* For data that needs to reside in the lower 64k of progmem. */ *(.progmem.gcc*) - *(.progmem*) . = ALIGN(2); __trampolines_start = . ; /* The jump trampolines for the 16-bit limited relocs will reside here. */ @@ -98,6 +97,28 @@ __dtors_end = . ; KEEP(SORT(*)(.ctors)) KEEP(SORT(*)(.dtors)) + *(.progmem.data*) /* Explicitly page 0 input sections */ + _elowtext = . ; + x = ASSERT (. <= 0x10000, "Error: .lowtext (128KiB limit) overflow. Try shrinking .progmem?") ; + } > text + + .flash1 0x10000 : + { *(.progmem1.data*) /* Page 1 */ + x = ASSERT (. <= 0x10000, "Error: __flash1 (64KiB limit) overflow. Need to shrink it.") ; + } > text + + .flash2 0x20000 : + { *(.progmem2.data*) /* Page 2 */ + _eflash2 = . ; + x = ASSERT (_eflash2 <= 0x10000, "Error: __flash2 (64KiB limit) overflow. Need to shrink it.") ; + } > text + + .flash3 0x30000 : + { *(.progmem3.data*) /* Page 3 */ + } > text + + .hightext ALIGN(2) : + { /* From this point on, we don't bother about wether the insns are below or above the 16 bits boundary. */ *(.init0) /* Start here after reset. */ @@ -146,7 +167,8 @@ KEEP (*(.fini0)) _etext = . ; } > text - .data : AT (ADDR (.text) + SIZEOF (.text)) + + .data : AT (_etext) { PROVIDE (__data_start = .) ; /* --gc-sections will delete empty .data. This leads to wrong start -- Very few things happen at the right time, and the rest do not happen at all. The conscientious historian will correct these defects. - Mark Twain, in "A Horse's Tale" _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-gcc-list