Author Topic: Help me understand this debugger behavior.  (Read 2133 times)

0 Members and 1 Guest are viewing this topic.

Offline Dan MoosTopic starter

  • Frequent Contributor
  • **
  • Posts: 357
  • Country: us
Help me understand this debugger behavior.
« on: September 10, 2016, 07:06:47 pm »
I just got an AVR Dragon, and I'm messing with debugWire.

I'm using Atmel Studio 7 and an atmega328. All seems to be working well, although the hassle of switching between debugwire and programming mode is a bit annoying. My understanding is that that is a common complaint, so I won't go on about that.

Anyway, here is the simple code snippet in question. I put an 'X' where debugger breakpoints are.

While(1)
      {
X        PORTB = 0b00000001;
          _delay_ms(500);
X        PORTB = 0b00000000;
          _delay_ms(500):
       
X        PORTB = 0b00000001;
          _delay_ms(500);
X        PORTB = 0b00000000;
          _delay_ms(500):
       }

Ok, here's what happens when I run the debugger. On the first pass through the while loop, execution stops at every breakpoint, the LED attached to the relevant pin does what I expect, and the IO port view window tells me what I expect. All is good.

But on every subsequent pass through the loop, the first breakpoint is ignored, and execution stops at the second one. It is only this one breakpoint that gets skipped. I made sure it was a generic, conditionless breakpoint like the others. In my first version, the redundant second half of the routine didn't exist. I added that to see if the behaviour had something to do with the code. The second half of the routine's breakpoints work as expected.

So why would a breakpoint only work on the first pass through a loop?

The only parameter I'm not super comfortable with is the clock speed I set the Dragon's interface to run at. I know it's supposed to be less than 1/4 of the target's clock speed, but that leaves allot of possibilities. Is there a more specific rule of thumb here? Is this possibly relevant to my issue? I'm running on the MCU's internal 8 mghtz clock btw.

Finally, is there a way in atmel studio with debugWire to execute the code one statement at a time with a keypress, regardless of breakpoints?
 

Offline obiwanjacobi

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Help me understand this debugger behavior.
« Reply #1 on: September 11, 2016, 06:23:58 am »
I always look at the .lst file to see what the compiler made of my code when I see the debugger jump around. The debugger follows asm not C/C++... It may help to turn down/off optimization (-O flags)...

[2c]
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline jcosper

  • Contributor
  • Posts: 15
  • Country: us
Re: Help me understand this debugger behavior.
« Reply #2 on: September 17, 2016, 03:12:27 am »
It's hard to tell, but the first stop is to look at the disassembler. That should give an idea of what is actually happening. I have seen the assembly match the functionality, but not what was written in the higher language. The optimizations would also mess with this, as suggested above.
 

Offline tatus1969

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: de
  • Resistance is futile - We Are The Watt.
    • keenlab
Re: Help me understand this debugger behavior.
« Reply #3 on: September 17, 2016, 07:49:37 am »
+1 to disable all optimizations.
We Are The Watt - Resistance Is Futile!
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: Help me understand this debugger behavior.
« Reply #4 on: September 17, 2016, 10:18:21 am »
+1 to disable all optimizations.

Definitely.
Look at the compiler output with -O3:
Code: [Select]
00000372 <main>:
 372: c1 e0        ldi r28, 0x01 ; 1
 374: c5 b9        out 0x05, r28 ; 5
 376: 64 ef        ldi r22, 0xF4 ; 244
 378: 71 e0        ldi r23, 0x01 ; 1
 37a: 80 e0        ldi r24, 0x00 ; 0
 37c: 90 e0        ldi r25, 0x00 ; 0
 37e: 0e 94 80 01 call 0x300 ; 0x300 <_delay_ms>
 ...8< 8<....
 39e: 15 b8        out 0x05, r1 ; 5
 3a0: 64 ef        ldi r22, 0xF4 ; 244
 3a2: 71 e0        ldi r23, 0x01 ; 1
 3a4: 80 e0        ldi r24, 0x00 ; 0
 3a6: 90 e0        ldi r25, 0x00 ; 0
 3a8: 0e 94 80 01 call 0x300 ; 0x300 <_delay_ms>
 3ac: e3 cf        rjmp .-58      ; 0x374 <main+0x2>
and note the target of the jump in the last line: since the value of r28 is known, the compile will skip the load.
The breakpoint is set to the beginning of the equivalent C line, but the loop will jump right "in the middle".

With -O0 the jump is at the beginning of the C line (and note the bloat for the port operation...):
Code: [Select]
       PORTB = 0b00000001;
 3a2: 85 e2        ldi r24, 0x25 ; 37
 3a4: 90 e0        ldi r25, 0x00 ; 0
 3a6: 21 e0        ldi r18, 0x01 ; 1
 3a8: fc 01        movw r30, r24
 3aa: 20 83        st Z, r18
        _delay_ms(500);
 3ac: 64 ef        ldi r22, 0xF4 ; 244
 3ae: 71 e0        ldi r23, 0x01 ; 1
 3b0: 80 e0        ldi r24, 0x00 ; 0
 3b2: 90 e0        ldi r25, 0x00 ; 0
 3b4: 0e 94 80 01 call 0x300 ; 0x300 <_delay_ms>
...8< 8<...
        PORTB = 0b00000000;
 3e2: 85 e2        ldi r24, 0x25 ; 37
 3e4: 90 e0        ldi r25, 0x00 ; 0
 3e6: fc 01        movw r30, r24
 3e8: 10 82        st Z, r1
        _delay_ms(500);
 3ea: 64 ef        ldi r22, 0xF4 ; 244
 3ec: 71 e0        ldi r23, 0x01 ; 1
 3ee: 80 e0        ldi r24, 0x00 ; 0
 3f0: 90 e0        ldi r25, 0x00 ; 0
 3f2: 0e 94 80 01 call 0x300 ; 0x300 <_delay_ms>
    }
 3f6: d5 cf        rjmp .-86      ; 0x3a2 <main+0x8>
Nandemo wa shiranai wa yo, shitteru koto dake.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf