Targetting multiple processors

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

Not sure if this is possible:

I have a large application - almost fills 32k of ATMega324 but has a number of versions: two different processors, three different displays and associated drivers, but eighty percent of the file is common.

While obviously one can conditionally include the necessary header files and #ifdef the different registers and code changes, I'm not sure if I can define a processor in the source to allow AS5 to select the appropriate compiler options, of if they're hard-set in the configuration options.

Ideally I would like to uncomment a single define at the top of the source and have the thing generate the appropriate code, but I don't know if that can apply to different processors. I don't want to end up with a dozen different slabs of code; I already have that and synchronising them is messy.

Any thoughts?

Ta,

Neil

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

Neil,

If you are using avr-gcc then the CPU you are building for is known at compile time because of the -mmcu= passed on the invocation of avr-gcc. If -mmcu=atmega324 is used then the compiler automatically defines one of the following macros:

#elif defined (__AVR_ATmega324P__) || defined (__AVR_ATmega324A__)
#  include 
#elif defined (__AVR_ATmega324PA__)
#  include 

I stole that code from io.h where you can see the full list of generated defines. Your own code can use these just as WinAVR does. I have examples such as:

int uart_putc(char c, FILE *unused) {
#ifdef __AVR_ATmega168__
	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = c;
#else
	while (!(UCSRA & (1<<UDRE)));
	UDR = c;
#endif
	return 0;
}

#ifndef __AVR_ATmega168__
// The following two ISRs are doing "poor man's PWM" 
//  but this allows it to be on a pin of my choice
ISR(TIMER0_COMP_vect) {
	PORTC &= ~(1<<PC0);
}
ISR(TIMER0_OVF_vect) {
	PORTC |= (1<<PC0);
}
#endif

That's actually switched between __AVR_ATmega16__ and _AVR_ATmega168__. The switch happens simply by telling Studio to build for the other CPU.

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

Ah, so

#define __AVR_ATmega324P__

overrides the auto make from the ISP. Excellent - I will play.

Thanks!

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

Quote:

overrides the auto make from the ISP.

I guess you meant IDE not ISP. And yes this is an internal macro definition that's provided by the compiler itself (hence the two leading under-scores in its name). The compiler actually defines quite a few of these:

