2

Author Topic: AVR gcc 'region text is full' error?!  (Read 12115 times)

0 Members and 1 Guest are viewing this topic.

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,659
  • Helpful? 169
    • Society of Robots
AVR gcc 'region text is full' error?!
« on: June 17, 2007, 11:10:01 AM »
I compiled my file ERP.c and got this really odd error:

Quote
c:\program files\winavr\bin\..\lib\gcc\avr\4.1.1\..\..\..\..\avr\bin\ld.exe: region text is full (ERP.elf section .text)
make: *** [ERP.elf] Error 1


What does that mean?!?

A google search on it was fairly useless . . .
http://www.google.com/search?hl=en&safe=off&rls=DGUS%2CDGUS%3A2006-11%2CDGUS%3Aen&q=%5Cavr%5Cbin%5Cld.exe%3A+region+text+is+full

Offline hazzer123

  • Supreme Robot
  • *****
  • Posts: 460
  • Helpful? 3
Imperial College Robotics Society
www.icrobotics.co.uk

Offline rgcustodio

  • Robot Overlord
  • ****
  • Posts: 217
  • Helpful? 0
  • Use "Search" and ye might find answers!
Re: AVR gcc 'region text is full' error?!
« Reply #2 on: June 17, 2007, 11:24:47 AM »
Your binary/program is too big to fit in the device's flash :)

1) Check that you are correctly using the right part. Check your compiler command line for something like "-mmcu=XXX". You might be incorrectly passing an incorrect part which contain smaller amount of flash than you actually have.
2) Enable "-Os" optimizations. Set it in your command line.
3) Optimize your code. This is the hard part.

You can also try to use an "older" version of WinAVR. The older versions seem to create smaller binary files as compared to the "newer" versions.


Use this search string instead:
http://www.google.com/search?hl=en&safe=off&rls=DGUS,DGUS:2006-11,DGUS:en&sa=X&oi=spell&resnum=0&ct=result&cd=1&q=winavr+%3E%3E++region+text+is+full&spell=1

Also, don't rely on the file size of the generated elf file to check if it'll fit in flash. Use avr-size to see the file's sections sizes.
« Last Edit: June 17, 2007, 11:40:05 AM by rgcustodio »
The best thing one can do when it's raining is to let it rain. - H. W. Longfellow

understanding is the path to enlightenment

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,659
  • Helpful? 169
    • Society of Robots
Re: AVR gcc 'region text is full' error?!
« Reply #3 on: June 17, 2007, 11:48:52 AM »
thanks!

hmmm appears it ran out of memory with only half the code I plan to use for it . . .

I guess I will switch the mcu out with a better one . . .

Offline AdminTopic starter

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,659
  • Helpful? 169
    • Society of Robots
Re: AVR gcc 'region text is full' error?!
« Reply #4 on: June 17, 2007, 01:40:09 PM »
Probably a stupid question, but is it possible to do "-Os" optimizations to only certain parts of my code? Im guessing no . . .

The reason why Im not using any optimization is because it deletes my delay code for servos.

Offline rgcustodio

  • Robot Overlord
  • ****
  • Posts: 217
  • Helpful? 0
  • Use "Search" and ye might find answers!
Re: AVR gcc 'region text is full' error?!
« Reply #5 on: June 17, 2007, 02:25:01 PM »
AFAIK, "-Os" can be used on a per file basis only.

Maybe you can move code that you don't want to be optimized to a separate file, and compile the rest with -Os.

Quote
The reason why Im not using any optimization is because it deletes my delay code for servos.

Are you using an empty loop? Try to add a simple statement in the loop ie dummy += 1; and declare dummy to be volatile uint8 or something.


BTW, here are other good optimization resources:
http://www.atmel.com/dyn/resources/prod_documents/doc1497.pdf
http://www.nongnu.org/avr-libc/user-manual/FAQ.html Find "Which -O flag to use?"

(Currently playing with an ATtiny13, 1K flash, as a robot brain for DeeSee).
The best thing one can do when it's raining is to let it rain. - H. W. Longfellow

understanding is the path to enlightenment

Offline JesseWelling

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 707
  • Helpful? 0
  • Only You Can Build A Robot!
Re: AVR gcc 'region text is full' error?!
« Reply #6 on: June 22, 2007, 07:30:01 PM »
If you are using an AVR and not using the timer outputs you could probably use the hardware timers right?
This is for using a ATMega128 at 16Mhz but if you are using an AVR the code could look pretty similar to this.

Offline pomprocker

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: AVR gcc 'region text is full' error?!
« Reply #7 on: July 14, 2008, 02:30:59 PM »
eeek I just saw this on my ATmega8! lucky I bought an ATmega168 a little while ago...

Offline izua

  • Supreme Robot
  • *****
  • Posts: 682
  • Helpful? 0
Re: AVR gcc 'region text is full' error?!
« Reply #8 on: July 14, 2008, 02:48:21 PM »
omeone here has a divine talent of digging up old threads ;D
Check out my homepage for in depth tutorials on microcontrollers and electronics.

Offline Webbot

  • Expert Roboticist
  • Supreme Robot
  • *****
  • Posts: 2,150
  • Helpful? 109
Re: AVR gcc 'region text is full' error?!
« Reply #9 on: July 21, 2008, 06:51:31 PM »
Ok its an old thread - but it does show some of the issues with optimisation.

Optimisation will try to get rid of code that 'does nothing' - that's its job!  For example:-
Code: [Select]
int i;
for(i=0; i<256; i++){
}

