I trying since a few days to write a very simple inline assembler code, but nothing worked. I have as IDE NetBeans and as compiler MinGW. My latest code is:
uint16 readle_uint16(const uint8 * buffer, int offset) {
unsigned char x, y, z;
unsigned int PORTB;
__asm__ __volatile__("\n"
"addl r29,%0\n"
"addl r30,%1\n"
"addl r31,%2\n"
"lpm\n"
"out %3,r0\n"
: "=I" (PORTB)
: "r" (x), "r" (y), "r" (z)
);
return value;
}
But I get everytime the same message "error: impossible constraint in 'asm'".
I tried to write all in a single line or to use different asm
introductions. I have no idea what I can do otherwise.
As EOF says, the
I
constraint is used for parameters that are constant (see the AVR section at https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html). By putting this parameter after the first colon (and by using an=
), you are saying this is an output. Outputting to a constant makes no sense.Also:
x
,y
, andz
as inputs to the asm (by putting them after the second colon), but they never get assigned a value. An input that has never been assigned a value makes no sense.There's more, but I just can't follow what you think this code is supposed to do. You might want to take some time to look thru the gcc docs for asm to understand how this works.
Notice that gcc's inline assembly syntax is
After the assembler instructions first come the output operands, then the inputs.
As @DavidWohlferd said,
I
is for "constant greater than −1, less than 64 "constants ("immediates").While the
out
instruction in fact requires a constant value from that range,PORTB
is not that constant value. (You can see that for yourself if you look into the correspondingavr/ioXXXX.h
file for your controller, where you may find something like#define PORTB _SFR_IO8(0x05)
.)Also, not all IO registers may be accessible via
out
/in
; especially the bigger controllers have more than 64 IO registers, but only the first 64 can be accessed as such. However, all IO registers can be accessed at their memory-mapped address throughlds
/sts
. So, depending on which register on which controller you want to access you may not be able to useout
for that register at all, but you can always usests
instead. If you want your code to be portable you'll have to take that into account, like suggested here for example.If you know that
PORTB
is one of the first 64 IO registers on your controller, you can use"I" (_SFR_IO_ADDR( PORTB ))
without
, else use"m" ( PORTB )
withsts
.So this:
should get you rid of that "impossible constraint" error. Although the code still does not make any sense, mostly because you're using "random", uninitialized data as input. You clobber registers r29-r31 without declaring them, and I'm totally not sure what your intention is with all the code before the
lpm
.