November 08, 2024, 09:03:33 PM

UNBELEIVABLE software glitch

Started by mikewax, December 22, 2016, 05:25:46 AM

Previous topic - Next topic

mikewax

OK here's something that i doubt anyone has seen before. here's a routine to toggle pin D12 off and on using the Arduino 1.6.12 IDE and an Olimexino 328. I'm using assembly code to do it because this method is the fastest way to toggle a pin. the instruction "asm ( "out 0x05, r21 \n" );" executes in a single clock cycle.

int x;

void setup() {
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
);
pinMode(12,OUTPUT); // port B, pin 4
}

void loop() {
if (x%8 == 0) x = 0;
asm ( "out 0x05, r21 \n" ); //write '0' to portB
delay(1000);
asm ( "out 0x05, r20 \n" ); //write '10000' to portB
delay(1000);
}


you'll notice that the statement "if (x%8 == 0) x = 0;" is completely extraneous, it's only there for the purpose of demonstration.
the UNBELIEVABLE part is that when i replace the number 8 in that statement with a 9 or larger number, the output on pin 12 stops working.
it would be nice if someone else could test this on a 328 to see if they get the same result.

jmyreen

There can be quite a difference in the code the compiler produces if the argument to the % operator is a power of two or not. If you do a (x%8), the compiler can implement it with a simple AND instruction, but if you do a (x%9), the compiler probably generates a call to a division subroutine. Maybe the subroutine is buggy, and never returns?

mikewax

yes i believe that's it. it seems that if i'm gonna use any of the atmega's core registers then my code's gonna screw up wherever i have a division operation that goes beyond a simple shift right.
this is just *&!%ed up. according to gcc documentation i'm supposed to be able to use some of these registers. now it looks like i can't.