Determine PC's width in compile time

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

Hi, All!

 

How to determine width of program counter in compile time?

 

FLASHEND is not suited: there is atMega640 with 3 byte PC's width, IMHO.

 

Ilya

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

501-q wrote:

Hi, All!

 

How to determine width of program counter in compile time?

 

FLASHEND is not suited: there is atMega640 with 3 byte PC's width, IMHO.

 

Ilya

Not exactly:

 

The ATmega640/1280/1281/2560/2561 Program Counter (PC) is 15/16/17 bits wide, thus addressing the 32K/64K/128K program memory locations.
 

...but that doesn't answer your question about "compile time".

 

Are you looking across all AVR models, or just that family?  If just the family, you could enhance the chip include (or have your own fragment) based on the AVR model being built for.

 

I think I see your issue in this area.  In a Mega640 app, is the return address three bytes?  I think that is true, and thus your problem situation?

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: Thu. Jun 18, 2015 - 01:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is easier at run-time, right?  ;)  Note the value of SP then issue a CALL and see the change?

 

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

theusch wrote:

 

The ATmega640/1280/1281/2560/2561 Program Counter (PC) is 15/16/17 bits wide, thus addressing the 32K/64K/128K program memory locations.
 

Ah, yes! In 2549D-AVR-12/05 this is present. I miss it.

Quote:

...but that doesn't answer your question about "compile time".

 

Are you looking across all AVR models, or just that family?

I am looking across all AVR models: tiny, mega and xmega.

Quote:
  If just the family, you could enhance the chip include (or have your own fragment) based on the AVR model being built for.

 

I think I see your issue in this area.  In a Mega640 app, is the return address three bytes?  I think that is true, and thus your problem situation?

Yes. Correct question is "How to determine size of return address at compile time".

 

Ilya

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

Quote:

It is easier at run-time, right?  ;)

Yes, I know. For xMega it is easy too (8077H–AVR–12/09):

Quote:

For devices with 128K bytes or less of program memory the return address is two bytes, hence the
Stack Pointer is decremented/incremented by two. For devices with more than 128K bytes of
program memory, the return address is three bytes, hence the SP is decremented/incremented
by three.

 

Ilya

Last Edited: Thu. Jun 18, 2015 - 01:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you should be able to use  FLASHEND 

but remember that the instructions are 16 bit so the 3 byte will only count for parts bigger than 128K

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

sparrow2 wrote:

you should be able to use  FLASHEND 

but remember that the instructions are 16 bit so the 3 byte will only count for parts bigger than 128K

sparrow2 -- As was discussed above, Mega640 (and '1280/'1281) do not have flash bigger than 128K but have a 3-byte program counter.  (Is that the only family?  Dunno.)

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

By "compile time" can we assume a C compiler? If so then which one?

 

For example:

~$ avr-gcc -mmcu=atmega2560 -Os -save-temps -g avr.c -E -dM | grep BYTE_PC
#define __AVR_3_BYTE_PC__ 1
~$ avr-gcc -mmcu=atmega16 -Os -save-temps -g avr.c -E -dM | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1
~$ avr-gcc -mmcu=attiny4 -Os -save-temps -g avr.c -E -dM | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1
~$ avr-gcc -mmcu=atmega1280 -Os -save-temps -g avr.c -E -dM | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1

So, for example:

int main(void) {
    asm("ldi r16,0");
    asm ("push r16");
    asm ("push r16");
#ifdef __AVR_3_BYTE_PC__
    asm ("push r16");
#endif
    asm("ret");
}

 

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

thanks, clawson!

 

clawson wrote:

By "compile time" can we assume a C compiler? If so then which one?

In C this is almost useless. But I compile assembler code with C preprocessor.

 

And what about IAR etc? ;-)

 

Ilya

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

In C this is almost useless. But I compile assembler code with C preprocessor.

As you can see I used "-E -dM". That dumps the pre-processor macros. They are just as valid in asm .S files as they are in .c/.cpp files. Only if you used .s rather than .S (so no prepro) would you not have access to such symbols.

And what about IAR etc? ;-)

The reason you pay $3000 for a copy of IAR is so that when you have questions like this IAR can dispatch the company Gulfstream to your location filled with Ploynesian virgins who will then feed you grapes and tender to your every whim as thy answer questions such as this.

 

(if I had to bet on it I'd say IAR does not have an equivalent mechanism - in my experience it isn't actually that great a compiler).

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

