How can I debug applications ?

Hi all,

I am new at the Arduino platform and have my first questions. How can I debug my application. Is there a possibility to set breakpoints or watch the variables on the running application. Ho can I find errors in my programms. Is there an interface on the hardware to debug the application like JTAG or debugwire?

Thanks in advance for your help.

BR stephan0607

Hi stephan0607,

Without any knowledge about JTAG or debugwire i use the serial connection and (a lot of) Serial.print statements to debug my sketches.

Hope it helps.

Jeroen

Sometimes I use this: Arduino Playground - HomePage

Or, I might use simple LEDs to signal changes and such.

I'm with Yot. I usually put some serialPrint(some_value) in various places in my code so I can see if it is doing what it's supposed to be doing. Helps a lot.

Hi again,

There are a couple downsides (more like 'properties') to using serialprint statements. It takes time (sometimes relatively alot) to serial.print something. So in fast/small loops the serial.print command takes more time than the rest of the loop.
The serial.print statement returns to the rest of the program after the last byte is placed in send buffer. Not after the last byte is send. So before you get the last byte from a serial.print on your terminal there could be something else happening in your program. This part is explained in the reference.

I'm a new to arduino aswell, so, anything i wrote could be wrong/incomplete (but not by intention). Please keep on thinking for yourself. :slight_smile:

Have fun,

Jeroen

You are completely right. There are times when adding serial.print statements will throw off the timing of a block of code. For instance, reading data sent by another serial device. Or when responding to an interrupt.

Knowing that serial.print returns after having buffered, but not necessarily sent, the last byte can be worked around by printing and extra character after the data that "needs" to be sent.

In the cases where timing is critical, one needs to use other techniques. Serial.prints before and after the time-critical sections, and peer-review of the code are useful techniques.

I use the Serial.print as well. But often I do not use it directly but with this

void hex_dump(void* pointer) {    
    hex_dump_n(pointer, 24);   
}

void hex_dump_n(void* pointer, int n) {    

    if ((int) pointer <  0x10) { Serial.print("0"); }
    if ((int) pointer < 0x100) { Serial.print("0"); }

    Serial.print((int) pointer, HEX);
    Serial.print(": ");
    for (int i = 0; i< n; i++) {                
        Serial.print((*(((uint8_t *) pointer)+i) >> 4) & 0xF, HEX);
        Serial.print(*(((uint8_t *) pointer)+i) & 0xf, HEX);
        Serial.print(' ');
    }

    for (int i = 0; i< n; i++) {            
        if ((*((uint8_t *) pointer+i) >= 0x20) && (*((uint8_t *) pointer+i) <= 0x7F)) {
            Serial.print(*((char *) pointer+i));
        }
        else { 
            Serial.print('.');
        }
    }
    Serial.println(' ');
}

This is because that I sometimes want to know what is going in the memory around my variables. Especially if I suspect that I have some buffer overflows.

hi Udo Klein,

If possible, could you give a small sketch on how to use that? I'm a bit confused in what is does. Not even mentioning how it does it.

thanks,

Jeroen

Here you go. It’s a pretty pointless example for a 324 processor. You can see how the variables i and s are treated completely different in memory (as expected). You can also see that the “constant” string is actually stored in Ram, just as the labels.

The blinking LED code is only in place to have some delay and some visual confirmation that this code actually runs.

void label_dump(char* label) {
    static uint8_t count = 0;

    Serial.print(count, HEX);
    Serial.print(": ");
    Serial.println(label);
    ++count;
}

void hex_dump(void* pointer) {    
    hex_dump_n(pointer, 24);   
}

void hex_dump_all() {    

    // attention: 72 is the magic number for 324, 168 or 644 have different memory sizes
    for (int chunk = 0; chunk < 72; ++chunk) {
        hex_dump_n((uint8_t *)NULL+(32*chunk), 32);
    }
    Serial.println("");
}

