Building the AVR toolchain

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

Greetings list,

So I've decided to take the plunge and build the entire AVR toolchain from source.

With guidance from:

... I managed to make a fair amount of progress. GNU Binutils, GCC, and AVR LibC have all built with no errors. So did SimulAVR. GDB installed with some complaints, as did AvarICE (which I likely won't use anyway). AVRDUDE was not so co-operative. At the moment I'm not so worried about that because I can always use my distro's version. I suspect the bulk of these issues are related to the age of the distro I am building on (Ubuntu 10.04.4 LTS). However, since I've successfully built the three main components I am not especially concerned yet.

As a test, I tried building a few existing test projects to validate the toolchain. So far, so good. Except when trying to build with some of my preferred compiler options. Notably, --combine and -fwhole-program. The former appears not to be supported anymore:

avr-gcc: error: unrecognized command line option '--combine'

... and there's no mention of it in the manpage. Building with just -fwhole-program causes other problems. Specifically, a ton of 'undefined referece' errors. This did not happen when building under 4.3.2 or 4.3.3.

The new toolchain:

    binutils-2.23.1.tar.bz2 gcc-4.8.0.tar.bz2
    avr-libc-1.8.0.tar.bz2
    avrdude-5.11.1.tar.gz
    gdb-7.5.1.tar.bz2
    simulavr-1.0.0.tar.gz
    avarice-2.13.tar.bz2
... with the support of
    cloog-0.18.0.tar.gz gmp-4.3.2.tar.bz2
    isl-0.11.1.tar.bz2
    mpc-1.0.1.tar.gz
    mpfr-3.1.2.tar.bz2
Any ideas would be welcome. For example, should I stay away from the bleeding edge? If I roll back to, say, GCC 4.7.2, then what versions of all other tools and support packages should I build?

Cheers,
JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Googling for -combine says that it was removed on GCC 4.6. Have to dig into the changelog/source history to know why.

If you were using -fwhole-program with combine and passing multiple C files, then you're bound to get linker errors, as whole-program assumes the current compilation unit is the whole program.

-flto (Link time optimization) is based on a similar (same?) idea - do inter translation unit optimizations when all the code for the final executable is available. Did you give that a try?

Regards

Senthil

 

blog | website

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

saaadhu wrote:
Googling for -combine says that it was removed on GCC 4.6. Have to dig into the changelog/source history to know why
I had missed that, thanks.
Quote:
If you were using -fwhole-program with combine and passing multiple C files, then you're bound to get linker errors, as whole-program assumes the current compilation unit is the whole program.
I imagine that is what --combine used to do for me...?
Quote:
-flto (Link time optimization) is based on a similar (same?) idea - do inter translation unit optimizations when all the code for the final executable is available. Did you give that a try?
I didn't yet. I recall the manpage cautioning against using it in concert with -fwhole-program, and I didn't really play any further than that.

I am at lunch on a mobile right now, I'll poke around later today. Thanks for the advice...

[edit]
Yup. That's the ticket. Seems a wiser way to do it, too. The man page is a bit misleading. It both cautions agains using it in conjuntion with -fwhole-program, but later suggests it.

Thanks for the tip!
[/edit]

Cheers,
JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Mar 24, 2013 - 03:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you read Bingo's sticky at the top of this forum? The key issue
when building toolchains isn't so much the nuts and bolts of
building the core toolchain but knowing where to look for the all
important patches ...

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

clawson wrote:
Did you read Bingo's sticky at the top of this forum?
I gave it a glance :) Didn't read all 16 pages...

At the moment I'm trying to decide whether to bother spending time resolving the build issues with the other tools. As I have Binutils, GCC, and AVR LibC successfully built, I wanted to see how well they performed w.r.t. some of the issues I have faced in the past. Many a response to my querries on these fora have amounted to "have you compiled your broken code with a recent toolchain?" I wanted to see what all the fuss was about :)

So far, to be honest, I haven't seen much reason to spend the effort. I still see a lot of missed optimizations. I realize there are bigger fish to fry, like fixing bugs, wrong compilation, etc., but I was never hit by those. The fact that an empty ISR still compiles to this:

00000058 <__vector_8>:
  58:	1f 92       	push	r1
  5a:	0f 92       	push	r0
  5c:	0f b6       	in	r0, 0x3f	; 63
  5e:	0f 92       	push	r0
  60:	11 24       	eor	r1, r1
  62:	0f 90       	pop	r0
  64:	0f be       	out	0x3f, r0	; 63
  66:	0f 90       	pop	r0
  68:	1f 90       	pop	r1
  6a:	18 95       	reti

... is a bit dissapointing. Twenty bytes of flash and 19 cycles, where 2 bytes and 4 cycles would do.

