Libpololu for not total dummies

Hello All!
I have one (for now) question and one proposal. Question first.

I tried to compile libpololu libraries and got different sizes than the original libraries. I use WinAVR 20100110 and tried to compile libraries from libpololu-avr-101104.zip. For example, originally, the size of libpololu_atmega324p.a was 334466, after compilation it had size of 402064. I just run “make clean” followed by “make” from the pololu lib directory (I have WinXP with SP3). I am curious if this difference is due to different compiler versions (then I would like to know which compiler and which version was used to compile the original libraries) or it is due to the lack of optimization (then I would like to know how to set optimization switches).

Now about my proposal (organized as a question :).
Is it possible to organize discussion about details of realization of libpololu libraries (not for total dummies)? Reading of the libpololu source code was exciting and challenging, and now I have a lot of questions. For example: Is it safe to use Timer0 interrupt in SVP-324 controller? In section “6.f. Orangutan Motor Control Functions” of “Pololu AVR C/C++ Library User’s Guide” it is stated that BOTH Timer0 and Timer2 are used for generating PWM outputs for all controllers (including Orangutan SVP), but in “Pololu AVR Library Command Reference” it is said that Orangutan SVP does not use Timer0 for PWM. So, the safety of using Timer0 interrupt for the Orangutan SVP is open.

Another question is about effectiveness of the library calls. Libs are written in C++. extern “C” commands make subroutines accessible from C. Usually they are just C-wrapping of C++ subroutines (C-subroutines just call the corresponding C++ subroutine). In many cases they are declared in such a way, that they are NOT inline functions, Does it mean, that if I use C-version of the library (say with AVR Studio) I make double call (call C-function which does nothing but immediately calls C++ finction)?

Thank you.

Hello.

I’m happy to answer any questions you have about how the Pololu AVR Library works.

It looks like we didn’t update the Library user’s guide as thoroughly as we should have when we added support for the SVP. I have have changed the introduction to section 6.f to mention how timer usage of the motor control functions differs for the X2 and SVP. In short, the SVP only uses timer 2 for motor control, so timer 0 is completely free for you to use however you want.

Yes, calls of C functions are essentially double function calls. This is a consequence of trying to support both C and C++ well. We have taken steps to optimize both C and C++ function calls for speed in some places, such as our digital I/O library, but this requires completely separate code for both C and C++.

- Ben

Thank you, Ben!
What about the difference in library size? When I compile it I get bigger file.

Another technical question concerns Timer2 interrupt handler in OrangutanTime.cpp. Can I use this interrupt for my own purposes? I understand, that all timing relies on this interrupt, but I do not need to change the timing, I just want to use 1 ms interrupt (which is provided by the library) for my own needs. Say I want to write a code for Finite State Machine for LCD output and Button press handler. 1 ms interrupt is the perfect place for this. What I am thinking is to modify TIMER2_OVF_vect() something like this

extern "C" void TIMER2_OVF_vect()
{
   __asm__ volatile (

   .  .  .

   "brcc Inc_msCounter" "\n\t"
   "out 0x3f, r2"       "\n\t"
   "pop r25"            "\n\t"
   "pop r24"            "\n\t"
   "pop r2"             "\n\t"
   "reti"               "\n\t" // us_over_10 < 10000, return

   "Inc_msCounter: sts  us_over_10+1, r25" "\n\t"
   "sts  us_over_10, r24" "\n\t"

   "lds  r24, msCounter"   "\n\t"
   "lds  r25, msCounter+1" "\n\t"
   "adiw r24, 1"           "\n\t"
   "sts  msCounter, r24"   "\n\t"
   "sts  msCounter+1, r25" "\n\t"

   "brcc msCounter_end"    "\n\t" // if carry is not set goto the user asm-code

   "lds  r24, msCounter+2" "\n\t" // carry flag is set, increment the high word
   "lds  r25, msCounter+3" "\n\t" // of the msCounter
   "adiw r24, 1"           "\n\t"
   "sts  msCounter+2, r24" "\n\t"
   "sts  msCounter+3, r25" "\n\t"

   "msCounter_end:" "\n\t"
// < add asm-code for 1 ms interrupt here >

   "out 0x3f, r2" "\n\t"
   "pop r25"      "\n\t"
   "pop r24"      "\n\t"
   "pop r2"       "\n\t"
   );

// < add C-code for 1 ms interrupt here >

   __asm__volitile (
   "reti" "\n\t"
   );
}

What I did is just replaced brcs with brcc for convenience and rearranged blocks of the code. There are two places where I can add my assembler code and C-code to this 1 ms interrupt.

The question is: can I modify Timer2 interrupt handler in this way, or the Pololu library counts on fixed size or duration of the TIMER2_OVF_vect() ?

Thank you.

You are likely using a different compiler, so a difference in file size is not surprising. If the compiled library were significantly bigger or smaller, I’d be more concerned.

