WinAvr/GCC code problem

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Okay, I've downloaded WinAvr, and are fiddling with my
first experiments on a atmega128. I have been able to
compile a blinking led program, and let it actually run
on the atmega128.

Now I am trying some inline assembly, and the compiler
complains about possible contraint problem with %1.
While I understand that there are simpler ways to send
some value to port b, I'd like to know what is wrong
with my code:

#include <avr/io.h>

int main (void)
{
  unsigned char outputvalue;

  //set PORTB for output
  DDRB =0xFF;

  // this I want to sent to port b
  outputvalue = 0x55;

  while (1)
  {
    asm volatile( "out %1, %0"  "\n\t"
             : "=&r" (outputvalue)
             : "I" (PORTB)
            );

  }
  return 1;
}

Any suggestions?


--
Thanks,
Frank Bemelman
We've slightly trimmed the long signature. Click to see the full one.
Re: WinAvr/GCC code problem
I'm no gcc inline assembly guru.  I usually just poke at it to see
which way it jumps.  However, I'll try to help...

On Thu, 23 Oct 2003 18:57:44 +0200, "Frank Bemelman"

[...]
Quoted text here. Click to load it

I think you misunderstand the difference between input operands and
output operands.  The terms "input" and "output" are relative to the
assembly code. Output operands come first.  The value of the variable
"outputvalue" is really an input (to the assembly code).  You don't
have any output operands -- there's no "return value" from the
assembly.

Try something like

   asm volatile ( "out %1, %0 \n"
                  :  // No outputs
                  : "r" (outputvalue), "I" (PORTB)
                  :  // No clobbers
                );

A few more notes:

The code above isn't real useful.  Hopefully this is just for
learning.  I believe if you are determined to use the "out"
instruction, there are functions supplied with avr-gcc to do that.
Look for them: they will probably be instructive.

The port address you pass (PORTB) is probably wrong -- I believe it
will expand to the RAM address of PORTB rather than the I/O address.

Download Harald Kipp's "GCC-AVR Inline Assembler Cookbook" from the
web.  It's not perfect, but it's better than most documentation of gcc
inline assembler -- for one, it exists, for another, it's specific to
the AVR.

HTH,

                               -=Dave
--
Change is inevitable, progress is not.

Re: WinAvr/GCC code problem

Quoted text here. Click to load it

Thanks, this was indeed *part* of the 'problem'. Thought those
places meant source and destination rather than inputs and outputs
to the final assembly line.

Quoted text here. Click to load it

At this moment I'm just playing around, no worries ;)

Quoted text here. Click to load it

Which seems to be exactly what happens. When I replace PORTB with 0x18
in your suggestion, it works.

Quoted text here. Click to load it

I've read that, but I think it's not up-to-date. He uses PORTB in his
examples, which was probably defined as 0x18 in those days. Now it
is defined as _SFR_IO8(0x18) and I don't know (yet) what *that* expands
to, perhaps to it's memory address (0x18 + 0x20). Or something ;)

Now I have to find a way to tell the c-compiler I want some of the
registers to be assigned to me and to me only, for my asm hacks.
I don't like assembler at all, but I need one very tight loop to
get the maximum possible speed. The rest will be plain C.

Thanks for the good pointers!

--
Thanks,
Frank Bemelman
We've slightly trimmed the long signature. Click to see the full one.
Re: WinAvr/GCC code problem

...
Quoted text here. Click to load it
...
Look at:
http://savannah.nongnu.org/download/avr-libc/doc/avr-libc-user-manual/FAQ.html#faq_regbind


Regards,
--
Artur Lipowski

Re: WinAvr/GCC code problem
Quoted text here. Click to load it
http://savannah.nongnu.org/download/avr-libc/doc/avr-libc-user-manual/FAQ.html#faq_regbind

Thanks! Very helpful, I hadn't found a way yet.


--
Thanks,
Frank Bemelman
We've slightly trimmed the long signature. Click to see the full one.
Re: WinAvr/GCC code problem

Quoted text here. Click to load it

That's exactly the kind of thing you should *not* do while writing
GCC extended inline assembler code.  It would defeat the purpose.

The trick is to write your inline assembly in a style that doesn't get
into the way of what the compiler is trying to do.  If you do it in
any other way, odds are you'll slow down the compiled C portions of
the code a *lot* more than you can ever hope to gain back by your
inlined assembly hacks.

Quoted text here. Click to load it

So what?  Write that part in inline assembly, *correctly* identifying
the registers you're using for input, output, and which you just
clobber internally, and that's that.  No need to trample on the
compiler's toes in the process.

--
Hans-Bernhard Broeker ( snipped-for-privacy@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Re: WinAvr/GCC code problem
Quoted text here. Click to load it

Can I send you my source-file ? ;) This is a totally weird piece
of software, never seen anything like it myself.

--
Thanks,
Frank Bemelman
We've slightly trimmed the long signature. Click to see the full one.
Re: WinAvr/GCC code problem

Quoted text here. Click to load it

There would not be all that much point to that, as I don't understand
AVR assembly.  Neither does GCC --- that's why you need all those
input/output/clobber lists in the first place.

You really should read the relevant chapter of the GCC documentation
(--> info gcc "C Extensions" "extended asm"), and if there are any
open questions left, ask the GCC and or AVR gurus about those.
--
Hans-Bernhard Broeker ( snipped-for-privacy@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Site Timeline