Quote:
The key issue when building toolchains isn't so much the nuts and bolts of building the core toolchain but knowing where to look for the all important patches and which must be applied to the head of repository / label.
The links mentioned in my original post seemed pretty thorough. They did mention patches to apply to Binutils and GCC, but those patches were because "The official version of might lack support for recent AVR devices", and in any case they predated the latest versions of these components with which I was building.
Quote:
Sadly this is the kind of thing the Canonical engineers building Ubuntu repo versions don't seem to know about. (nor did Atmel it appears in their first attempts to build/issue their own "Toolchain" though they now seem to have got the hang of things). In fact if you could live with a 4.6.2 until Atmel release a standalone version of the 4.7.2 in 6.1beta then their Linux Toolchain is pretty good.
I can live with 4.3.2 or 4.3.4. I just wanted to have newer toolchains around so I can add "yes, I tried with 4.x.x and the problem persists" to any future posts :)

In all seriousness, I am interested in migrating away from the past. Would you in fact recommend 4.6.2 as a good next step? I expect I will still have some challenges when building, at least until I make the plunge to a more recent distro. Ubuntu 10.04.4 LTS is my preferred distro. Support for the desktop version ends next month, but support for the server version continues until 2015. I am only interested in LTS versions, and I haven't made the plunge to 12.04 LTS because of the move away from Gnome to Unity (didn't want to fuss with configuring Gnome on my own. I will probably move to Kubuntu instead). At some point I will install a VM to test that theory.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I'd give this a go:

www.atmel.com/tools/atmelavrtool...

Oh and our corporate choice is to use Kubuntu 12.04LTS, I like the interface.

Oh and if you don't like the stock prologue / epilogue of an ISR (it is a bit sad if you aren't interrupting MUL and the code in ISR is relying on R1=0) then look into ISR_NAKED but obviously the prologue / epilogue then becomes your responsibility including the reti().

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

clawson wrote:
I'd give this a go:

www.atmel.com/tools/atmelavrtool...

Embarassing that I never knew about this. I should look up from my keyboard more often.

This lacks GDB, avrdude, simulavr, and avarice, but I will add this to my now growing list of build environments. Thanks.

Quote:
Oh and our corporate choice is to use Kubuntu 12.04LTS, I like the interface.
I've never been a fan of out-of-the-box KDE. Gnome either, by the way, but it was a more natural migratory path away from windoze for others in my household (are we not all our parents' sysadmins?) And I didn't care enough to maintain two environments. I cannot abide Unity :) I'll learn to cope with KDE. I'm sure I'll wonder why I ever resisted.
Quote:
Oh and if you don't like the stock prologue / epilogue of an ISR (it is a bit sad if you aren't interrupting MUL and the code in ISR is relying on R1=0) then look into ISR_NAKED but obviously the prologue / epilogue then becomes your responsibility including the reti().
Yes, I long ago started writing most of my ISR code in assembler. For example:
// just for wakeup
ISR(ADC_vect, ISR_NAKED) {
  __asm__ __volatile__ ("reti");
}

... inelegant though it is.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
// just for wakeup 
EMPTY_INTERRUPT(ADC_vect);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or at the very least:

ISR(ADC_vect, ISR_NAKED) {
  reti();
} 

already defines reti().

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

> Did you read Bingo's sticky at the top of this forum? The key issue
> when building toolchains isn't so much the nuts and bolts of
> building the core toolchain but knowing where to look for the all
> important patches ...

Lately, this is no longer that much of an issue. Unless you really
need the latest AVR device that has been announced just 3 months ago,
you get along reasonably well these days by using the stock GNU
toolchain.

@joeymorin, if you need help compiling AVRDUDE, best ask on its
mailinglist about it. Normally, it's supposed to compile reasonably
well out of the box, as long as your system installs the header files
for the required libraries (in particular, you might be interested
in getting libusb support).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

snigelen wrote:

// just for wakeup 
EMPTY_INTERRUPT(ADC_vect);

clawson wrote:
Or at the very least:
ISR(ADC_vect, ISR_NAKED) {
  reti();
} 

already defines reti().

It's an embarrassing week for me :)

In truth, I have been using:

// just for wakeup
ISR(ADC_vect, ISR_NAKED) {
  __asm__ __volatile__ ("reti");
}

... since the days when I worked exclusively within the Arduino IDE. I hadn't even heard of . The funny thing is, I since have read the docs many times. I even noticed EMPTY_INTERRUPT() and ISR_ALIASOF() and thought "how interesting, I bet I could put that to use..." but just never made the connection ;)

I note with interest that the syntax suggested in the docs

 EMPTY_INTERRUPT(ADC_vect);

... generates a warning when compiling with -pedantic:

main.c:14: warning: ISO C does not allow extra ‘;’ outside of a function

Dropping the terminal semicolon vanishes the warning, and the generated code is nevertheless correct.

I'm still curious to learn what mechanism is responsible for the missed prologue/epilogue optimization in:

ISR(ADC_vect) {
}

Although multiple solutions are available the prevent the prologue/epilogue from being generated in the first place, it seems odd that at no point in the compile/link process is the redundant code identified for elimination, even with -flto and/or -fwhole-program.

