Inline ASM with PORT Definitions

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When working in Assembly in in the AVRGCC realms, I know that to load a port I can simply run:

sts	PORTA_OUT, R21

In C, if I load a port value it is disassembled into:

ldi     R24, 0x50
sts     0x0604, R24

If I try to run an inline asm command in c:

asm("sts PORTA_OUT, R21");

I get an error "undefined reference to". I see that the disassembled code places the actual address for the port in place as I would expect. Is there a way to have the asm instruction understand the "PORTA_OUT" definition, or will I also have to place the address definition?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try this:

http://nongnu.org/avr-libc/user-...
section "How do I use a #define'd constant in an asm statement?"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can

#include 

void out_port (uint8_t out)
{
    asm volatile ("sts %0,%1" : "=m" (PORTA) : "r" (out));
}

or, with a current tool chain

#include 

void out_port (uint8_t out)
{
    asm volatile ("out %i0,%1" : "=m" (PORTA) : "r" (out));
}

And you can use the address of PORTA, of course:

#include 

void out_port (uint8_t out)
{
    asm volatile ("sts %0,%1"
                  :: "i" (&PORTA), "r" (out) : "memory");
}

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the help.

Watchmaker, I did see the manual, but when trying to run:

asm volatile("sbi %0, 0x07" : "I" (_SFR_IO_ADDR(PORTB)):);

I would get errors related to "lvalue required" and "output operand constraint lacks '='". After researching the error I found no solutions that would work.
SprinterSB, your examples were perfect. I was able to accomplish what I wanted with the following three variations:

asm volatile ("sts %0,r18" : "=m" (PORTA_OUT));
asm volatile ("sts %0,r18" :: "i" (&PORTA_OUT));
asm volatile ("sts %0,r18" :: "i"(_SFR_IO_ADDR(PORTA_OUT))); 

From this I have three related questions.

First, why a lowercase “i”. In all manuals and instructions I only saw defined an uppercase “I”.

Second, I found that I can access the address in the end with both “&” and “_SFR_IO_ADDR”. Is there a time I would only use _SFR_IO_ADDR? I saw it in various examples for straight ASM (in the avrgcc .s file) as well, but did not see why.

Finally, I also found when dealing with addressing examples that using the following snippet of code at the top to correct offsets. Is this required?

#define _SFR_ASM_COMPAT 1  /* Not sure when/if this is needed */
#define __SFR_OFFSET 0

P.S. Man that was annoying learning that the forums did not like percent signs

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Most of SprinterSB's posts have a signature with a link to this:

http://www.rn-wissen.de/index.ph...

(not sure why his post above is not showing the sig?).

Oh and use Google Translate if you don't speak German. I found what Google comes up with to be fairly OK to follow the sense of what's being said.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks. That has helped greatly.