The changes you’re proposing to make to the timer 2 overflow interrupt look fine, though I only skimmed it and didn’t verify that the logic is entirely correct. The library code does not make any assumptions about the size or execution time of the interrupt. Just note that the ISR is executed every 106.4 us, so it is crucial that it be, on average, very fast, or else you are devoting a significant portion of your processing time to the ISR. This is why we wrote it in (what we hope is) speed-optimized assembly. Since your addition only affects the execution time of the ISR once per millisecond, you won’t have to worry as much about overburdening the processor, but make sure the ISR run time doesn’t exceed ~200 us (or else you will start permanently missing timer updates).

- Ben

Hello, Ben.
Time for another set of questions.

1. Library libpololu is organized in such a way, that all finctions which belong to the same group (say all LCD functions) are placed in one cpp-file. Does it mean, that if I call one of these functions, the whole LCD module will be linked to my code (even if I do not use some of it’s functions)?

At least C-compiler works like this. The library is written in C++, so I am not sure if it is possible not to link all class members to the code. In C if we want to link only explicitly used subroutines we must put them into separate files (one file, one subroutine). Is this true for AVR C++?

I tried to rewrite libpololu library in C only for SVP324 controller. Not the whole thing, but the easy part:
Time, LCD, LED, PushButtons, and Digital modules. I used one-file-one-function rule for reducing size of the code. It seems, that it works, but I was slightly confused by using “static” modifier in the original C++ text of the code. You cannot write your own library without 100% understanding of the original code. It is understandable that all class function-members are declared as static (this forces the compiler to use only one instance of such functions even if several variables of this type exist in the program.

What was strange to me is using of static modifier in inline functions. From my point of view, inline function puts it’s body at the place where it was called, and modifier “static” looks strange, at least it is not clear what it is used for here. I experimented with inline functions in my C-version of the pololu library and found that though avr-gcc compiler does not return error or warning, defining inline functions as static, noticeably increases the size of the library and the resulting code.

2. What is the reason in declaring inline functions as static in the pololu library ?

Thank you.

Hello,

I think I can help answer your questions. But could you explain why you are trying to rewrite our library in C?

There are many C compilers, and they behave differently. We use GCC, which provides two options to control the code that is included in the final binary: -ffunction-sections and gc-sections. The -ffunction-sections argument is used in compiling the library, and it causes each function to be in its own “section”. The gc-sections argument is used when linking our example programs, and we recommend for your own projects. It causes unused sections to be removed. So these options together have the result that only functions that you use will be compiled into your code.

I believe ISRs will be compiled in as long as you use at least one function from a file, but I could be wrong about this.

The “static” keyword in C and C++ has about 10 different meanings. I think you are asking about why we use it on some inline functions in C++ classes - “static” in that context means that the function is a member of the class, so you can call it whether or not you have an object. In C, this concept does not exist. Instead, “static” on a function means that it is used only within the current file rather than being linked between multiple files. Note that this meaning is entirely different and unrelated to the C++ version! Anyway, it seems like “static inline” would not have much effect, but based on some Google searches, one effect is that any static variables or strings defined within the method are not shared between multiple files. Instead, if the function is included in multiple files, you will have multiple copies of the static variables and strings. That could explain why using “static” caused your code size to increase.

-Paul

I think I added the “static” keyword to some of our inline C functions. At some point there were some inline functions that the compiler actually chose not to inline, so the compiler generated symbols for these functions at compile time and then complained at link time when these symbols existed in multiple objects. Adding the “static” keyword fixed that because it suppressed the symbols. There might have been a bug in that version of the compiler and I don’t expect that this effect will be easy to reproduce.

–David

Hello again.
I was playing with compiling pololu library from the source code and realized that both options -g (debugging) and -Os (small size optimization) are on in the makefile which is responsible for library compilation. I am talking about
libpololu-avr/devices/template.mk
This make file is used for compilation of libraries for all devices. Individual make files for specific devices just set DEVICE variable and call this template. My concern is that the variable CFLAGS contains both -g and -Os options. Usually, if you want to debug your code, you set debug option -g and remove optimization -O0. For release version you set optimization what you like either -Os (for small size) or -O3 (for fast code) and remove the debug option -g. Debug option is mostly useless if optimization is turned on, because optimization heavily rearranges the code and it does not match line-by-line c-code any more. With both options turned on, the size of the pololu library for atmega324p is 372524. It is slightly bigger than the size of the original libpololu_atmega324p.a file, provided with the library, probably because of different versions of WinAVR GCC compiler. BUT when I removed -g option, I reduced the library size to 129142. This is my question. Is there any particular reason for turning both options (-g and -Os) on in the make file?

Hello,

The debugging symbols do not get loaded on the AVR, and on a modern PC, there is not much reason to try to save 200k, so why are you worried about it? If there is some chance that the symbols will be useful to people, it seems like a good idea to make them available.

By the way, the AVR-gcc FAQ suggests doing exactly this:

-Paul