But why should a 640 and 1280 have a 3 byte PC! (saying it don't !!!)

 

The datasheet say :

 

Note: EICALL and EIJMP do not exist in ATmega640/1280/1281.

ELPM does not exist in ATmega640.

 

 

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

http://www.atmel.com/webdoc/AVRL...

 

Indeed, it isn't in chip-include or other places mere mortals can access...

Machine-specific options for the AVR

The following machine-specific options are recognized by the C compiler frontend. In addition to the preprocessor macros indicated in the tables below, [which include __AVR_n_BYTE_PC__]

To the OP:  As syntax varies among toolchains, I think you need to limit yourself to solving the problem one toolchain at a time. Nothing jumps out at me in CodeVision.  There is indirect in setjmp.h in GCC and CV (below):

 
#if defined (_CHIP_ATXMEGA128A1_) || defined (_CHIP_ATXMEGA128A1U_) || \
    defined (_CHIP_ATXMEGA128A3_) || defined (_CHIP_ATXMEGA128A3U_) || \
    defined (_CHIP_ATXMEGA128A4_) || defined (_CHIP_ATXMEGA128A4U_) || \
    defined (_CHIP_ATXMEGA128B1_) || defined (_CHIP_ATXMEGA128B3_) || \
    defined (_CHIP_ATXMEGA128C3_) || \
    defined (_CHIP_ATXMEGA128D3_) || defined (_CHIP_ATXMEGA128D4_) || \
    defined (_CHIP_ATXMEGA192A1_) || defined (_CHIP_ATXMEGA192A3_) || \
    defined (_CHIP_ATXMEGA192A3U_) || defined (_CHIP_ATXMEGA192C3_) || \
    defined (_CHIP_ATXMEGA192D3_) || defined (_CHIP_ATXMEGA256A1_) || \
    defined (_CHIP_ATXMEGA256A3_) || defined (_CHIP_ATXMEGA256A3U_) || \
    defined (_CHIP_ATXMEGA256A3B_) || defined (_CHIP_ATXMEGA256A3BU_) || \
    defined (_CHIP_ATXMEGA256C3_) || defined (_CHIP_ATXMEGA256D3_) || \
    defined (_CHIP_ATXMEGA384C3_) || defined (_CHIP_ATXMEGA384D3_) || \
    defined (_CHIP_ATMEGA2560_) || defined (_CHIP_ATMEGA2560V_) || \
    defined (_CHIP_ATMEGA2561_) || defined (_CHIP_ATMEGA2561V_) || \
    defined (_CHIP_ATMEGA256RFR2_)
typedef char jmp_buf[11];
#else
typedef char jmp_buf[9];
#endif

and in GCC

#if defined(__AVR_TINY__)
# define _JBLEN 11
#elif	defined(__AVR_3_BYTE_PC__) && __AVR_3_BYTE_PC__
# define _JBLEN  24
#else
# define _JBLEN  23
#endif
typedef struct _jmp_buf { unsigned char _jb[_JBLEN]; } jmp_buf[1];

 

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: Thu. Jun 18, 2015 - 02:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just had a look at the IAR PDFs on another machine. The fact is that I'll take back some of what I said. They have symbols such as __HAS_ELPM__, __HAS_EIND__, __HAS_RAMPX__, etc. but there isn't one to say (as GCC does) __HAS_EIJMP_EICALL. What they do have are __CORE__ and __CPU__. I imagine the CPU  one is like the individual, per CPU, symbols that GCC uses to determine what a generic io.h should resolve to. The __CORE__ is possibly more interesting. Now I don't know what values IAR deliver in that symbol but in GCC you have:

$ avr-gcc -mmcu=atmega1280 -Os -save-temps -g avr.c -E -dM | grep AVR_ARCH
#define __AVR_ARCH__ 51
$ avr-gcc -mmcu=atmega2560 -Os -save-temps -g avr.c -E -dM | grep AVR_ARCH
#define __AVR_ARCH__ 6

I'm sort of assuming that IAR's __CORE__ is going to be defined something like this but it may not actually be 51 and 6. However I'll bet __CORE__ for 1280 is different to 2560.

 

(off to try a quick experiment...)

 

EDIT: and back. So I built:

int main(void) {
    PORTB = __CORE__;
}

for 1280 and 2561 (couldn't find 2560 in the list!). It used 3 for the 1280 and 5 for the 2561. So I think __CORE__ is the way to do it in IAR.

 

(now, where do I apply for my share of the $3000?)

Last Edited: Thu. Jun 18, 2015 - 02:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, you get some of the Polynesian virgins.

The largest known prime number: 282589933-1

Without adult supervision.

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

My PC was about 8 inches wide when the command prompt was showing, but it didnt change much when I was compiling?

 

Imagecraft compiler user

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

Hi!

clawson wrote:

 

~$ avr-gcc -mmcu=atmega2560 -Os -save-temps -g avr.c -E -dM | grep BYTE_PC
#define __AVR_3_BYTE_PC__ 1
~$ avr-gcc -mmcu=atmega1280 -Os -save-temps -g avr.c -E -dM | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1

 

 

Is this bug in avr-gcc or error in documentation?

D:\>avr-gcc --version
avr-gcc (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


D:\>echo | avr-gcc -mmcu=atmega64 -dM -E - | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1

D:\>echo | avr-gcc -mmcu=atmega640 -dM -E - | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1

D:\>echo | avr-gcc -mmcu=atmega1280 -dM -E - | grep BYTE_PC
#define __AVR_2_BYTE_PC__ 1

I have no hardware with those MCU. In simulator I see that atmega640 "call" push 2 bytes onto the stack.

 

In 2549D-AVR-12/05 page 13:

Quote:
The Stack Pointer is decremented by one when data is pushed onto the Stack with PUSH instruction, and it is decremented by three when the return address is pushed onto the Stack with subroutine call or interrupt.

I think that documentation with error, and it is "Preliminary" only.

 

Ilya

Last Edited: Fri. Jun 19, 2015 - 04:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is this bug in avr-gcc or error in documentation?

Not sure what you are asking. Any AVR up to 128KB will only require a 2 byte PC because the 128KB is 64K Words and the minium opcode width is 1 word. So a 16 bit 0..64K PC is fine for any chip up t0 128KB. It is only 256KB (and 384KB Xmega) that require a 3 byte PC.

 

The same goes for the pushing of addresses in CALLs. Only 3 bytes will be required for the 3 byte PC in 256KB/384KB AVRs.

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

clawson wrote:

Is this bug in avr-gcc or error in documentation?

Not sure what you are asking. Any AVR up to 128KB will only require a 2 byte PC because the 128KB is 64K Words and the minium opcode width is 1 word. So a 16 bit 0..64K PC is fine for any chip up t0 128KB. It is only 256KB (and 384KB Xmega) that require a 3 byte PC.

 

The same goes for the pushing of addresses in CALLs. Only 3 bytes will be required for the 3 byte PC in 256KB/384KB AVRs.

Ok, I know all of this. But I doubt in this: according to 2549D-AVR-12/05 (Preliminary datasheet for ATmega640/V, ATmega1280/V etc) page 13, all those MCUs have 3 byte PC.  I think, that this is error in documentation. But... who know?

 

Edit: I check actual documentation. ATmega640/ATmega1280 have 2 byte PC.

 

Ilya

Last Edited: Fri. Jun 19, 2015 - 11:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have 2549P-AVR-10/2012.

 

I see no such mention of 3 byte PC on page 13. In fact when I search "Counter" and read references to the program counter the first mention of 3 bytes is in 7.8.1 on page 20. That would appear to be an error because clearly it should be "2/3 bytes"

 

Section 7.6 about the Stack Pointer says this:

 The Stack Pointer is decremented by one when data is pushed onto the Stack with the
PUSH instruction, and it is decremented by two for ATmega640/1280/1281 and three for
ATmega2560/2561 when the return address is pushed onto the Stack with subroutine call or
interrupt. The Stack Pointer is incremented by one when data is popped from the Stack with the
POP instruction, and it is incremented by two for ATmega640/1280/1281 and three for
ATmega2560/2561 when data is popped from the Stack with return from subroutine RET or
return from interrupt RETI.

 

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

The only AVR's that push/pop to many bytes are tiny4 & 5 , they only need 1 byte, but use the "normal" 2. :)

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

...

I have 2549P-AVR-10/2012.

...

...as do I.

 

Now, when I commented above I searched for "program counter".  I find the first pertinent hit in 7.8.1 also.  In addition to the mention of the three bytes, it also says five cycles.  If it is 2/3 bytes then it should be 4/5 cycles, right?

 

In 8.2 it says

 

If the Stack is placed in external SRAM, interrupts, subroutine calls and returns take three clock cycles extra because the three-byte program counter is pushed and popped, ...
 

So you can see where OP and I were coming from.  My search for "program counter" did not find your 7.6 mention.  So the datasheet has one place that says 2/3, and more than one place that says three?

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

But using external ram is <1% of avr apps. Just remember reading and writing to external ram takes an extra cycle.

 

Imagecraft compiler user

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

But remember we talk about Atmel data sheets, they are known for a lot of cut and paste errors, but mostly the chips do work a logic way smiley