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

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

Re: Re: [avr-gcc-list] RE __attribute__((naked)) isn't doing fine!


From: sebastian meuren
Subject: Re: Re: [avr-gcc-list] RE __attribute__((naked)) isn't doing fine!
Date: Fri, 2 Jul 2004 12:22:27 +0200

> D.Sc. Julius Luukko wrote:
>
> How are your tasks initially called? Couldn't the tasks' contexts
(=registers) be initialized so that r24,r25 contains the pointer argument
and the context switch routine "restores" the context before jumping to the
first address of your task. r24 and r25 would then contain the argument when
the task starts. No actual C function call is used to call the task. That
way your tasks could be normal functions without the hassle with naked
attribute and two functions. This is how it is done e.g. in uC/OS-II.
>
>
Year, I know that's a was to do it... But I decieded to do it a bit like
it's done in ethernut... My basic approach is to keep task-switching time
low. Therfor I  just want to save the neccessary registers. This are (using
WinAvr) only those, which mustn't be clobered during a function call
(unfortunatly the argument-registers, at least r24/r25 can be clobered!).
So, if a task decides to suspend itself (e.g. by waiting on a semaphore),
the "normal" task-switching only saves the "unclobbered" registers (not
including r24/r25). For sure I could cheat this anyhow, but that would
result in more offset.... If you take a look at ethernuts os, it works
around that by using a special function: (thread.c)

static void NutThreadEntry(void) __attribute__ ((naked));
static void NutThreadEntry(void)
{
    asm volatile ("pop r25" "\n\t"      /* first parameter hi-byte */
                  "pop r24" "\n\t"      /* first parameter lo-byte */
                  "pop __tmp_reg__" "\n\t"      /* Get RAMPZ */
                  "out %0, __tmp_reg__" "\n\t"  /* Restore RAMPZ */
                  "pop __tmp_reg__" "\n\t"      /* Get SREG */
                  "out %1, __tmp_reg__" "\n\t"  /* Restore SREG */
                  "pop __zero_reg__" "\n\t"     /* Zero register */
                  "reti" "\n\t" /* enables interrupts */
                  ::"I" _SFR_IO_ADDR(RAMPZ), "I" _SFR_IO_ADDR(SREG)
        );
}
 This function is executed before the task is scheduled for the first time.
That is achieved by introducing a special "start-frame", which is created
only once by the
"NutThreadCreate" - function (thread.c):

HANDLE NutThreadCreate(u_char * name, void (*fn) (void *), void *arg,
u_short stackSize)
{
 ....
    /*
     * Setup entry frame to simulate C function entry.
     */
    ef->cef_pchi = (u_char) (((u_short) fn) >> 8);
    ef->cef_pclo = (u_char) (((u_short) fn) & 0xff);
    ef->cef_sreg = 0x80;
    ef->cef_rampz = 0;
    ef->cef_r1 = 0;
    ef->cef_arglo = (u_char) (((u_short) arg) & 0xff);
    ef->cef_arghi = (u_char) (((u_short) arg) >> 8);
    sf->csf_pchi = (u_char) (((u_short) NutThreadEntry) >> 8);            //
The Task wont start with it's entry-function (fn), it will start with the
helper-function !!!
    sf->csf_pclo = (u_char) (((u_short) NutThreadEntry) & 0xff);
...

I first thought about s.th simular, but life could be so easy if only I
could insert my own prologue code (doing that what ethernut does by a
help-function). The
difference betwenn Ethernut and my approach is, that ethernut does it during
runtime (using more stack & instructions) and I did it during compile time
(with a cryptic macro that isn't proved to be working under all
circumstances. Of curse I can still use my macro, do it like ethernut or
change the whole stuff to save more registers (including my
argument-registers) .... But I'm a bit perfectionist (cause even one
additional rjmp-instruction would make the cryptic macro reliable, I even my
cheat the compiler by using the __attribute__ ((section(".foo")))  - stuff
(thank you eric!!!), but all that makes it complicated or wastes
resources... and that's contraticting the kiss-principle [keep it simple,
stupied]...
So Thank you all for your suggestions (can't get enough hints in your live
(-:), hopefully one day the compiler will come alonge with a feature like
__attribute__((useprologue:myprologue))  (-;:!!



reply via email to

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