atmega: register data gets corrupted by division operation

48 views Asked by At

Hello I'm writing in C with an olimexino (arduino). I'm using the following code to load 2 registers (atmega328):

asm (
"ldi r20, 0 \n" //load register r20 with 0
"ldi r21, 16 \n" //load register r21 with 16
: : : "r20","r21" //compiler directive to reserve the two registers );

then I use this:

asm ( "out 0x05, r21 \n" ); //write '0' to portB
asm ( "out 0x05, r20 \n" ); //write '10000' to portB

to write from the two registers to port B. But using the two registers r20 and r21 creates a problem. A conflict occurs if i do a division operation. for example, if any part of my program has a statement like "x = x/6" or "y=x%9" then the numbers i stored in those registers seem to change. if i do a simple division like "x/4" or "x%8" there's no problem. but any operation that's more complex than a simple shift division screws me up.

Any help? Thanks

1

There are 1 answers

0
David Wohlferd On

Do it as a single, multi-line statement:

asm (
"ldi r20, 0 \n" //load register r20 with 0
"ldi r21, 16 \n" //load register r21 with 16
"out 0x05, r21 \n" //write '0' to portB
"out 0x05, r20 \n" //write '10000' to portB
: : : "r20","r21" //compiler directive to reserve the two registers );

Or perhaps even better:

asm (
   "out %0, %1 \n"
   "out %0, %2 \n"
   : : "i"(5), "r"(16), "r"(0));

Or how about a routine:

void WriteToPort5(unsigned char b)
{
   asm ("out 0x05, %0"
   : : "r"(b));
}

That you can call like this:

WriteToPort5(16);
WriteToPort5(0);