This code doesn't actually do anything - it just wastes time. At the time of compiliing your program the optimiser realises this - since all it does is use a local variable called 'i', and it doesn't call any other functions. So the compiler realises that this doesn't actually do anything so it throws all the code away.

But if your intention is that you WANT to waste time, say for the delay loop on a servo pulse, then you can fool the optimiser by saying that your variable is 'volatile' (which means that its value can change under interrupts). eg

Code: [Select]
void _delay_cycles(volatile unsigned int cycles)
{
while(cycles > 0){
cycles--;
};
}

Since the 'cycles' parameter is 'volatile' then it means that this routine could be effected by interrupts (although it isn't in reality). So the optimiser leaves it alone.

As a low level programmer you MUST understand the 'volatile' keyword - otherwise you will never be able to benefit from optimisation. Why is this? Variables are stored in memory but are loaded into registers in the microcontroller for comparison or arithmetic operations.  Code such as:
Code: [Select]
x = x + 1;
at runtime this will load the value of 'x' into register(s), add 1 to it, and then write the register back into the memory used to store the value of 'x'. Many compilers will only make the microcontroller do this once it has run out of registers. So lets consider a simple routine that waits for the next millisecond tick. Lets assume that an interrupt routine increments a variable called 'millis' and the rest of your code looks like this:-
Code: [Select]
unsigned millis = 0; // The variable that is incremented under interrupts
// Wait until the 'millis' has moved to the next value
for(unsigned now=millis; now==millis;){
}

With optimisation disabled then this is turned into the following pseudo code:-
Code: [Select]
load register with 0;
store register into variable millis;
load register from variable millis;
store register into variable now;
1)
load register from variable now;
register = register - variable millis;
if register equals zero then goto 1)

With optimisation enabled then we don't bother to write out the value to 'now' and then reload it immediately. We also may use more registers. So we may get:-
Code: [Select]
load registerA with 0;
// DONT 'store register into variable millis;' as we have it in registerA
// DON'T NEED TO 'load register from variable millis;' AS WE HAVE IT IN registerA
// DONT 'store register into variable now;' UNTIL WE NEED TO
1)
// DONT NEED TO 'load register from variable now;' AS WE HAVE IT IN registerA
// AT THIS POINT RegisterA has the value of 'millis' and of 'now'
// SO THE FOLLOWING LINE WILL ALWAYS RETURN 0 (ie  'now' = 'millis')
// register = register - variable millis;
// And is replaced by:
goto 1
So your loop will go round FOREVER !!!!.

This happens because the compiler doesn't know that the variable 'millis' is changed under interrupts so once it has been read into a register - it may not be read again. By making the variable 'volatile' then we force the compiler to re-read the variable wherever it is referenced and to write its value back immediately if it is changed.
This gives us the following pseudo-code that does what we expect:-
Code: [Select]
load registerA with 0;
store registerA into variable millis;
load registerA from variable millis;' - AS IT MAY HAVE BEEN CHANGED UNDER INTERRUPT
// DONT 'store register into variable now;' UNTIL WE NEED TO
1)
// DONT NEED TO 'load register from variable now;' AS WE HAVE IT IN registerA
// AT THIS POINT RegisterA has the value of 'now', but 'millis' may have changed under interrupt
registerB = registerA - variable millis;
if registerB equals zero then goto 1)
So our code now works again, and is slightly smaller than with no optimisation as we can hold the variable 'now' in registerA rather than reading/writing it from/to memory.




Is the optimiser being a pain? Well not really - its just doing its job. Say you wrote some (bad) code like this:-
Code: [Select]
int random(){
    if( 1 > 2){
        // This will never happen - but lets assume we have loads of code in here
    }else if( 2 < 1 ){
       // This will also never happen
    }else{
        return 1;
    }
}

At the time of compilation the optimiser can realise that the first two 'ifs' will NEVER happen and so will just generate the code for 'return 1'.

But the optimiser can also optimise for execution speed. So if your code does something like scan a 100 by 100 thing such as:
Code: [Select]
for(int y = 0; y < 100; y++){
   for(int x=0; x < 100; x++){
       int pos = y * 100 + x;
       readBit(pos);
   }
}
Then the optimiser should realise that the
Code: [Select]
int pos = y * 100 + x; wastes a lot of time as it does
Code: [Select]
y * 100 for each
Code: [Select]
x even though the
Code: [Select]
y hasn't changed. So, if optimising for speed then the optimiser should, at the very least, re-arrange your code as if it was:-
Code: [Select]
for(int y = 0; y < 100; y++){
   int temp = y * 100;
   for(int x=0; x < 100; x++){
       int pos = temp + x;
       readBit(pos);
   }
}

A more aggressive optimiser may realise that the following does the same thing:-
Code: [Select]
for(int pos= 0; pos < 10000; pos++){
       readBit(pos);
}

Optimisation is very helpful - but does have its unexpected issues. If you are using optimisaton and stuff is going wrong then turn the optimisation flags off, clean, and recompile. If you still have a problem then its your fault, otherwise its because the optimiser is being too helpfull and optimising stuff you dont want optimised. Having said that:- if you have a central method to pause for a given time then the rest of your code should only ever need to call this and can otherwise run at full speed - so optimisation should not be a problem.

Most compilers allow you to change the optimisation for certain bits of code, if you want, via the 'pragma' directive. However: I don't really recommend this. Your makefile should dictate if you are optimising for speed/code size/or none. Placing directives all over your code only makes it harder to make global changes.



Webbot Home: http://webbot.org.uk/
WebbotLib online docs: http://webbot.org.uk/WebbotLibDocs
If your in the neighbourhood: http://www.hovinghamspa.co.uk

 


Get Your Ad Here