Xmega Application Code crossing 0xFFFF

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

I have a series of projects using the Xmega 128A1 which has 128kB of application Flash memory. I'm programming with AVRStudio 4.19 and WinAVR GCC.

Only recently have I had problems with code memory, and after a lot of searching I realised I'd crossed the 50% code space utilization, and some of my code was rolling over from 0xFFFF to 0x1xxxx. When I cleaned out a lot of debug code and got the code size well below 0xFFFF, everything was fine. But the time will come when I need to add sufficient features that I cross that boundary again.

I've checked and I have the correct MCU set in project configurations, (since I've has avr\xxx.h issues in the past) checked that io.h calls up iox128a1.h and that iox128a1.h specifies the correct macro values for application code space.

I was under some confusion that the Xmega PC is a modulo-2 counter, and addresses 16-bit words in the *byte* address range 0x0000, 0x0002, 0x0004,..., 0x1FFFE. But now I'm beginning to doubt my understanding of that.

Anyone seen this problem before, or able to offer any help?

Electronic components work on the principle of smoke; I know this because when I let the smoke out, they stop working. Also, sanity is over-rated.

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

Quote:
I was under some confusion that the Xmega PC is a modulo-2 counter, and addresses 16-bit words
the data sheets says
Quote:
Direct addressing of up to 16M bytes of program and data memory.
that would mean a 24 program counter.

Your problem may be WinAVR related, have you tried with the Atmel toolchain which would be a lot newer?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

This is a GCC issue and should be moved there for answers.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

js wrote:
Quote:
I was under some confusion that the Xmega PC is a modulo-2 counter, and addresses 16-bit words
the data sheets says
Quote:
Direct addressing of up to 16M bytes of program and data memory.
that would mean a 24 program counter.

Indeed it would, you're quite right.

js wrote:
Your problem may be WinAVR related, have you tried with the Atmel toolchain which would be a lot newer?

Sorry, I am mistaken. I'm using Atmel AVR Toolchain 3.3.0.710, not WinAVR. There is a newer version, 3.4.2 so I'll try that before anything else. Thanks for the pointer to check what I had... ;-)

Electronic components work on the principle of smoke; I know this because when I let the smoke out, they stop working. Also, sanity is over-rated.

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

indianajones11 wrote:
This is a GCC issue and should be moved there for answers.

Presupposing that the cause is the compiler, and not something that I have not correctly initialised in the MCU to enable access to the entire address space, I'd agree. But I didn't/don't know that. However John has prompted me to look for a compiler update, so it could well be that. If there's nothing to configure in the chip, I'll gladly look to the GCC forum for answers. Cheers.

Electronic components work on the principle of smoke; I know this because when I let the smoke out, they stop working. Also, sanity is over-rated.

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

There are some caveats, did you read and follow the GCC documentation on EIND and devices with >= 128 KiB program memory?

If yes, everything works fine and your problem is somewhere else.

If no, your program might still work but it is not robust.

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB wrote:
did you read and follow the GCC documentation on EIND and devices with >= 128 KiB program memory?

Oh, your comment looked so promising. But I found GCC reference on AVR Options, section 3.17.4.1 which is titled EIND and Devices with more than 128 Ki Bytes of Flash. It states:
Quote:
Pointers in the implementation are 16 bits wide. The address of a function or label is represented as word address so that indirect jumps and calls can target any code address in the range of 64 Ki words.

The problem I have is when the code exceeds byte address 0xFFFF, which is only half way through the flash and is easily addressed by a code word pointer.

I'm beginning to think js and indianajones11 are on the right lines...

Electronic components work on the principle of smoke; I know this because when I let the smoke out, they stop working. Also, sanity is over-rated.

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

IF you think it is an avr-gcc issue, you can open a bug report. Please keep the bug eporting instructins in mind:

http://gcc.gnu.org/bugs/#report

avrfreaks does not support Opera. Profile inactive.

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

Thanks SprinterSB, if I can pinpoint a compiler failure I'll do just that. :-)

Electronic components work on the principle of smoke; I know this because when I let the smoke out, they stop working. Also, sanity is over-rated.

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

There was a bug that someone posted here about the compiler not using the EIND about 2-3 yrs ago. I assume it's fixed now... OP what version of AVR-GCC do you have ? I assume your issue is about code execution, not accessing constants stored in program space...that's what your posts are stating anyway.

