d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > Question For Hardcore Coders ;) > 8bit And 16bit, Avr-gcc, Atmega32u4
Add Reply New Topic New Poll
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Nov 28 2012 11:13am
Hi, here the important code-lines of my code:

Code
 7 uint16_t total=0, temp=0;
 8 uint8_t bufs[64];
 9 uint8_t bufr[64];
...
17   while (1) {
18     if (usb_recv(bufr) == 64) {
19 #if 1 //depending on this if, the result of bufs[0] will eventually be 0x01 or 0x02... why?
20       total = (((uint16_t)bufr[0]) << 8) + ((uint16_t) (bufr[1] & 0xFF));
21 #endif
22       temp = (((uint16_t)bufr[0]) << 8); //temp is 0x02
23       bufs[0] = temp >> 8;
24       bufs[1] = (((uint16_t)bufr[0]) << 8) >> 8; //send back high byte of temp calculated without temporary variable. works


you also need to know that bufr[0] is 0x02 right after the usb_recv(), where bufr[i] is zero (for all i higher than zero)

As you can see, I casted the 8-bit variables to 16-bit ones BEFORE i move them 8 bits to the left. So you can't tell me that this is the mistake... :)
My question is the "why?" which you can find in the code. note that the variable total is never used, but if i calculate it the bufs[0] will be eventually 0x01 and thus incorrect...

(bufs[1] is correctly calculated, and thus 0x02)



(i got no jtag adapter, so i can't debug it)
use your brain and help me ;)
Member
Posts: 4,605
Joined: Sep 15 2011
Gold: 9,464.00
Nov 28 2012 01:05pm
Question for clarification: do you mean that, the given code above, if line 20 is removed, the result of line 23 is bufs[0] --> 0x02? and that if line 20 is in there, the result of line 23 is bufs[0] --> 0x01?

Also, would you mind showing the compiled code for the #if block as well? That could at least show you what's happening in that line of code.

This post was edited by irimi on Nov 28 2012 01:07pm
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Nov 28 2012 01:56pm
Quote (irimi @ 28 Nov 2012 20:05)
Question for clarification: do you mean that, the given code above, if line 20 is removed, the result of line 23 is bufs[0] --> 0x02?  and that if line 20 is in there, the result of line 23 is bufs[0] --> 0x01?

yes exactly :)

Quote (irimi @ 28 Nov 2012 20:05)
Also, would you mind showing the compiled code for the #if block as well? That could at least show you what's happening in that line of code.

the compiled code for the "#if 1" block is the one on the right side, while the compiled code for "#if 0" is on the left side (one image for both, made it with vimdiff)
Member
Posts: 4,605
Joined: Sep 15 2011
Gold: 9,464.00
Nov 28 2012 03:21pm
The assembly looks right on both sides.

On the LHS, it basically treats your shifts as no-ops: loading the value of bufr[0] into r24 and putting it in the high bits of temp at 0x0103, and storing a bunch of zeros in the low bits of temp at 0x0102, and when you assign bufs[0] to the right shift of temp, it says "oh, but that's just the high bits of temp, which we just got from r24".

On the RHS, the result of the IF statement basically puts the value of the 16-bit, left-shifted bufr[0] into the segmented registers r28 and r29, so when you call temp = blah... , the compiler realizes this and directly writes the values of r28 and r29 into the memory address of temp (0x0102-0x0103). So when you assign bufs[0] to the shifted temp, ***it copies registers r28-r29 into registers r14-r15 and then stores the high bits (in r15) to bufs[0] (at 0x0147).***

A couple thoughts:

1) Are you correctly reading the output? Maybe the above code works fine, but there's a bug in the code that looks at this stuff.

2) Assuming that there IS a bug, it might possibly be from the ***-enclosed sentence. According to the Atmega32u4 spec, r14 and r15 are not segmented registers, so I'm actually a little confused as to how the movw from r28 to r14 actually works. It could be possible that the mov doesn't actually do the right thing, and you're storing the garbage from r15 into the lower bits of bufs[0] -- in this case, it happens to be 0x01.


Also, isn't your comment on the temp = statement wrong? Assuming bufr[0] is 0x02, shouldn't temp be 0x20 after the shift?

This post was edited by irimi on Nov 28 2012 03:30pm
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Nov 29 2012 12:35pm
Quote (irimi @ 28 Nov 2012 22:21)
On the LHS, it basically treats your shifts as no-ops:  loading the value of bufr[0] into r24 and putting it in the high bits of temp at 0x0103, and storing a bunch of zeros in the low bits of temp at 0x0102, and when you assign bufs[0] to the right shift of temp, it says "oh, but that's just the high bits of temp, which we just got from r24".

i agree with that

Quote (irimi @ 28 Nov 2012 22:21)

1) Are you correctly reading the output?  Maybe the above code works fine, but there's a bug in the code that looks at this stuff.

may be, but i've tried a lot of different methods to check if that is actually the problem. when i simplify the surrounding code (as example, if i set "buf[0]=1;") then the compiler compiles different (then he is more lucky to do it correctly)

Quote (irimi @ 28 Nov 2012 22:21)

2) Assuming that there IS a bug, it might possibly be from the ***-enclosed sentence.  According to the Atmega32u4 spec, r14 and r15 are not segmented registers, so I'm actually a little confused as to how the movw from r28 to r14 actually works.  It could be possible that the mov doesn't actually do the right thing, and you're storing the garbage from r15 into the lower bits of bufs[0] -- in this case, it happens to be 0x01.

hmm, i haven't found that in the datasheet i looked at before. it just said those are "general registers"... i guess that this isn't the problem :)

Quote (irimi @ 28 Nov 2012 22:21)

Also, isn't your comment on the temp = statement wrong?  Assuming bufr[0] is 0x02, shouldn't temp be 0x20 after the shift?

yep, you're right, actually it should be 0x0200

i guess the problem is already earlier... here my thoughts:

1) r15 must have a wrong value, else there is no way the output could be wrong
2) the value of r15 is the value of r29 (the "movw r28 r14" does this... or should do it :) )
3) the line where r29 is changed right before that is the "movw r28 r24"-command. so r29 is just the copy of r25
4) r25 is never set... the "ldi r24, 0x00" is just a one-byte clearing...
it's possible that i'm wrong, but right now i'm quite convinced ^^... what do you think? does my theory make sense?
Member
Posts: 4,605
Joined: Sep 15 2011
Gold: 9,464.00
Nov 29 2012 01:20pm
The spec sheet here: http://academy.cba.mit.edu/classes/embedded_programming/doc7766.pdf

says specifically that the six segment registers are r26-r31.

movw r28 r14 should in theory zero out r29, because you're moving from an 8-bit register to a 16-bit segment register.

This post was edited by irimi on Nov 29 2012 01:24pm
Go Back To Programming & Development Topic List
Add Reply New Topic New Poll