3

I would like to bind a global variable to an unused I/O register (e.g. PORTB) using avr-gcc, to reduce code size. I learned this trick in AVR's application note AVR035 (page 14).

In the application note, they use the IAR compiler and bind the variable to an I/O register like this:

__no_init volatile uint8_t counter@0x35;

With avr-gcc, I can bind a variable to a standard register (r3 in this case) using this line:

register uint8_t counter asm("r3");

This does not work for I/O registers though. Is there a way to do this for I/O registers?

2
  • whoa, this is a nice trick. but one question: when you're thinking about the code size gains from using IN and OUT instead of STS and LDS, why aren't you coding the whole thing in assembly in the first place? Commented Apr 30, 2012 at 12:53
  • Assembly is probably a good idea on this level of code tweaking :-) I was hoping for a "quick" gain by just moving some global vars to i/o registers. Turned out it is not that easy. Commented Apr 30, 2012 at 18:44

1 Answer 1

2

Since this works for global variables only, what about just using something like this to use, for example the Uart Baud Rate Register:

#define myGlobalVariable UBRR

Also note that this optimization is only worth it if you're doing a lot of bit testing, because there are direct bit testing instructions for most of the IO registers. Oh, I forgot that not all AVRs have the LDS and STS instructions and some access SRAM only through the Z register, which makes a big difference in both code size and speed compared to a simple IN and OUT...

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, this is what I am doing now. However I noticed that using UBRR actually increased code size compared to a SRAM var. Using e.g. PORTB saved a couple of bytes though. Probably I need to look more closely what the compiler does here.
@henning77 IO registers are usually volatile which means that the compiler must generate IO operations for every read or write in the source code. With (non-volatile) variables the compiler can optimize accesses away by caching values in registers. Example: i = 5; i = i + 1; i = i * 2; requires 3 writes and 2 reads from the IO register aliased to i but only a single write to the global non-volatile variable i.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.