E:\avr[i386_vc]>avr-gcc -c -mmcu=atmega16 -E -dM test.c | grep "__" | sort
#define FILE struct __file
#define FUSEMEM __attribute__((section (".fuse")))
#define FUSES __fuse_t __fuse FUSEMEM
#define INT32_C(value) __CONCAT(value, L)
#define INT64_C(value) __CONCAT(value, LL)
#define INTMAX_C(value) __CONCAT(value, LL)
#define LOCKBITS unsigned char __lock LOCKMEM
#define LOCKMEM __attribute__((section (".lock")))
#define SIZE_MAX (__CONCAT(INT16_MAX, U))
#define UINT16_C(value) __CONCAT(value, U)
#define UINT16_MAX (__CONCAT(INT16_MAX, U) * 2U + 1U)
#define UINT32_C(value) __CONCAT(value, UL)
#define UINT32_MAX (__CONCAT(INT32_MAX, U) * 2UL + 1UL)
#define UINT64_C(value) __CONCAT(value, ULL)
#define UINT64_MAX (__CONCAT(INT64_MAX, U) * 2ULL + 1ULL)
#define UINT8_C(value) ((uint8_t) __CONCAT(value, U))
#define UINT8_MAX (__CONCAT(INT8_MAX, U) * 2U + 1U)
#define UINTMAX_C(value) __CONCAT(value, ULL)
#define _FDEV_SETUP_READ __SRD
#define _FDEV_SETUP_RW (__SRD|__SWR)
#define _FDEV_SETUP_WRITE __SWR
#define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET)
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
#define _SFR_IO_ADDR(sfr) (_SFR_MEM_ADDR(sfr) - __SFR_OFFSET)
#define _SFR_IO_REG_P(sfr) (_SFR_MEM_ADDR(sfr) < 0x40 + __SFR_OFFSET)
#define _VECTOR(N) __vector_ ## N
#define __AVR 1
#define __AVR_2_BYTE_PC__ 1
#define __AVR_ARCH__ 5
#define __AVR_ATmega16__ 1
#define __AVR_ENHANCED__ 1
#define __AVR_HAVE_JMP_CALL__ 1
#define __AVR_HAVE_LPMX__ 1
#define __AVR_HAVE_MOVW__ 1
#define __AVR_HAVE_MUL__ 1
#define __AVR_LIBC_DATE_ 20090702UL
#define __AVR_LIBC_DATE_STRING__ "20090702"
#define __AVR_LIBC_MAJOR__ 1
#define __AVR_LIBC_MINOR__ 6
#define __AVR_LIBC_REVISION__ 7
#define __AVR_LIBC_VERSION_STRING__ "1.6.7"
#define __AVR_LIBC_VERSION__ 10607UL
#define __AVR_MEGA__ 1
#define __AVR__ 1
#define __BOOT_LOCK_BITS_0_EXIST
#define __BOOT_LOCK_BITS_1_EXIST
#define __CHAR_BIT__ 8
#define __CONCAT(left,right) __CONCATenate(left, right)
#define __CONCATenate(left,right) left ## right
#define __DBL_DENORM_MIN__ 1.40129846e-45
#define __DBL_DIG__ 6
#define __DBL_EPSILON__ 1.19209290e-7
#define __DBL_HAS_DENORM__ 1
#define __DBL_HAS_INFINITY__ 1
#define __DBL_HAS_QUIET_NAN__ 1
#define __DBL_MANT_DIG__ 24
#define __DBL_MAX_10_EXP__ 38
#define __DBL_MAX_EXP__ 128
#define __DBL_MAX__ 3.40282347e+38
#define __DBL_MIN_10_EXP__ (-37)
#define __DBL_MIN_EXP__ (-125)
#define __DBL_MIN__ 1.17549435e-38
#define __DEC128_DEN__ 0.000000000000000000000000000000001E-6143DL
#define __DEC128_EPSILON__ 1E-33DL
#define __DEC128_MANT_DIG__ 34
#define __DEC128_MAX_EXP__ 6144
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
#define __DEC128_MIN_EXP__ (-6143)
#define __DEC128_MIN__ 1E-6143DL
#define __DEC32_DEN__ 0.000001E-95DF
#define __DEC32_EPSILON__ 1E-6DF
#define __DEC32_MANT_DIG__ 7
#define __DEC32_MAX_EXP__ 96
#define __DEC32_MAX__ 9.999999E96DF
#define __DEC32_MIN_EXP__ (-95)
#define __DEC32_MIN__ 1E-95DF
#define __DEC64_DEN__ 0.000000000000001E-383DD
#define __DEC64_EPSILON__ 1E-15DD
#define __DEC64_MANT_DIG__ 16
#define __DEC64_MAX_EXP__ 384
#define __DEC64_MAX__ 9.999999999999999E384DD
#define __DEC64_MIN_EXP__ (-383)
#define __DEC64_MIN__ 1E-383DD
#define __DECIMAL_DIG__ 9
#define __DEC_EVAL_METHOD__ 2
#define __FINITE_MATH_ONLY__ 0
#define __FLT_DENORM_MIN__ 1.40129846e-45F
#define __FLT_DIG__ 6
#define __FLT_EPSILON__ 1.19209290e-7F
#define __FLT_EVAL_METHOD__ 0
#define __FLT_HAS_DENORM__ 1
#define __FLT_HAS_INFINITY__ 1
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MANT_DIG__ 24
#define __FLT_MAX_10_EXP__ 38
#define __FLT_MAX_EXP__ 128
#define __FLT_MAX__ 3.40282347e+38F
#define __FLT_MIN_10_EXP__ (-37)
#define __FLT_MIN_EXP__ (-125)
#define __FLT_MIN__ 1.17549435e-38F
#define __FLT_RADIX__ 2
#define __GNUC_GNU_INLINE__ 1
#define __GNUC_MINOR__ 3
#define __GNUC_PATCHLEVEL__ 3
#define __GNUC_VA_LIST
#define __GNUC__ 4
#define __GXX_ABI_VERSION 1002
#define __INTMAX_MAX__ 9223372036854775807LL
#define __INTMAX_TYPE__ long long int
#define __INTTYPES_H_
#define __INT_MAX__ 32767
#define __LDBL_DENORM_MIN__ 1.40129846e-45L
#define __LDBL_DIG__ 6
#define __LDBL_EPSILON__ 1.19209290e-7L
#define __LDBL_HAS_DENORM__ 1
#define __LDBL_HAS_INFINITY__ 1
#define __LDBL_HAS_QUIET_NAN__ 1
#define __LDBL_MANT_DIG__ 24
#define __LDBL_MAX_10_EXP__ 38
#define __LDBL_MAX_EXP__ 128
#define __LDBL_MAX__ 3.40282347e+38L
#define __LDBL_MIN_10_EXP__ (-37)
#define __LDBL_MIN_EXP__ (-125)
#define __LDBL_MIN__ 1.17549435e-38L
#define __LOCK_BITS_EXIST
#define __LONG_LONG_MAX__ 9223372036854775807LL
#define __LONG_MAX__ 2147483647L
#define __NO_INLINE__ 1
#define __PTRDIFF_TYPE__ int
#define __REGISTER_PREFIX__
#define __SCHAR_MAX__ 127
#define __SEOF 0x0020
#define __SERR 0x0010
#define __SFR_OFFSET 0x20
#define __SHRT_MAX__ 32767
#define __SIZEOF_DOUBLE__ 4
#define __SIZEOF_FLOAT__ 4
#define __SIZEOF_INT__ 2
#define __SIZEOF_LONG_DOUBLE__ 4
#define __SIZEOF_LONG_LONG__ 8
#define __SIZEOF_LONG__ 4
#define __SIZEOF_POINTER__ 2
#define __SIZEOF_PTRDIFF_T__ 2
#define __SIZEOF_SHORT__ 2
#define __SIZEOF_SIZE_T__ 2
#define __SIZEOF_WCHAR_T__ 2
#define __SIZEOF_WINT_T__ 2
#define __SIZE_T
#define __SIZE_TYPE__ unsigned int
#define __SIZE_T__
#define __SMALLOC 0x80
#define __SPGM 0x0008
#define __SRD 0x0001
#define __SSTR 0x0004
#define __STDC_HOSTED__ 1
#define __STDC__ 1
#define __STDINT_H_
#define __SUNGET 0x040
#define __SWR 0x0002
#define __UINTMAX_TYPE__ long long unsigned int
#define __USER_LABEL_PREFIX__
#define __USING_MINT8 0
#define __USING_SJLJ_EXCEPTIONS__ 1
#define __VERSION__ "4.3.3"
#define __WCHAR_MAX__ 32767
#define __WCHAR_TYPE__ int
#define __WINT_TYPE__ unsigned int
#define ___int_size_t_h
#define __size_t
#define __size_t__
#define __va_copy(d,s) __builtin_va_copy(d,s)
#define __va_list__
#define clearerror(s) do { (s)->flags &= ~(__SERR | __SEOF); } while(0)
#define feof(s) ((s)->flags & __SEOF)
#define ferror(s) ((s)->flags & __SERR)
#define getc(__stream) fgetc(__stream)
#define putc(__c,__stream) fputc(__c, __stream)
#define putchar(__c) fputc(__c, stdout)
#define stderr (__iob[2])
#define stdin (__iob[0])
#define stdout (__iob[1])
#define va_arg(v,l) __builtin_va_arg(v,l)
#define va_copy(d,s) __builtin_va_copy(d,s)
#define va_end(v) __builtin_va_end(v)
#define va_start(v,l) __builtin_va_start(v,l)

