GCC support for >64K devices

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a link that summarizes what the current support for the larger devices is?

One thing that currently has me wondering is a bootloader that I'm porting for a Mega2561. I noticed in the GCC generated startup code that it tries to copy the data section using lpm. Is there a switch for this or do I just have to replace it with my own?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I noticed in the GCC generated startup code that it tries to copy the data section using lpm
This comes from gcrt1.S for the larger avr's, and I can't find any crtm2561.o's that don't use elpm (20070525 - 20080512).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
Quote:
I noticed in the GCC generated startup code that it tries to copy the data section using lpm
This comes from gcrt1.S for the larger avr's, and I can't find any crtm2561.o's that don't use elpm (20070525 - 20080512).

This is built in Avr Studio for the Mega2561 using 20080610.

0003f01e <__ctors_end>:
   3f01e:	12 e0       	ldi	r17, 0x02	; 2
   3f020:	a0 e0       	ldi	r26, 0x00	; 0
   3f022:	b2 e0       	ldi	r27, 0x02	; 2
   3f024:	ea eb       	ldi	r30, 0xBA	; 186
   3f026:	f7 ef       	ldi	r31, 0xF7	; 247
   3f028:	02 c0       	rjmp	.+4      	; 0x3f02e <.do_copy_data_start>

0003f02a <.do_copy_data_loop>:
   3f02a:	05 90       	lpm	r0, Z+
   3f02c:	0d 92       	st	X+, r0

0003f02e <.do_copy_data_start>:
   3f02e:	a0 31       	cpi	r26, 0x10	; 16
   3f030:	b1 07       	cpc	r27, r17
   3f032:	d9 f7       	brne	.-10     	; 0x3f02a <.do_copy_data_loop>
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahhh, just realized I'm linking with -nostartfiles in order to suppress the vector table which is causing the problem. Is this just a side effect or should the correct copy code still be emitted?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

__do_copy_data is now coming from libgcc.a for some reason. I don't know what is referencing those functions to get them pulled in (__do_clear_bss is always from libgcc.a, though).

edit- it appears the compiler always creates those global symbols, causing either the function to be pulled in from the library, or in the case of >64k, since the function is provided by crt*.o, there is no need to get it from libgcc.a (with -nostartfiles, it wants to then get it from libgcc.a)

( -nodefaultlibs 'eliminates' libgcc.a including those functions, but the rest of libgcc.a is then unable to be used. )

You could yank out the __do_copy_data function from gcrt1.S if you still need to copy data, and let libgcc.a provide the __do_clear_bss as before. With your own __do_copy_data function, it will not be pulled in from libgcc.a. If __do_clear_bss is not wanted, just make an empty function so it doesn't pull it in from the library.

I never realized those symbols were being generated by the compiler, so I used -nodefaultlibs to get rid of the data/bss startup code (<64k avr's), but I guess a couple empty functions would do the same, and not prevent usage of other libgcc.a stuff.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for all the info on this. I'll need to do some more investigating to see if I can make better sense of it.

Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This may explain better (probably not)-

//=========== <=64k ==========
//----startfiles
//crt*.o (gcrt1.S)
//.vectors
//.init2
//.init9
//----startfiles
//
//libgcc.a
//.init4
//the following get 'pulled' from the
//library because these symbols are defined
//by the compiler (and functions not provided
//anywhere else)
//__do_copy_data 
//__do_clear_bss

//=========== >64k ==========
//----startfiles
//crt*.o (gcrt1.S)
//.vectors
//.init2
//.init4 (__do_copy_data)
//.init9
//----startfiles
//
//libgcc.a
//.init4
//__do_clear_bss
//no need to pull __do_copy_data from
//library, because crt*.o already provides it


// -nostartfiles
//=========== <=64k ==========
//libgcc.a
//.init4
//the following get 'pulled' from the
//library because these symbols are defined
//by the compiler (and functions not provided
//anywhere else)
//__do_copy_data 
//__do_clear_bss

// -nostartfiles
//=========== >64k ==========
//libgcc.a
//.init4
//the following get 'pulled' from the
//library because these symbols are defined
//by the compiler (and functions not provided
//anywhere else)
//__do_copy_data <<the 'wrong' one 
//__do_clear_bss

When -nostartfiles is used, the crt*.o is eliminated. Which means __do_copy_data is no longer there, but the global symbol causes it to be pulled from the library instead, and is the 'wrong' code (not for large avr's).

It seems libgcc.S should probably be setup to take care of __do_copy_data in all cases instead of having the crt take care of it for large avr's. That way the -nostartfiles option will act the same way for all avr's. (Probably some reason they do it the way they do it, that I don't see).

If you want -nostartfiles to act exactly as before, you have to provide your own __do_copy_data to prevent the 'wrong' one being pulled from the library. If you use -nostartfiles and -nodefaultlibs, then it doesn't make any difference.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great! I just made a dummy __do_copy_data since I copy my own anyway. The one thing I did have to do was set EIND in my startup code because the "prologue save" uses a EIJMP but the EIND setting is removed with the __do_copy_data. At any rate it seems to work perfect now.

I can't help but think that the lack of extended support is more of an oversight (bug?) especially since each device group seems to have its own copy of libgcc.a Maybe one of the GCC gurus will chime in with more info on this.

Thanks again,
Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have used the mega2560 for a couple of years now. When I first started, I did the heretical: I compiled my boot as part of the app. This (unknowingly by me) eliminated the __do_copy_data call from the boot, since it was merely relocated code, not a full app by itself. By the way, I've avoided pre-initialized variables in my boot like the plague, so again this problem would not have reared its ugly head.

I think you are actually doing the right thing here. I've avoided separately compiling the boot mostly because what I have works. I now realize that there may be more to the "separate compile" idea than I thought.

The extended pgmspace support is a lack. Carlos Lamas posted an extended version of the pgmspace stuff that I think you already have. However, as you point out, the problem extends to other parts of the library.

Unfortunately, the way that the core code works is a bit incompatible with the large (> 64 KBytes Flash) devices, with the worst problems showing up in the really large (> 128 KBytes Flash) devices.

I'm sure this could be solved a a bit of effort. Of course, since the entire GCC/avr-libc effort is run by volunteers, you can help by giving your time and effort to improving things. After all, if this is "free" as in "free speech", then your voice should be heard, eh? :wink:

At any rate, you'll need to muddle through the best you can. Maybe, at the other end of the tunnel, you can post a tutorial on what you've found. :shock:

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Stu,

At the very least I'll publish the ported code as a project here. If I get more definite answers to some of the crt/lib questions I may even write up a small tutorial. I think bootloaders present a little more challenge here than a conventional app would but it never hurts to know a little more about whats going on behind the scenes. Those that have donated their time and talent certainly deserve a pat on the back for getting gcc as far as it is.