allocated section `xyz' not in segment - SOLVED

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you've used the older AVR32 studios, you've seen these build warnings. If you've upgraded the studio & tool chains, you probably noticed they went away somewhere among the upgrades. Alas, I've never seen any mention of exactly HOW Atmel resolved this. And if you're using unmodified linker scripts, you probably don't care. :D

But if you're adding your own linker sections, for example for SDRAM use, you may still be getting this error/warning. For various reasons, I didn't upgrade from Studio 2.02 to 2.2 until today, and found that SOME of my added linker sections still generated these warnings.

In my case, I need a 64 byte chunk of internal RAM that survives reset - in other words, it's not overwritten by the code in Crt0.S that copies data from flash to RAM (section .data) and zeros the BSS section of RAM (section .bss). So I stuck the segment definition outside those areas, like this:

  .reset_ram ORIGIN(INTRAM)	: 
	{ 
		*(.reset_ram) 
	}  >INTRAM AT>INTRAM :INTRAM

That puts the segment starting at address 0x04 (for some reason the linker is told that RAM starts at 0x04 instead of 0x0, I still haven't figured out why).

Then I defined a C variable using that section, the structure ResetRamS is 64 bytes long:

ResetRamS ResetRam __attribute__ ((section(".reset_ram"))) ;

This causes the error. After a half day of fiddling & Googling, no answers came but more information did. The PHDRS section of the linker script defines Program HeaDeRS for ELF files, the rest of the linker thinks of these as segments. When an ELF program is loaded (on a Linux system, or whatever) the loader scans the PHDRS to determine what to load into memory and where. Anything outside of a PHDR won't be loaded.

Of course, in an embedded system, the loader function is taken care of by code in Crt0.S that copies data from linker symbol _data in flash to symbol _edata in flash, with a destination address of _data_lma in RAM (at least, in my code it does). Similarly it zeros the bytes of RAM from _bss_start to _end.

Here's the PHDR section of my linker file:

PHDRS
{
  FLASH 	PT_LOAD;
  INTRAM_ALIGN 	PT_NULL;
  INTRAM_AT_FLASH	PT_LOAD;
INTRAM 			PT_NULL;
  NVRAM 		PT_LOAD;
  FLASH_HI_ZERO_PAGE	PT_LOAD;
USERPAGE 		PT_LOAD;
  SDRAM_PHDR 		PT_NULL;
}

Segments marked PT_LOAD will be loaded by the loader, segments marked PT_NULL won't. (The PT_NULL sections are new and part of how Atmel resolved the warnings.) Of course I have no loader, but the linker doesn't know that. So the linker is warning me that section .reset_ram is allocated (since I have a variable placed in that section) but it's not in a segment - which isn't true. It's in segment INTRAM, but that's not a LOADABLE segment! I wish GNU would change that error message, it's not strictly true.

Finally, solving the problem became easy. I added a new PHDR line:

INTRAM_DUMMY	PT_LOAD;

And changed the segment definition:

  .reset_ram ORIGIN(INTRAM)	: 
	{ 
		*(.reset_ram) 
	}  >INTRAM AT>INTRAM :INTRAM_DUMMY

And the error goes away. My struct is placed at 0x04, outside of the data and bss sections and so is not initialized at reset. Since the segment it resides in is marked PT_LOAD, the linker is happy because it thinks my non-existent loader will now do something with the section.

Of course, for this to work you need to ensure that you place this at a point in the link script outside the normal data, text and bss sections. You don't need to locate it at ORIGIN(INTRAM) either, you can specify any address you want outside the standard sections, or let the linker choose the address. In my case, I have to deal with updating firmware in the field and can't let the linker move it around as I change my code, so I stuck it at the start of RAM.

Hope this helps someone!

System info: Win XP, WinAVR 20100110, AVR studio 4.18 build 700, JTAGICE MKII. Atmega 168 & 328, Xmega 192A3.