__AVR_ATmega16__ (as a result of -mmcu=atmega16) in there is just one of many #defines all your .c and .h see by default.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define __STDC_HOSTED__ 1

Is this really so?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

4.3.3 clearly thinks so.

Anyone can do this test - just invoke avr-gcc but pass "-E -dM" as command line parameters and it spews all the defines. I grep'd and sort'd the output above as the test.c I used happened to #include and that leads to hundreds more macros being output. (but this is a good way for checking what macros ARE active - if you've ever tried to decode _SFR_IO_ADDR() you'll know how useful this could be)

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

Quote:

4.3.3 clearly thinks so.

Clearly that is wrong thinking of it, yes? E.g. limits.h, time.h (and perhaps more) are missing.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Johan see:

http://gcc.gnu.org/onlinedocs/gc...

in particular:

Quote:
To make it act as a conforming freestanding implementation for a freestanding environment, use the option -ffreestanding; it will then define __STDC_HOSTED__ to 0 and not make assumptions about the meanings of function names from the standard library, with exceptions noted below.

However see much prior discussion here why using -ffreestanding is "Not a Good Idea(tm)". (it's the one you can use if you want the prototype to main() to be "void main(void)" as might be expected for embedded)

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

Quote:
I guess you meant IDE not ISP.

Of course. I'm suffering from an attack of eight-month-old-granddaughter, and my brain has turned to mush.

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

Hmm. Is there something in there that controls the name of the final .hex file based on a #define in the source?

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

The name is set as a parameter to the avr-objcopy utility that produces the hex, so the neither the compiler nor the linker is involved here. It might be that AVR Studio 5 (the IDE per se) has a system of "symbols" or "macros" and that one of them returns the AVR model name set in the project. If so, and if AS5 has a dialogue element for setting the name of the final hex, then you're golden. (I'd look in an ordinary Visual Studio for you, but I'm not near any such machine ATM.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Thanks.

It looks like the original premise doesn't work... if the IDE defined processor and the source definition are the same, it flags a warning of a redefined variable - not a problem. But if they're different, it's still using the IDE-defined processor and therefore throwing dozens of undefined register names at me.

Damn.

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

Aaaand after sleeping on it... I think the solution is not to define the processor in the source, but just use the external definition. It's easy enough to change, and its obvious - dozens of register names get complaints - to tell when I have the wrong one.

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

Been over to a AS5-enabled machine.

I could not find any provision for setting a specific name for the HEX. I assume it gets the same name as the ELF..

OT: In fact, I could not find anything where you can in any way affect the objcopy stage of a build, like specifying things to include or exclude..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Surely you just have multiple projects that build from the same source files. Each project has its own OBJ directory, so you rebuild properly.

You can also have multiple target directories for a single project.

You may also have some object files that are common to every build regardless of any conditional macros.
You can add these from a common directory as 'library' files.

Personally, I would definitely use separate 'projects' for different CPUs. But different 'builds' for the same cpu can just use different targets. Yes the HEX file will have the same name, but the path would be 'default/project.hex' or 'target_special/project.hex' or whatever.

David.

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

It's complicated, David.

The original code was all designed to work with the M32. There were a couple of different versions, for different display resolutions, but the majority of the code remained the same - just different display driver and font tables.

Then the M324 became significantly cheaper than the M32, and offered improvements in the serial ports, so I no longer needed to emulate a UART in software; all that code went. Also, many of the port names changed although I believe it's still binary compatible.

The final (current) version has another change of display - though it's a trivial difference; two lines of code in four thousand.

For historical reasons, this is all in one big file (yeah, yeah, I know...) for each version. Each new version was made by taking the last working version and making the necessary changes. But this means it's bloody difficult to merge changes back through the system.

By sticking it all into one file and building conditionally, I get everything in one place and consistent.

Neil

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

Quote:

Also, many of the port names changed although I believe it's still binary compatible.

Really? Surely the mega32 has SRAM starting at 0x60 and the mega324(xxx) have SRAM starting at 0x100 ?

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

Ah, you could be right. I think that what I meant to say was 324 registers in the same places as on the 32 had the same function and same control sequence. But I'm not even sure of that; I think there are some slight differences.

Forgive me; I'm having a bad attack of the eight-month-old granddaughter visiting this couple of weeks, and my brain is currently mush!

Neil