Edit: I just read a post where SprinterSB stated EIND doesn't need to be touched at all by GCC. Ok...well the manual's not the easiest thing to understand for how all this is to be setup ( but it's my first time taking a look at it too... ). :?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

It's still the case that GCC does not change EIND. Reason is that it is not possible to chenge EIND without raising glitches. If you'd change EIND prior to a EIJMP / EICALL there is no way to set it back...

Anyone who wants to improve GCC please come up with better documentation and contribute it. I am not a native speaker, sorry.

avrfreaks does not support Opera. Profile inactive.

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

What is the compiler version you are using?

The one displayed with

    avr-gcc --version

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB, we both missed the OP's June 6 post:

Quote:
Sorry, I am mistaken. I'm using Atmel AVR Toolchain 3.3.0.710, not WinAVR. There is a newer version, 3.4.2 so I'll try that before anything else. Thanks for the pointer to check what I had...

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

This still don't tell what the compiler version is...

avrfreaks does not support Opera. Profile inactive.

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

The release notes (at Studio Archive) say 3.3.0 contains

Quote:
1. AVR 8-bits GNU Binutils 2.20.1
• Binary utilities for AVR 8-bits target (including assembler, linker, etc.).
2. AVR 8-bits GNU Compiler Collection (avr-gcc) 4.5.1
• C language and C++ language compiler for AVR 8-bits target.
3. AVRLibC 1.7.1
• C Standard Library for AVR 8-bits
But maybe OP changed to 3.4.2?

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

This means that the xmega stupport might come with bugs like PR52461 or PR52508, both fixed in 4.7.1. These bugfixes were not backported because 4.7.0 is the oldest official release that supports xmega.

To work around PR52461 you can try the following init-function that resets RAMPZ before main starts:

#include 

static void __attribute__((__naked__,__used__,__section__(".init8")))
set_rampz (void)
{
    __asm__ __volatile__("sts %0, __zero_reg__" : "=m" (RAMPZ));
}

avrfreaks does not support Opera. Profile inactive.

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

Hi,

I've just installed the Atmel studio 7(Version: 7.0.943), and I'm facing the same issue.
Is there a known solution?

I've added some info if other information is needed please let me know.

Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\lib\gcc\avr\4.9.2\include

Lines from the output tab:
Invoking: AVR/GNU Linker : 4.9.2
Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe

           text           data        bss        dec            hex    
          65068        472       6387      71927      118f7    
    Done executing task "RunCompilerTask".
    Task "RunOutputFileVerifyTask"
                Program Memory Usage     :    65540 bytes   47.1 % Full
                Data Memory Usage         :    6859 bytes   12.0 % Full

Lines from the map file:
                0x0000fe2c                __data_load_start = LOADADDR (.data)
                0x00010004                __data_load_end = (__data_load_start + SIZEOF (.data))

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

But this thread dates from 2013 and posts above suggest it is fixed by 4.7.1. As you are using 4.9.2 are you saying you still have an issue?

 

So are you saying it's missing the 4 bytes that spill past 65536 in the _do_copy_data() loop then?

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

Yes it still exists and I don't know how to avoid it.

Yes its those extra 4 bytes that causes it.

I still have some more coding to do so I must have an access to the extra space beyond 0xffff.

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

Well the _do_copy_data() loop should be doing ELPM but this uses a 24 bit address made up of Z and RAMPZ. For those last 4 bytes RAMPZ would need to be 1 while it is 0 for the start of .data

 

An old copy of that code is here:

 

http://svn.savannah.nongnu.org/v...

 

specifically:

	.section .init4,"ax",@progbits
	.global __do_copy_data
__do_copy_data:
	ldi	r17, hi8(__data_end)
	ldi	r26, lo8(__data_start)
	ldi	r27, hi8(__data_start)
	ldi	r30, lo8(__data_load_start)
	ldi	r31, hi8(__data_load_start)

	/* On the enhanced core, "elpm" with post-increment updates RAMPZ
	   automatically.  Otherwise we have to handle it ourselves.  */

#ifdef __AVR_ENHANCED__
	ldi	r16, hh8(__data_load_start)
#else
	ldi	r16, hh8(__data_load_start - 0x10000)
.L__do_copy_data_carry:
	inc	r16
#endif
	out	AVR_RAMPZ_ADDR, r16
	rjmp	.L__do_copy_data_start
.L__do_copy_data_loop:
#ifdef __AVR_ENHANCED__
	elpm	r0, Z+
#else
	elpm
#endif
	st	X+, r0
#ifndef __AVR_ENHANCED__
	adiw	r30, 1
	brcs	.L__do_copy_data_carry
#endif
.L__do_copy_data_start:
	cpi	r26, lo8(__data_end)
	cpc	r27, r17
	brne	.L__do_copy_data_loop
#ifdef __AVR_HAVE_RAMPD__
	out	AVR_RAMPZ_ADDR, __zero_reg__
#endif /* __AVR_HAVE_RAMPD__*/

As you can see it only sets RAMPZ before the loop but does not consider the occasion where it might change 0 to 1 during the loop.

 

Since gcc 4.3 this loop has been absorbed inside the compiler but I imagine the code is the same.

 

Looking at it the answer would seem to be to pad .text so that the start of .data falls over the 0x10000 boundary. Just add something like:

#include <avr/pgmspace.h>

char padding[512] PROGMEM = { 0 };

That will be put in .progmem.data which is between .vectors and .init1 (right near the start of the 1st 64K) and should be enough to move everything up so .data starts beyond 0x10000.

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

As you can see it only sets RAMPZ before the loop but does not consider the occasion where it might change 0 to 1 during the loop.

According to the AVR8 Instruction Set document (Rev. 0856J–AVR–07/2014) the Z+ (enhanced) mode does increment RAMPZ:

 

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

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

Thanks for helping.

I thought so too and I did the same thing just by adding some more code until .text was big enough beyond 0xffff but it didn't solve the problem.

Any other ideas?

Parts of the map file:

.text           0x00000000    0x102c2
 *(.vectors)
 .vectors       0x00000000      0x1f4 C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/XMEGAA_DFP/1.0.39/gcc/dev/atxmega128a1/avrxmega7/crtatxmega128a1.o
                0x00000000                __vector_default
                0x00000000                __vectors
 *(.vectors)

 

               0x000102c2                __data_load_start = LOADADDR (.data)

               0x0001049a                __data_load_end = (__data_load_start + SIZEOF (.data))

Part of the output tab:

           text            data        bss        dec        hex   
          66242        472       6387      73101      11d8d    

                Program Memory Usage     :    66714 bytes   47.9 % Full
                Data Memory Usage         :    6859 bytes   12.0 % Full