WinAVR - Cause compile to fail if EEMEM overflow

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

I am using AtmelStudio/WinAVR targeting an ATMega1284p and my compile does not fail when the EEMEM overflows (i.e.: larger than 4096).

 

Is there a compiler setting/utility that would cause the build step to fail in this case?

 

Chuck

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

You can achieve this using the linker script. If you build some existing code and look at the .map file you will find that 1284p is "avr51" architecture. So if you then look in the lib\ldscripts directory at the .x files you will see something like:

 Directory of C:\SysGCC\avr\avr\lib\ldscripts

18/08/2016  10:10             6,984 avr1.x
18/08/2016  10:10             6,989 avr2.x
18/08/2016  10:10             6,990 avr25.x
18/08/2016  10:10             6,991 avr3.x
18/08/2016  10:10             6,992 avr31.x
18/08/2016  10:10             6,991 avr35.x
18/08/2016  10:10             6,989 avr4.x
18/08/2016  10:10             6,991 avr5.x
18/08/2016  10:10             6,992 avr51.x
18/08/2016  10:10             6,992 avr6.x
18/08/2016  10:10             6,284 avrtiny.x
18/08/2016  10:10             6,994 avrxmega1.x
18/08/2016  10:10             6,994 avrxmega2.x
18/08/2016  10:10             6,994 avrxmega3.x
18/08/2016  10:10             6,994 avrxmega4.x
18/08/2016  10:10             6,994 avrxmega5.x
18/08/2016  10:10             6,994 avrxmega6.x
18/08/2016  10:10             6,994 avrxmega7.x

And because you know that 1284p is "avr51" then it will be avr51.x from all those that is used as it's linker script. Looking at the top of the file:

C:\SysGCC\avr\avr\lib\ldscripts>head avr51.x -n 20
/* Default linker script, for normal executables */
/* Copyright (C) 2014 Free Software Foundation, Inc.
   Copying and distribution of this script, with or without modification,
   are permitted in any medium without royalty provided the copyright
   notice and this notice are preserved.  */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:51)
MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = 128K
  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 0xff00
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
  signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
}
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  .hash          : { *(.hash)           }

because this single .x file is used for loads of different AVRs the authors have set the size limit for EEPROM to be a very generous 64K so it's larger than any of the devices in the group:

 Directory of C:\SysGCC\avr\avr\lib\avr51

18/08/2016  10:10            11,004 crtat90can128.o
18/08/2016  10:10            10,568 crtat90usb1286.o
18/08/2016  10:10            11,968 crtat90usb1287.o
18/08/2016  10:10             8,844 crtatmega128.o
18/08/2016  10:10            12,984 crtatmega1280.o
18/08/2016  10:10            11,460 crtatmega1281.o
18/08/2016  10:10             8,920 crtatmega1284.o
18/08/2016  10:10             8,920 crtatmega1284p.o
18/08/2016  10:10             4,668 crtatmega1284rfr2.o
18/08/2016  10:10             8,848 crtatmega128a.o
18/08/2016  10:10            18,128 crtatmega128rfa1.o
18/08/2016  10:10            20,240 crtatmega128rfr2.o

But if you are using a specific device from this group and you know the max EEPROM size what you can do is copy avr51.x from the lib\ldscripts directory to your own project directory.

 

Edit it and change the "LENGTH = 64K" on the eeprom line to be "LENGTH = 4K". Then when you build your AVR code use the usual commands for linking but to that add -Wl,-T,local_avr51.x (or whatever your local copy is called). That will use that in preference to the default one and now the LENGTH = 4K thing will come into play. Exceed it and you will hear about it...

C:\SysGCC\avr\bin>type avr.c
#include <avr/io.h>
#include <avr/eeprom.h>

char big_array[5000] EEMEM;

int main(void) {
}

