As every SW developer knows, it's very helpful to have a good tool to debug the SW. Unfortunately the base Arduino IDE hasn't much utilities to debug your sketch. In order to improve it I created a tool that allow, by the USB, to see (and modify) at runtime the SW variables while the program is running on the Arduino board.
Basically this feature is more or less an “hack” of Arduino compiler and memory management in Arduino. Using the compiled files (.elf), I get the memory address of variables used in the sketch. After, with this information, I created a serial communication that allow me to read and write any statically allocated variable on the Arduino SW. To do that, it’s necessary a tool to install on PC and a little library to add to Arduino sketch.
Step 1: Get Sketch Memory Map
For any Avr-like Arduino board, it’s used the same builder. This builder, when you launch a build and download of a sketch on the board, create many intermediate files. One of them is the .hex file (that is the effective compiled program written in the Arduino FLASH), another one, not used during the download but very helpful for our aim is the .elf file. This file is normally used by the debuggers in order to make a debug step by step. It has many information and one of them if the full memory map: exactly what we need for your application.
So, the first step is to obtain the .elf file. Normally the Arduino IDE created the files in a temporary folder (hard to find), but we can force it to use a known folder. Opening the menu -- > file -- > option we have a window with all configuration info of the builder and, at the end, the link file to preferences files. Opening the file preferences.txt we can change the deep Arduino builder configurations. In this case we add a new option (writing a line at the end of file) that force the builder to use a known folder for temporary build files:
After this change and a rebuild, we should found many files in the chosen folder: one of them is the .elf file:
NOTE: all changes on the preferences file must be made while the Arduino.exe is closed, otherwise it will rewrite the file with original configuration.
Now, starting from elf file we can extract the .map file using launching avr-objdump.exe (already present in Arduino IDE installation path) with follow command:
"ARDUINO EXE PATH\hardware\tools\avr\bin\avr-objdump.exe" -t "ELF PATH">> "C:\myfolder\mapfile.txt"
Opening the generated mapfile.txt with a text editor, we can found many lines with a lot of information about the usage of FLASH and memory. Between the lines there are the addresses and the sizes of all used statically allocated variables:
00000596 g F .text 00000076 init
00000068 g .text 00000000 __ctors_start
0080012a g O .bss 00000004 counter
00000078 g .text 00000016 .hidden __do_copy_data
the lines with variables info are identified in follow way:
fisical_address_in_memory g O .bss size_variable name_variable
Step 2: PC Graphical Interface
I created a PC tool (using C# language) that automatize all operation before described and provide to establish a serial communication and graphical interface to read-write variables. The tool to work needs of follow information:
- The path of Arduino.exe file (menu file-->configuration)
- The path of Arduino Ide preferences (menu file --> configuration). Take care that when you set this path the Arduino.exe shall be closed because the program need to change the file in order to add build path option (as described before). Setting a correct path, the program will create a backup copy of the file and after add the line to force the build in a known internal path.
After configured the correct path, it’s necessary to set the COM port of Arduino USB serial and connect. The tool will do automatically all action described in previous paragraph and after a parsing of generated map file, will give a list of all variables found.
After a double click of one of variables , it will ask how interpret the variables i.e like a int, or a byte or a string etc.. This operation it’s necessary because unfortunately at moment from memory map is possible to have only address and size of variable and not his type. After clicking ok, the tool will create a serial communication with Arduino in order to get continuously his real time value. The variable will appears in watch list with his value periodically updated. It’s possible to add in watch till 5 variables at same time.
Doing a double click on one of watch variables, its’ possible to have a graphical view of it and, if you want to force it to a new value.
The link to binary and full C# project of the graphical interface it's here:
Don't need installation (the only requirement is to have framework 4.0 or more installed): just copy the full binary folder and launch the .exe
Step 3: Arduino Library
To make effective the communication it’s necessary to add to your sketch a library and after created the “DEBUGSERIAL” object to call two function:
- Init: to call once in Setup that will configure internal variables and communication
- Run: to call continuously in Loop function. This function will provide to manage the serial communication with the PC Not specification about the frequency, just take care that the Arduino will interact with PC only when this function it’s called (for a high update rate, it’s necessary an high frequency of call of this function).
The protocol used is quite simple and structured in order to reduce the number of transmitted bytes. Any data is transmitted in pure binary and the single messages is done in this mode:
0xFF 0x02 ….. data bytes …. 0xFF 0x03
To avoid ambiguity to detect begin and end of messages if in the data are present an escape character ( 0xFF ) it’s transmitted twice:
0xFF 0x02 0x00 0xFF 0xFF 0x03 -- > 0xFF 0x02 0x00 0xFF 0xFF 0xFF 0x03
The basilar messages from PC to Arduino begin with a character that define the type of message and some byte specialized for type of message. The messages sent at moment are:
- ‘V’: send the list of required variables (address and size for each)
- ‘R’: set the rate of transmission
- ‘F’: force a value of a variable at required address
When a request of a list of variables, periodically for each variable the SW will point directly the address and return back the content for a number of bytes equal to required.
Here a sample code for a test (you can found it in file --> examples --> ardudebug after installing the library):
// some dummy variables (to debug)
float counter = 0;
// create the object to manage serial debug communication
// the setup routine runs once when you press reset:
// init the serial debugger
// init string
// the loop routine runs over and over again forever:
// manage the serial debug communication
// some dummy operation on variables to test counter = counter + 1;
if (counter >= 1000)
counter = 0;
// delay for stability
The link of Arduino library source code, installation package and example sketch can be found here:
Step 4: Status of Art and Improvement
This tool was very helpful for my development and debug of Arduino sketch. To see directly and with an high rate any SW variables (without stop and use other strategy like to send serial log string message) allow a quick check of feature or, why not, use it as a quick way to have a PC interface for your sketch.
There are anyway some limitation:
- Obviously it’s possible to see only static variables (i.e global variables). To check a dynamic allocated variable it’s necessary to copy it in a dummy global defined. NOTE: take care that sometime if the compiler detect a variable never used (i.e only declared and initialized) it will not include it in the compiled file: in this case it will not appears in the variables list
- The biggest limitation at moment is that I’m not able to understand the type of variables. So there are some limitation like to don’t manage complex variables like structures or objects (they can be see but only like a byte array). This limitation shall avoid in future with a parsing of the code. Someone know a good meta-compiler that should give me types information?
- At moment it works only for avr-like architectures (i.e. not Edison or 101 that have a OS Linux).
- I'm thinking to adapt the graphical interface as a general purpose PC logger/viewer for Arduino: you just create the program, without worries about communication issue or customization (simply add the library calls) and after configure the tool to log and plot on PC any variable you want. you could select one or more data or change what you want to see without modify the sketch: easy, isn't?
- May be there are necessary some improvements and bug fixes: I tested it by myself only with Arduino 1.6.9 and a Arduino UNO: each notification of bug or suggestion to improve it will be appreciated!
Think, create and have fun!