Not to hijack my own thread, nor to [bump] another, but I am curious how apparently simple questions like:

"Why, even with

int main(void) __attribute__ ((__noreturn__));

... does main get an RCALL instead of an RJMP (eating 2 bytes from the stack)." ... and ... "Why do _exit and _stop_program not get optimized away?"

Of course, now that I've put this in writing some helpful soul will shortly point out some easy, obvious, universally known, googleable solution, thus increasing my week's ration of embarrassment even more :) I realize I say "apparently simple" quite cavalierly, without any knowledge of the toolchain internals, nor of any kind of bigger picture. I does make me wonder when I'll stop talking about it, crack open some source code, and contribute. I've a lot to learn first.

Many thanks to all who continue to help :)

Cheers,
JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

joeymorin wrote:

"Why, even with
int main(void) __attribute__ ((__noreturn__));

... does main get an RCALL instead of an RJMP (eating 2 bytes from the stack)."

The call to main comes from gcrt1.S (avr-libc), which is assembled at avr-libc build time and is automagically linked into the final executable. So
1. The call is made from assembly code
2. Address resolution happens at link time, and all attribute/compiler control flow knowledge is lost by that time.

OTOH, I don't see the compiler doing it even when it knows about enough either

volatile int x = 2;

int __attribute__((noinline)) foo() 
{
    x = 3;
    while (1);
}

int main()
{
    foo();
}

still generates an rcall to foo, at -O2 and -Os. Should be interesting to figure out why.[/code]

Regards

Senthil

 

blog | website

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

Quote:

still generates an rcall to foo, at -O2 and -Os. Should be interesting to figure out why.

OK, I'll bite. Just as an observer: You expressly told the compiler "noinline". Yet you expect the compiler to disobey your command?

Quote:

Function Attributes documentation from GCC mentions:

noinline This function attribute prevents a function from being considered for inlining.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:
Function Attributes documentation from GCC mentions:

noinline This function attribute prevents a function from being considered for inlining.

This is not guaranteed. It goes on to say:
Quote:
If the function does not have side-effects, there are optimizations other than inlining that cause function calls to be optimized away, although the function call is live. To keep such calls from being optimized away, put

asm ("");

(see Extended Asm) in the called function, to serve as a special side-effect.

Look more carefully at @saaadu's code for foo:
while (1);

This should be enough for the compiler to know that it can dispense with the RCALL... no?

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Quote:

You expressly told the compiler "noinline". Yet you expect the compiler to disobey your command?

I think his suggestion was that the compielr could have spotted that it could (r)jmp rather than (r)call if it realised it could not come back. As it is the code generated is:

00000082 :
volatile int x = 2;

int __attribute__((noinline)) foo()
{
    x = 3;
  82:	83 e0       	ldi	r24, 0x03	; 3
  84:	90 e0       	ldi	r25, 0x00	; 0
  86:	90 93 61 00 	sts	0x0061, r25
  8a:	80 93 60 00 	sts	0x0060, r24
  8e:	ff cf       	rjmp	.-2      	; 0x8e 

00000090 
: while (1); } int main() { foo(); 90: 0e 94 41 00 call 0x82 ; 0x82 00000094 <_exit>: 94: f8 94 cli 00000096 <__stop_program>: 96: ff cf rjmp .-2 ; 0x96 <__stop_program>

this is an improvement over previous GCC which used to create:

...
  76:	0e 94 48 00 	call	0x90	; 0x90 
7a: 0c 94 4d 00 jmp 0x9a ; 0x9a <_exit> 00000082 : volatile int x = 2; int __attribute__((noinline)) foo() { x = 3; 82: 83 e0 ldi r24, 0x03 ; 3 84: 90 e0 ldi r25, 0x00 ; 0 86: 90 93 61 00 sts 0x0061, r25 8a: 80 93 60 00 sts 0x0060, r24 8e: ff cf rjmp .-2 ; 0x8e 00000090
: while (1); } int main() { foo(); 90: 0e 94 41 00 call 0x82 ; 0x82 } 94: 80 e0 ldi r24, 0x00 ; 0 96: 90 e0 ldi r25, 0x00 ; 0 98: 08 95 ret 0000009a <_exit>: 9a: f8 94 cli 0000009c <__stop_program>: 9c: ff cf rjmp .-2 ; 0x9c <__stop_program>

Where code early in the CT would call main then, when it came back it would jump to exit: but now that's simply done by falling through.

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

Quote:

This is not guaranteed. It goes on to say:

What does the analysis of "do nothing" code have to do with inlining?

I have no vested interest here, so I'll step aside. "How many angels can dance on the head of a pin?" http://en.wikipedia.org/wiki/How...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

The compiler can optimize away the call to the function itself, if it detects that it doesn't do anything.

Anyway, as Cliff suggested, I was curious why the compiler did an RCALL to a function that it knows will never return.

Regards

Senthil

 

blog | website