Pages: [1]   Go Down
Author Topic: Sketch debugging with Simple Dumping Monitor  (Read 4019 times)
0 Members and 1 Guest are viewing this topic.
Saint Petersburg, Russia
Offline Offline
Full Member
***
Karma: 2
Posts: 105
Amateur
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Simple Dumping Monitor library for ATmega168/ATmega328p-based Arduino boards allows you to dump either registers, timer states and RAM, Flash, EEPROM memories, and interrupts vectors table also.

Starting with version 0.6 simple symbolic debugger functions were added.

Being compiled, the library requires near 11 KBytes of Flash memory and requires less than 1 KByte of RAM (277 Bytes for dumpmon.pde example, 377 Bytes for dumpmonDebug.pde example).

In order to use the library, download source code archive file and unpack it into the libraries directory of Arduino IDE software. It should be libraries/DumpMon directory as the result.

At the DumpMon/Examples directory, dumpmonDebug.pde sketch could be found. This sketch shows an example how the library can be used for sketch debugging.

After both complation and uploading of the sketch are successful, open Serial Monitor window, set necessary data exchange speed (library examples use 19200 kbps). Then following commands can be used to display watching variables and control debug session.

  • ? - display help info on commands.
  • W - display the list of watches.
  • S - switch debugger to step-execution mode.
  • N - executing program until next breakpoint.
  • G - execute the sketch as usual, without breaks.
  • A - repeat last command.
  • С - continue dump output (for W command it means repeat last command).

Both commands and addresses can be entered in either high and low cases. Variable and address values are displayed and should be entered hexadecimal.

In order to use Simple Dumping Monitor library, add the library initialization function call inside setup() function of the sketch. Also watched variables shoud be added into the watches list.

Code:
#include <dumpmon.h>        // Include the library header

#define LEDPIN 13           // LED connected to the Digital 13 pin

int count = 0;              // 16-bit integer counter variable
long lcount = 0;            // 32-bit integer counter variable
char* text = "Debug";       // Text string variable

void setup() {
  pinMode(LEDPIN, OUTPUT);          // Set LED pin in Output mode
  dumpmonSetup(19200);              // DumpMon library initialization
  watch(&count, "count");           // Add integer type variable to the watch list
  watch(&lcount, "lcount");         // Add long type variable to the watch list
  watch(&text, "text");             // Add pointer to character string to the watch list
  watch(&PORTB, "PORTB");           // Add register to the watch list (Digital 13 pin corresponds to bit 5 of the Port B)
}

dumpmonSetup() function access two arguments:

  • USART serial interface data exchange speed in bits per second
  • Start mode of debugger (default is STEP_MODE, step-execution mode)

Since step-execution mode is used as default, then after reset the sketch will be executed until first breakpoint() function call. In order to make the sketch executing as usual, with no stops at breakpoints, GO_MODE should be used as second argument of dumpmonSetup() function call:

Code:
  dumpmonSetup(19200, GO_MODE);              // DumpMon library initialization

After initialization made and variables added to the watch list, breakpoints can be used by adding the breakpoint() function call with breakpoint identifier of any type accessible as Serial.print() function argument.

Code:
void loop() {
  ++count;                          // Incrementing the counters by one
  ++lcount;
  breakpoint("counters watch");     // Breakpoint
  if (count & 1)                    // Some text processing
    text = "Example";
  else
    text = "Debug";
  breakpoint("text watch");         // Another breakpoint
  if (count & 5)                    // Blinking the LED fast enough to step-by-step execution
    digitalWrite(LEDPIN, HIGH);
  else
    digitalWrite(LEDPIN, LOW);
}

After both compilation and uploading of the sketch are successul, in order to start debug session, open Serial Monitor window and set the data exchange speed equal to dumpmonSetup() function call value at the sketch. In this case it's equal to 19200.
If all is correct, Serial Monitor window displays current breakpoint info:

Code:
<0> counters watch
0158  count  0001  ".."
015A  lcoun  00000001  "...."
0140  text   "Debug"
0025  PORTB  00  "."

Enter N and press Enter key or click Send button to send this command to Arduino.

Code:
<1> text watch
0158  count  0001  ".."
015A  lcoun  00000001  "...."
0140  text   "Example"
0025  PORTB  00  "."

Now it's clear what the debugger displays. First line contains break count and breakpoint identifier. Then it displays dump of watches in following format: variable address, symbolic name, hexadecimal and ASCII value. For text string variables it displays text value in ASCII.

Let's dump RAM memory at text variable address by sending M140 command. The debugger will display dump starting from 0140 address.

Code:
Memory dump: RAM
0140  27 01 00 00 08 00 00 00 00 00 43 16 76 14 8F 14  '.........C.v...
0150  E3 15 10 16 F6 15 32 16 01 00 01 00 00 00 40 01  ......2.......@.
0160  03 03 04 00 58 01 5A 01 40 01 25 00 00 00 00 00  ....X.Z.@.%.....
0170  00 00 00 00 63 6F 75 6E 74 6C 63 6F 75 6E 74 65  ....countlcounte
0180  78 74 00 50 4F 52 54 42 00 00 00 00 00 00 00 00  xt.PORTB........
0190  00 00 00 00 00 00 00 00 00 00 00 00 01 03 FF 00  ................
01A0  00 00 00 00 02 00 01 00 00 6E 6D 31 34 30 30 00  .........nm1400.
01B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0200  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0210  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0220  00 00 00 00 00 00 00 00 00 06 00 05 00 4A 01 A9  .............J..
0230  01 C5 00 C4 00 C0 00 C1 00 C6 00 04 03 07 05 01  ................

Since text variable is a pointer to array of char type items, value 0127 is address of the string, which pointed by text variable at the moment. Let's dump it with M127 command.