void hex_dump_n(void* pointer, int n) {    

    if ((int) pointer <  0x10) { Serial.print("0"); }
    if ((int) pointer < 0x100) { Serial.print("0"); }

    Serial.print((int) pointer, HEX);
    Serial.print(": ");
    for (int i = 0; i< n; i++) {                
        Serial.print((*(((uint8_t *) pointer)+i) >> 4) & 0xF, HEX);
        Serial.print(*(((uint8_t *) pointer)+i) & 0xf, HEX);
        Serial.print(' ');
    }

    for (int i = 0; i< n; i++) {            
        if ((*((uint8_t *) pointer+i) >= 0x20) && (*((uint8_t *) pointer+i) <= 0x7F)) {
            Serial.print(*((char *) pointer+i));
        }
        else { 
            Serial.print('.');
        }
    }
    Serial.println(' ');
}

void free_dump() {
  
  uint8_t *heapptr;
  uint8_t *stackptr;

  stackptr = (uint8_t *)malloc(4);   // use stackptr temporarily
  heapptr = stackptr;                // save value of heap pointer
  free(stackptr);                    // free up the memory again (sets stackptr to 0)
  stackptr =  (uint8_t *)(SP);       // save value of stack pointer

  Serial.print("HP: ");
  Serial.println((int) heapptr, HEX);
  Serial.print("SP: ");
  Serial.println((int) stackptr, HEX);
  Serial.print("Free: ");
  Serial.println((int) stackptr - (int) heapptr, HEX);
  Serial.println("");
}

const int ledPin =  13; 

void setup() {  
  Serial.begin(115200);
  Serial.println("this is a test!");
  label_dump("label l1");
  hex_dump_all();
  free_dump();
  
  pinMode(ledPin, OUTPUT);   
}

void loop() {
  int i = 0;
  static int s = 0;
  hex_dump((void *)"this is a test");
  hex_dump(&i);
  hex_dump(&s);
  i++;
  s++;
  hex_dump(&i);
  hex_dump(&s);
  Serial.println(i);
  Serial.println(s);
  
  label_dump("label l2");
  digitalWrite(ledPin, HIGH);   // set the LED on  
  delay(1000);                  // wait for a second
  digitalWrite(ledPin, LOW);    // set the LED off
  delay(1000);                  // wait for a second
  
  
}

Thanks Udo Klein for your response.

At this moment i don't know how or why i should use this code and that has something to do with my lack of knowledge, but thanks for sharing.

Jeroen

i don't know how or why i should use this code

Don't worry, it is very much "overkill" for beginning debugging. Serial.print is the best place to start for debugging simple (and complex!) applications, I would say. You can move on to more sophisticated ones when the need manifests itself.

If you are looking for an general guide on debugging that is suitable for beginners you might want to have a look at

http://www.debuggingrules.com/Get_the_book.html

I liked it very much. Most experts will know the content implicitly but this book is very good to the point.

I know what to get/ask for christmas. The excerpts were a nice reading.

You can move on to more sophisticated ones when the need manifests itself.

Hmm. That scares me a little. ;D Especially after the reading of the debugging rules poster.

Thanks for the link,

Jeroen

With regard to Andy's comment: I consider it underkill. Measured by today's standards an overkill is something like this:
http://www.lambdacs.com/debugger,
http://video.google.com/videoplay?docid=3897010229726822034 :slight_smile:

mamma mia!

And one more: right now I am very frustrated searching a bug. I already refrain to avr-objdump -d -s sketch.elf. But I agree this is something most people will not do :slight_smile:

By chance I found the arduino shell:

http://biot.com/arsh/

I think for some debugging purposes this might be helpful as well. Especially in cases where you do not know if the issue is caused due to hardware or due to software.

I did not yet try it though.

Fascinating, especially the video. Not that i understand most of the technical stuff but the concept of logging everything is great.

Not restricted by any knowledge on the subject; Why don't all debuggers work that way. :slight_smile:

Jeroen

Because the data volumes are unbelievable high. Debugging one second of an Arduino would create > 16 Mbytes of data.
Actually one statement can affect program counter, stack pointer, some ram and/or ports, some register and the arduino includes some independent running timers --> actual rates would be probably beyond 50 MBytes per second.

Debugging one second of a modern PC CPU would create >8 Gigabytes of data per second, not including DMA. Of course you can compress it and you can slow down the CPU in order to ease the bandwidth requirements, but suppose you would need to debug for more than some seconds ...

Still impressive though.