Code Reuse and #define

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

This may be a general C question and not an Atmel Studio question per se.  I am using Atmel Studio 7.0.1188 so I will post in this forum.

 

I have created a library that I want to reuse.  The library exists on it's own as a "GCC C Static Library Project." It is critical to its function that the library makes use of utils/delay.h.  As we are all aware, delay.h requires the definition of the macro F_CPU.  

 

I would like to use the library on multiple projects that run on different devices operating at different speeds.  However, to my understanding, this requires that that I either:

  1. Define F_CPU in the library code and change it each time I compile for a new device, 
  2. Define F_CPU in the project's tool chain properties and change it each time I compile for a new device, or
  3. Copy the code into each project where it will be used and set up a header file that defines the marcos that want to use for the target device (like the tutorial on "Modularizing C Code: Managing large projects").

 

None of these seems ideal.  Options 1 and 2 lends themselves to errors (forgetting to change the macros) and Option 2 presents a configuration management issue with multiple copies of the same code (making a change to the library).

 

Is there a way that I can define F_CPU at compile time based on the project?  Is there any other options that you can think of that I have overlooked?

 

Thanks in advance for any assistance.

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

Put the Symbol F_CPU in Toolchain Properties for both C and C++. Select All Configurations.
.
It is not difficult to do this for every Project.
Of course, it would have been sensible for AS7 to provide a Box for F_CPU.
.
Then make a #Error if F_CPU is not defined.
.
David.

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

David,  Thanks for the reply.  How is this different from my description of option 2 above?  In order for me to define the macro in the tool chain, I have to define it for the library project.  If I define it in the main project it is still undefined in the library.  This may be because the library is compiled first because it is a dependency but I am not sure.

 

Thanks again for your quick response.

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

If F_CPU is required by anything in the Static Library, then the library will be incorrect for any project that has a different F_CPU.

Static Libraries are (typically) not really useful for uC projects...

David (aka frog_jr)

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

Frog jr, that is my fear, that there is no really useful way to do what I am looking to do.  If my fear is realized I will just go about implementing option 3 with an extra project that represents the CM truth for the library.

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

You CAN define it  in the IDE. Very obscure, though. Go to the Project menu and select your project properties at the bottom of the menu. Then, I think you go to the Symbols subsection of the AVR GNU C section, and simply type it out (in the Defined Symbols box) like you would in a #define but without the "#define". Eg, F_CPU 8000000UL or such. When you do this, it becomes a global define; if you put it in an included file, that file has to be included in every c file that needs to know F_CPU. Yes, you need to remember to do it. But, I would argue that there are many things you need to remember to do. I do not think there is any process that avoids this need!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Oct 15, 2016 - 01:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yungoe wrote:

3. Copy the code into each project where it will be used and set up a header file that defines the marcos that want to use for the target device (like the tutorial on "Modularizing C Code: Managing large projects").

In other words, you make it a source library - rather than an object library.

 

​As others have already said, this probably the most practical approach in this kind of environment - because it is so hard to accommodate all the hardware runtime options in a static (object) library.

 

This is precisely what ASF does and, in my experience, all the other similar things from other chip makers.

 

Update:

 

This is a very frequently-recurring topic!

 

See clawson's recent reply to one such:

clawson wrote:
Sadly this is exactly why static libraries have almost no part to play in AVR development (apart from the obvious ones line libc.a and libm.a). When you use "library" code with an AVR there are almost always some compile time configuration like a UART baud rate or a PORTx choice for an LCD interface or an F_CPU input for calculating timer rates and so on. You have two choices...

 

 https://www.avrfreaks.net/comment...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sat. Oct 15, 2016 - 11:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
You CAN define it  in the IDE. Very (sic?) obscure, though. 

I don't know about very obscure - but certainly not as clear as in a header somewhere.

 

Which brings up 2 pet peeves about IDEs:

 

  1. I have never yet seen an IDE where the 'Go To Definition' works for things defined in the project options;
     
  2. I have never yet seen an IDE that provides any means to document the settings made & options selected in the project options.

 

But I guess that's a topic for a separate discussion ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yungoe wrote:
Copy the code into each project where it will be used [/quote]

Note that you don't have to copy it - you could just have a single copy in one location, and have your project "point" to that.

 

Personally, I do prefer to take a copy - as that makes the project self-contained, and you won't get any nasty surprises if the "main" library changes ...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
This is a very frequently-recurring topic!
 
See clawson's recent reply to one such
Thanks for finding that. Saves me retyping the key points. Bottom line : static libs have no place in the AVR world. If you don't believe me answer why there are 17 copies of libgcc, libc, libm etc. ;-)

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

I suspect that the desire for static library is so that the source code remains private.

 

If this is important,   separate the F_CPU dependent functions.    Leave them as public source.    The rest as a static library.

 

AS Cliff has suggested,   you might just as well keep everything public.   

In practice,   modern PCs will compile quite fast.    The Makefile ensures that files are only re-compiled if necessary.

 

David.

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

But if F_CPU is external from static lib code then you are going to have to pass it in as a function parameter and your UART code (for example) is going to be a sea of "if baud==9600 && F_CPU_parm == 8000000 ..." Or some convoluted math function to calculate UBRR at run time. Same for your timer code and your LCD delay code and everywhere else that F_CPU is consumed.

(and you still need 17 copies!)

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

Thank you all for your answers.  It seems very clear to me that I am looking to build a Source Library here and I will manage it as such.

 

Again, I truly appreciate your input.

 

Cheers,

Yungoe