Code:
Memory dump: RAM
0127  45 78 61 6D 70 6C 65 00 44 65 62 75 67 00 74 65  Example.Debug.te
0137  78 74 20 77 61 74 63 68 00 27 01 00 00 00 00 00  xt watch.'......
0147  00 00 00 43 16 76 14 8F 14 E3 15 10 16 F6 15 32  ...C.v.........2
0157  16 01 00 01 00 00 00 27 01 03 03 04 00 58 01 5A  .......'.....X.Z
0167  01 40 01 25 00 00 00 00 00 00 00 00 00 63 6F 75  .@.%.........cou
0177  6E 74 6C 63 6F 75 6E 74 65 78 74 00 50 4F 52 54  ntlcountext.PORT
0187  42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  B...............
0197  00 00 00 00 00 01 03 FF 00 00 00 00 00 02 00 01  ................
01A7  00 00 6E 6D 31 34 30 30 6D 31 32 37 00 00 00 00  ..nm1400m127....
01B7  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01C7  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01D7  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01E7  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01F7  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0207  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0217  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Then dump the watches list by W command:

Code:
0158  count  0001  ".."
015A  lcoun  00000001  "...."
0140  text   "Example"
0025  PORTB  00  "."

All is correct, string constant "Example" is stored in the RAM at 0127 address, which pointed by text variable at the moment.

Let's execute the sketch with G command. Then let's stop it with either S or N command.

Code:
<2> text watch
0158  count  2D22  ""-"
015A  lcoun  00022D22  ""-.."
0140  text   "Debug"
0025  PORTB  20  " "

Values of the counters are equal at less significant 16 bits. Most significant 16 bits of the lcount counter shows that during this time count counter became zero several times. In my case it's happen 2 times. Also text variable points to the "Debug" string and PORTB register is equal 0x20. It means the bit 5 has logic one state, so the LED should be lighting. I am looking at the Arduino board and there is it, the LED is lighting.
I send N command:

Code:
<3> counters watch
0158  count  2D23  "#-"
015A  lcoun  00022D23  "#-.."
0140  text   "Debug"
0025  PORTB  00  "."

PORTB register is zero again. The LED is off too.

Click the link below and Save As to download DumpMon
http://sites.google.com/site/vanyambauseslinux/home/fajlovyj-menedzer/DumpMon-0.7.tar.gz(17,7 Кб).

More about dumping functions of the library http://arduino.cc/forum/index.php/topic,50790.0.html

Enjoy incredibly smart Arduino debugging with Simple Dumping Monitor library! Don't use breakpoint() function inside interrupt handlers, it won't work.
« Last Edit: February 28, 2011, 09:48:09 pm by Vanyamba » Logged

Georgina Ontario
Offline Offline
Sr. Member
****
Karma: 5
Posts: 437
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vanyamba:

This looks really good. I have not tried it yet but I will.

Is there a simple way to determine how much RAM is used by a sketch? If not, it might be a good addition. I am using the Mega2560, and although it has 8KB of RAM I expect to be pushing the limit shortly.

My skill with C and C++ on a scale of 1 to 100 is about 0.1 so this should be really helpful.

It looks like you are having fun! Keep going!!!!!
Logged

Just another Hacker

Saint Petersburg, Russia
Offline Offline
Full Member
***
Karma: 2
Posts: 105
Amateur
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there a simple way to determine how much RAM is used by a sketch?

Thanks, WillR.

There's no sharp enough method to know exactly how many RAM is used by sketch, because it uses stack and dynamic allocation.
But you can to know how many RAM is used for data sections, since compiler produces both binary and hex firmware from executable file. In Linux it's  ELF format executable.
So in Linux and Arduino IDE software one can find temporary object files  at the temporary directory, when Arduino IDE is open and sketch was compiled at least once. For example:

Code:
$ find /tmp | grep mysketch

This comand can find some object and temporary source files like these ones:

/tmp/build3128765879146587932.tmp/mysketch.cpp
/tmp/build3128765879146587932.tmp/mysketch.cpp.o
/tmp/build3128765879146587932.tmp/mysketch.cpp.hex
/tmp/build3128765879146587932.tmp/mysketch.cpp.elf

If it's found, ELF executable can be dumped with avr-objdump tool:

Code:
$ avr-objdump -h /tmp/build3128765879146587932.tmp/mysketch.cpp.elf

The -h key dumps section headers and its sizes. For example:

Code:
/tmp/build3128765879146587932.tmp/mysketch.cpp.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         0000001c  00800100  00000b56  00000bea  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00000b56  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          000000a3  0080011c  0080011c  00000c06  2**0
                  ALLOC
  3 .stab         00006b7c  00000000  00000000  00000c14  2**2
                  CONTENTS, READONLY, DEBUGGING
  4 .stabstr      00007512  00000000  00000000  00007790  2**0
                  CONTENTS, READONLY, DEBUGGING

Both .bss and .data sections are located at RAM when sketch is running. The .text section contains program code.
0x1c + 0xa3 = 191 bytes of RAM required in this case. Plus some RAM for stack.
Logged

Portugal
Offline Offline
God Member
*****
Karma: 5
Posts: 962
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or just use avr-size and pass the .elf file to it.
Logged

Saint Petersburg, Russia
Offline Offline
Full Member
***
Karma: 2
Posts: 105
Amateur
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Show available RAM function added in version 0.7.

http://sites.google.com/site/vanyambauseslinux/home/fajlovyj-menedzer/DumpMon-0.7.tar.gz
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This old thread popped up in a Google search for debugging on the Arduino.  Here's what looks to be the site where this project is now hosted:
http://sourceforge.net/p/dumpmon/wiki/Home/

Very cool stuff!  Thanks!
Logged

Pages: [1]   Go Up
Jump to: