Can I select (or change) target processor at compile time, not project/solution properties?

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

I am preparing to adapt an existing AVR C/C++ application to support a different AVR processor (and subsequently a non-AVR processor), and before I get started, I'd like to make an appropriate choice for how to deal with the different compilation paths that would be needed to accommodate differing target types. My experience level with Atmel Studio 7 is "an hour after beginner", thanks to the outstanding support I've encountered here so far (thank you!)

 

Is it possible (if so, how?) to select my target processor type at the start of my C/C++ source file (using the GNU C/C++ toolchain in Atmel Studio 7, or potentially a completely different IDE/toolchain), rather than (or as an override to) the target type normally configured in Atmel Studio 7 solution/project?

 

Ideally, I'd like to have something like this ("why" is noted below):

 

// Beginning of main.cpp file - or any other c/cpp in the same project/solution) is here

// Today, choose target X, not target Y or Z - tomorrow we might choose target Y or Z rather than target X.

#define target_is_X

//#define target is Y

//#define target is Z

...

#ifdef target_is_X

// What would I put here, #include the header file for processor of type X?

#endif //target_is_X

#ifdef target_is_Y

// What would I put here, #include the header file for processor of type Y?

#endif //target_is_Y

#ifdef target_is_Z

// What goes here might be different, assuming target Z is not to be handled by the Atmel Studio 7 GCC tool chain

#endif //target_is_Z

...

// in the rest of the code in this file, it would (when encountering something target-specific) look like this:

#ifdef target_is_X

// A segment of the project source code specific to target X

#endif //target_is_X

#ifdef target_is_Y

// A segment of the project source code specific to target Y

#endif //target_is_Y

#ifdef target_is_Z

// A segment of the project source code specific to target Z

#endif //target_is_Z

 

I am open to any way to solve this, however, it would be very much preferable if I could use #define and #ifdef statements, as the source code would take different compilation paths depending on which target is currently selected (as in different bits of code to accommodate the detail differences in onboard peripherals present in the differing targets), and would at some point be re-purposed for yet a different (non-AVR, so other toolchain) target type.

 

"why?" - I am working with an existing program (source code) targeting a specific AVR processor type (which is currently set in the Atmel Studio 7 solution/project settings), and need to create within the same files and project/solution support for another AVR processor type (and a third option for a non-AVR processor type), and be able choose which processor type is going to get built (of course, for Atmel Studio 7 would be constrained to the processor types it supports), preferably using #define and #ifdef type directives (so that the solution has some portability out of Atmel Studio 7 when the need arises.)

 

Thank you for any advice or request for clarifying questions,

 

Dave

This topic has a solution.
Last Edited: Thu. Dec 16, 2021 - 09:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


But there's issues such as the linker having to know at build time which CPU it is so it links the right CRT with the correct IVT.

 

I just did:

 which created a solution and first project for mega32. Then I used:

 

and this time I created a project for mega328P.

 

 

When I build I see:

------ Build started: Project: projMega32, Configuration: Debug AVR ------
...
		Invoking: AVR8/GNU C Compiler : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega32 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega32" -c -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.cpp" 
		Finished building: .././main.cpp
		Building target: projMega32.elf
		Invoking: AVR8/GNU Linker : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -o projMega32.elf  main.o   -Wl,-Map="projMega32.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega32 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega32"  
...
		   text	   data	    bss	    dec	    hex	filename
		    114	      0	      0	    114	     72	projMega32.elf

Build succeeded.

------ Build started: Project: projMega328P, Configuration: Debug AVR ------
...
		Invoking: AVR/GNU C Compiler : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\include"  -Og -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c" 
		Finished building: .././main.c
		Building target: projMega328P.elf
		Invoking: AVR/GNU Linker : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -o projMega328P.elf  main.o   -Wl,-Map="projMega328P.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega328p"  
...
		   text	   data	    bss	    dec	    hex	filename
		    134	      0	      0	    134	     86	projMega328P.elf

Build succeeded.
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

So during one build I have built for two different processors despite what:

 

 

might lead you to believe - that is for selecting the debug target, not the build target.

 

(BTW you may have spotted that I inadvertently made one of these projects C and one C++ but I thought it was an interesting point when I spotted it so I left it as it was).

 

Anyway all that would remain now is to throw away any main.c/main.cpp that might have been created for each of these projects and instead use "Add as link" to give both projects access to a common source. You could then either use the fact that the compiler auto-defines symbols such as __AVR_ATmega32__ and __AVR_ATmega328P__ to make some parts of the common code conditional. Or you could add a -D to each project to say -DVARIANT=MODEL_1 or -DVARIANT=MODEL_2 to make some parts of the code conditional (that could as easily be -DMODEL_1 or -DMODEL_2). 

 

You make build defines like this under "Symbols" in the project properties.

 

Personally I would probably just go with __AVR_ATmega32__ and __AVR_ATmega328P__ that the compiler will define as a result of the -mmc= setting. It is, after all, how <avr/io.h> manages to pick the right ioxxx.h for the device so is a system that works infallibly. 

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

wb0gaz wrote:
I am open to any way to solve this, however, it would be very much preferable if I could use #define and #ifdef statements, as the source code would take different compilation paths depending on which target is currently selected (as in different bits of code to accommodate the detail differences in onboard peripherals present in the differing targets), and would at some point be re-purposed for yet a different (non-AVR, so other toolchain) target type.
Conditional compilation is also in make.

Though Microchip Studio 7 doesn't have a CMake interface there is MSBuild.

 

C/C++ projects and build systems in Visual Studio | Microsoft Docs (Visual Studio 2015, search for CMake and MSBuild)

Build and Run Options | Microchip Studio (bottom for MSBuild)

 

"Dare to be naïve." - Buckminster Fuller

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

Thanks to both - this gives me some clear insight into what to look for (again as before, more involved than I originally anticipated!)

 

I'll surface again after experimenting with and learning more about these possible solutions...

 

Dave

 

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

Appears I was going about this backwards - the IDE has a better way (at least as far as I can tell now) ---

 

I can set target in project properties > Device > Change Device, and that works as expected.

 

It seems all my program needs to know (at compile time) is which device was selected.

 

It appears #include <avr/io.h>, which I'd need to find registers and stuff, is fulfilled (for ATMEGA328P example) by:

 

C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.7.374\include\avr\iom328p.h

 

which (after a friendly reminder not to directly include the file) says

 

#ifndef _AVR_IOM328P_H_
#define _AVR_IOM328P_H_ 1

 

I was able to detect _AVR_IOM328P_H_ and (and one other elsewhere in the tree) to tell me which device is being used at compile time.

 

Is this an appropriate way to detect the selected device (as in, are these #define arguments unique per device and unlikely to change in subsequent updates to the tool)?

 

If not, is there a better way?

 

This (change device) feature seems far more convenient than trying to manage device selection in source code.

 

Thanks,

Dave

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The "AVR Built-in Macros" section of https://gcc.gnu.org/onlinedocs/g... details a better option (check the documentation for __AVR_Device__).

build-avr-gcc: avr-gcc build script

toolchain-avr-gcc: CMake toolchain for cross compiling for the AVR family of microcontrollers

avr-libcpp: C++ standard library partial implementation (C++17 only) for use with avr-gcc/avr-libc

picolibrary: C++ microcontroller driver/utility library targeted for use with resource constrained microcontrollers

picolibrary-microchip-megaavr: picolibrary HIL for megaAVR microcontrollers

picolibrary-microchip-megaavr0: picolibrary HIL for megaAVR 0-series microcontrollers

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

apcountryman - thank you, that clearly would provide what I was looking for (and more.)

 

Thanks!