avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] is tiny15 not c-programmable


From: Bruce D. Lightner
Subject: Re: [avr-gcc-list] is tiny15 not c-programmable
Date: Mon, 26 May 2003 15:32:49 -0700

Abhijeet,

> Hi Friends
>   I am doing a project using tiny 15.
> The avr libc user manual states the following
> for tiny 15
> "[1] Assembly only. There is no support for these devices to be
> programmed in C since they do not have a ram based stack."
> 
> But I could program attiny15l in C using iccavrtiny.
> Can someone please exlpain.
> --
> Regards
> Abhijeet D Mhatre
> Email: address@hidden

I've been using "avr-gcc" to program the Atmel ATmega15L microcontroller
for almost a year.  I love the part, especially its size, features, power
consumption, and price!  I've used "avr-gcc" for quite a number of
ATtiny15L projects, including a tiny RS232 serial port programmer for AVR
in-circuit programming (fits in DB9 connector "hood" and is self-powered
by RS232 voltages), a couple of different DC motor controllers, a air-flow
sensor, a touch sensitive light with dimmer, and an analog data logger.

This use of "avr-gcc" not for everyone!  You need to have a good
understanding of what kind of C statements generate what kind of AVR
assembly code.  If you are a "hard core" embedded programmer like me, that
part comes naturally.  (Unlike Joerg "IMHO" Wunsch, you will need to
actually look at the assembly language listing file. [Ref: Joerg Wunsch
email, Re: [avr-gcc-list] Help from a veteran?, Mon, 31 Mar 2003 10:00:05
+0200 (MET DST)]

I use avr-gcc version 2.95.2 for ATtiny15L programming, but it is very
likely that avr-gcc version 3 will work as well.  I use the default AVR
processor (i.e., AT80S8515), but provide my own I/O header definitions for
the ATtiny15L.  You *must* use C-compiler optimization (such as -Os) to
get AVR code that does not reference any SRAM.

I really like the ATtiny15L, and am willing to "jump through a few hoops"
in order to make "avr-gcc" work.  If you give avr-gcc's excellent code
generator a chance, it will generate AVR machine code that is as good or
better than hand-generated assembly language, with no need for SRAM.  

Here are a few of the required "tricks"...

(1) Limit the call tree depth to 2 or 3 (e.g.,
main->subroutine->subroutine), depending up whether you will be using
interrupts.  The ATtiny15L has a "hardware" call/return stack of limited
depth.

(2) Limit the complexity of your subroutines as to not overflow the
available "scratch" registers.  I found that this is pretty easy to
control, once you have a little bit of experience.

(3) Assign any required global variables to registers as in the following
example:

      register unsigned short v asm("r2");

(4) Use a Perl script to check the generated AVR machine code for "illegal
instructions", namely those that reference SRAM (e.g., push/pop/sts/lds)
or use instructions missing from the ATtiny15 instruction set (e.g.,
adiw/sbiw).  My "makefiles" add the following rule...

    .c.o:
            $(CC) $(CFLAGS) -c -g -Wa,-almshd=$*.lst -o $*.o $*.c
            perl chkinstr.pl $*.lst || ( rm $*.o && exit 1 )

...which runs the assembler's "mixed listing" through a Perl script
(chkinstr.pl) which will abort the compile process if "bad stuff" is
detected.  The Perl script prints out an error message showing the
offending AVR assembly code along with the C-code line number and
statement that caused the problem.

(4) Use "static inline" routines and in-line assembly macros as required
to limit call depth (and register usage).

(5) Use my BYTE() in-line assembly macro to avoid C code which generates
"illegal" ATtiny AVR instructions like "sbiw".  (This could be fixed with
a patch to avr-gcc, but I'm too lazy to figure out how.)

    #define BYTE(ch) ({                   \
        uint8_t t;                        \
        asm volatile (                    \
                "ldi %0, %1"              \
                : "=d" (t)                \
                : "M" ((uint8_t)(ch))     \
        );                                \
        t;                                \
    })

For example, instead of using constructs like...

    while (n--)
    for (i = 0; i < 10; ++i)

...use instead...

   while (n -= BYTE(1))
   for (i = 0; i < 10; i += BYTE(1))

As for Joerg "IMHO" Wunsch's pronouncement:

   Nobody considered the effort worth a while to port gcc to an
   architecture that doesn't even have RAM.  It might even be
   impossible to do it.

He once again has got it half-right!  The big volume (and in fact the big
dollars) is in the cheap parts, like the ATtiny15.  This is a "fact of
life" in the embedded world.  It makes no sense to "skip" these RAM-less
parts!  I predict that there will be a "port" for these parts...I just may
have to do it myself.

As for it being "impossible", that's just another typical "Joerg-ism".

Best regards,

Bruce

-- 
 Bruce D. Lightner
 Lightner Engineering
 La Jolla, California
 Voice: +1-858-551-4011
 FAX: +1-858-551-0777
 Email: address@hidden
 URL: http://www.lightner.net/lightner/bruce/


reply via email to

[Prev in Thread] Current Thread [Next in Thread]