C:\SysGCC\avr\bin>head my_avr51.x -n 18
/* Default linker script, for normal executables */
/* Copyright (C) 2014 Free Software Foundation, Inc.
   Copying and distribution of this script, with or without modification,
   are permitted in any medium without royalty provided the copyright
   notice and this notice are preserved.  */
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:51)
MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = 128K
  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 0xff00
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 4K
  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
  signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
}
SECTIONS
{

C:\SysGCC\avr\bin>avr-gcc -mmcu=atmega1284p -Wl,-T,my_avr51.x -Os avr.c -o avr.elf
c:/sysgcc/avr/bin/../lib/gcc/avr/5.3.0/../../../../avr/bin/ld.exe: avr.elf section `.eeprom' will not fit in region `eeprom'
c:/sysgcc/avr/bin/../lib/gcc/avr/5.3.0/../../../../avr/bin/ld.exe: region `eeprom' overflowed by 904 bytes
collect2.exe: error: ld returned 1 exit status

 

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

Now, I'm not a GCC guru.  But you do realize that the toolchain build you are using is ... ancient.

 

For fun, I pulled up a test app in Studio7.  The target is a Mega168 that has 512 bytes of EEPROM.  I declared a 768 byte array in EEPROM, and rebuilt.

 

Indeed, the last line of the build report:

 

...

Invoking: AVR/GNU C Compiler : 5.4.0

...

Done building project "GccApplication2.cproj".

Build succeeded.
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

However, looking a bit above:

 

Using "RunOutputFileVerifyTask" task from assembly "C:\Program Files (x86)\Atmel\Studio\7.0\Extensions\Application\AvrGCC.dll".
    Task "RunOutputFileVerifyTask"
                Program Memory Usage     :    4714 bytes   28.8 % Full
                Data Memory Usage         :    310 bytes   30.3 % Full
                EEPROM Memory Usage     :    768 bytes   150.0 % Full    (Memory Overflow)
    Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "GccApplication2.cproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Avr.common.targets" from project "C:\Users\ltheusch\Documents\Atmel Studio\7.0\GccApplication2\GccApplication2\GccApplication2.cproj" (entry point):
Done building target "Build" in project "GccApplication2.cproj".
Done building project "GccApplication2.cproj".

Build succeeded.
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

 

So the situation >>is<< reported, but not as a "failure".

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

Lee that report is some Atmel added stuff. By default the linker scripts define:

C:\SysGCC\avr\avr\lib\ldscripts>grep -H "LENGTH =" *.x | grep eeprom
avr1.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr2.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr25.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr3.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr31.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr35.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr4.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr5.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr51.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avr6.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega1.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega2.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega3.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega4.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega5.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega6.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
avrxmega7.x:  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K

(never looked before - so they are all the maximum 64K in fact!!). So using a "stand alone" compiler nothing will warn you.

 

Having said that Eric Weddington made a special patch for avr-size (adding the -C option) back in the time of WinAVR and it would do what the Atmel thing now tries to do and "know" the upper limit for all the AVRs but it never caught on as adding new devices became a support nightmare.

 

I'm guessing the Atmel thing uses their own ATDF XML data files which each know the size of the AVR memory regions.

 

As I just demonstrated as long as you don't mind tying a .x file to a certain device then it's quite easy to arrange for a generic linker error.

 

PS forgot to say that I totally agree that no one should really be developing new code with a 2010 compiler at this stage - avr-gcc has move way beyond WinAVR now.

Last Edited: Mon. Oct 23, 2017 - 03:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For new versions of avr-gcc, you can use 

avr-objdump -Pmem-usage <elf file>

instead of avr-size to get the sizes. (the elf file must contain a .note.gnu.avr.dev section for this to give any usable info). 

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

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

meolsen wrote:
(the elf file must contain a .note.gnu.avr.dev section for this to give any usable info)
And how does that get into the file? Presumably the generator "knows stuff" such as the fact that a 1284 EEPROM is 4K etc? Is that coming from thing built into the compiler, or built into the linker or somehow read from some other data source?

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

From the crt (https://lists.nongnu.org/archive...) Which already know about the sizes (i.e it removes the need to maintain yet another table of sizes)

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

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

My bad, I said "WinAVR" but it is Studio 7 with "AVR/GNU C Compiler : 5.4.0" ...

 

Trying to digest the other comments now ...

 

Chuck

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

ChuckH wrote:
Trying to digest the other comments now ...

So, if you know you are fairly close in this app, then just scroll up a bit after each build and check.  Old school, indeed.  But I resemble that...

My school is the squarish fieldstone building between the church on the left, and the nuns' house (the teachers) on the right.

 

Circa 1900, perhaps, as by the time I went there in the '50s there were good sized trees in the yard and other changes.  IIRC the cornerstone of the church was dated 1880.

 

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.

Last Edited: Mon. Oct 23, 2017 - 08:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So the situation >>is<< reported, but not as a "failure".

 

My solution file contains several (6 at the moment and growing) different EEMEM builds (projects) for different configurations.  After the configuration was reported as bad by the target system I went back and checked the build log/Output and did see that EEMEM had overflowed but it's rather tedious to have to go back through the logs on every build to see if one of the configurations overflowed (imagine if we had to do that for the average source compile error).  That's why I was looking for a way to force the solution build to fail.

 

Guess I'll have to check the builds for the moment.  This whole issue is going away as I am adding configuration capabilities to the PC control program that manages the network of controllers which are the targets of the config info being generated at the moment from a bunch of macro invocations.

 

Chuck

 

 

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

Sorry but what is wrong with the solution (the "right" solution) that I demonstrated in #2 above? It works just as well in AS7 as any other environment. The only "clever bit" is knowing about the -T option to the linker.