Hi Frederic,
just let me add a few notes:

If you want to call functions by pointers you should rather use the compiler's typechecking capabilities than using *sloppy* (void*) casts. You can do this by cleanly typed declarations as you can see in the attached example code: The declaration and use of my2 is accepted while a declaration like int ( *my2 ) ( int ) = my1; will produce an incompatible pointer types warning. Using this can keep you from spending hours or days for debugging searching for the reasons of unpredictable behaviour. ( Don't wonder about the form: my1 and &my1 are equivalent and both valid.)

Now the other problem: As a matter of fact your asm instruction eventually uses a variable which means it is no immediate addressing. This is completely independent of the location of your variable so a const declaration won't help anything since it only tells the compiler that it is read only and the linker that it may reside in program flash memory. Furthermore even extern const int * __stack; will not work for still it is no immediate addressing and __stack is no pointer variable (!). If you tried this with "g" the compiler will accept that but will produce the wrong results: It will produce a memory lookup at address __stack to read a pointer to an integer variable and move it to SP. __stack is a symbol which can be relocated at link time and which can p.e. be declared as extern int __stack[]. Here you can see the big difference between int* a; and int b[]; both are compatible if you use it this way
extern int* a;
extern int b[];
...
a = b;
...
int b [] = {1,2,3,4,5};
but declaring b as int* though it is an array like this
extern int* a;
extern int* b;
...
a = b;
...
int b [] = {1,2,3,4,5};
is likely to result in excessive debugging parties ;-) (in the latter case a will carry 1 and dereferencing it like a pointer is destined to be used ....) Finally the fact that __stack is just a symbol has got another consequence: You could keep your extern int __stack declaration and just add a & to your asm instruction
mov %0, r1"::"i" (&__stack)
In this case you could declare __stack as whatever you want (extern struct { int a; union { char b[2];struct ... } c; int d:2;} __stack [ 25 ];) because ...it's just a symbol somewhere in address space.
I hope that's not too much words about nothing :0).
Have much fun

Arnd-Hendrik


[email protected] wrote:
Hi all,
I want to initialize the stack pointer. Instead of using the
STACKINITIALVALUE like in the mspgcc doc example :
#define STACKINITIALVALUE 0x0280
NAKED(_reset_vector__)
{
/* Initialise the stack */
__asm__ __volatile__("mov %0, r1"::"i" (STACKINITIALVALUE));
/* Your startup code goes here */
__asm__ __volatile__("br #main"::);
}

I want to use the =93__stack=94 variable defined in the linker but if I =
try
this:
NAKED(_reset_vector__){

 extern int __stack;

 // Initialize the stack pointer
 // N.B. Don't forget to add the compiler option "-mno-stack-init"
 __asm__ __volatile__("mov %0, r1"::"i" (__stack));

}

I obtain this error:
inconsistent operand constraints in an `asm'

Is there someone who knows how to use =93__stack=94?


First I'll tell you why the compiler won't accept what you are
doing.  Then I'll tell you why it won't work anyway, so pay attention.

Given your other question,


Is it possible to give me an example of how I can get the function
pointer at compile time?
Thank you very much!


You can't get it at *compile* time, exactly, but you can trivially
get it at link time, with something like

void * const interesting_functions[] = {
        (void *)&main,
        (void *)&function_foo,
        (void *)&function_bar,
        (void *)&function_baz
};

Note that I declared the array "const" so it can be put in ROM rather
than needing to be copied to RAM.

This is such an elementary thing to be confused about that I'll risk being
personally offensive and guess that you're not a particularly experienced
C programmer.  As such, I recommend an *extremely* careful reading of the
manual and relevant source code before trying to get tricky with asm()
and reset vectors.  You can get into deep trouble that way.

In particular, "if you lie to the compiler, it will get you".  GCC's asm()
features are extremely powerful and let you describe your asm to the
optimizer so it can work with it.  If you describe it correctly, the
optimizer can do wonderful things for you.  But if you do not correctly
describe the conditions the asm requires to operate, the optimizer
will do things you didn't imagine and the asm may malfunction in highly
mysterious ways.

Just for example,
        asm("..." : "=r" (x) : "r" (x))
Some people have assumed that %0 and %1 would have to be the same register,
the one that contained "x".  FALSE!  There's a way to tell the optimizer that,
either
        asm("..." : "=r" (x) : "0" (x))
or the more compact
        asm("..." : "+r" (x)))
but if you use the original form, the optimizer will happily take
advantage of the fact that it copies from place-to-place and turn:
        x = y;
        asm("..." : "=r" (x) : "r" (y))
        foo(y);

into
        asm("..." : "=r" (x) : "r" (y))
        foo(y);
to save an instruction.  If your "..." code doesn't cope with the
possibility that %0 and %1 might be different registers, it will either
operate on the wrong data (if it reads from %0), or overwrite %1 which GCC
needs to remain unchanged so it can call foo(y).



Okay, back from the digression to your problem.  What's wrong with

        __asm__ __volatile__("mov %0, r1"::"i" (__stack));

Well, the reason it won't compile is that you are using a *variable*
__stack, but telling the compiler, via the "i" constraint, that only
an *immediate constant* is legal.

You can actually use any addressing mode in the source of a mov, so
        asm("mov %0, r1" :: "g" (__stack));

will generate correct assembly code.  Note that you don't need the
underscores around __asm__ unless you're compiling in strict-ANSI mode,
and any asm() with no output operands is automatically assumed to be
volatile by the compiler.  (It must have strange side effects, because
it doesn't have any non-strange ones and presumably you put it in the
source for *some* reason.)

However, DON'T try to put that in your code!  It won't work!

The reason is that you have declared __stack as "extern int".
(Really, it could be "extern int *", since that's what it is -
a pointer to a 16-bit aligned piece of memory.)

There's no "const" in the declaration.  That means that the variable
is in RAM.  Which means that its value is UNDEFINED until the initial
startup code is executed which copies the initialized variables from
ROM to RAM.

In your naked reset vector, that code hasn't been run yet!  Until you
call it, THE VALUES OF ALL NON-CONST VARIABLES ARE UNDEFINED.
Specifically including __stack.


Now, you could place the __stack variable in ROM (which will happen
automatically if you declare it as const and don't do anything
weird with the linker) and fetch from that, but you could just as
easily copy the initializer in-line and make it an immediate
operand after all.

The only reason to use a constant "variable" in ROM is if its value
cannot be computed when the C is compiled, and is going to be
provided by linking in some non-C object file or by patching the
final binary.


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Mspgcc-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mspgcc-users


/*
   This is from the example
   #define STACKINITIALVALUE 0x0280

   The following versions will all produce memory lookup and thereby
   result in compiler error messages with immediate addressing.
   Even with asm .....:"g"... they will not lead to the expected results.
   extern int   __stack;
   extern int * __stack;
   extern const int   __stack;
   extern const int * __stack;
*/

extern int __stack [];

NAKED(_reset_vector__)

{

/* Initialize the stack */

__asm__ __volatile__("mov %0, r1"::"i" (__stack));

/* Your startup code goes here */

__asm__ __volatile__("br #main"::);

}

static int my1 ( char a )
{
   return ( int ) a;
}

int main ( int argc, char** argv )
{
   int ( *my2 ) ( char ) = my1;
   return my2 ( 'a' );
}

Reply via email to