In this post I will try to describe how to dump memory contents of en embedded system and plot them using Gnuplot or some other program. To dump the memory I will connect to the target with openOCD and GDB debugger.
All of the above operations can be done with a simple script. My target platform will be STM32F105 microcontroller.
1. To get started We will need to connect to the target with openOCD. It can be done from the console or from IDE such as eclipse.
Here is the command that I'm using and the openOCD output:
>openocd -f interface/ocd.cfg -f target/stm32f1x.cfg Open On-Chip Debugger 0.5.0 (2011-08-09-23:21) Licensed under GNU GPL v2 For bug reports, read http://openocd.berlios.de/doc/doxygen/bugs.html Info : only one transport option; autoselect 'jtag' 3000 kHz 3000 kHz adapter_nsrst_delay: 100 jtag_ntrst_delay: 100 cortex_m3 reset_config sysresetreq Info : clock speed 3000 kHz Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) Info : JTAG tap: stm32.bs tap/device found: 0x06418041 (mfg: 0x020, part: 0x6418, ver: 0x0) Info : stm32.cpu: hardware has 6 breakpoints, 4 watchpoints
2. After connecting We will need to start a GDB debug session. GDB allows the user to dump memory content with "dump" command. As input parameters it needs: dump type, file location, start address and end address. To dump the memory We will need to stop the target. It can be done with a breakpoint. Here are the commands for GDB and output:
gdb -ex "target remote localhost:3333" -ex "monitor reset halt" -ex "break *0x080029dd" -ex "continue" -ex "dump binary memory c:/data/p1.hex 0x20000d88 0x20000DEC" -ex "dump binary memory c:/data/p2.hex 0x20000e50 0x20000EB4" -ex "dump binary memory c:/data/p3.hex 0x20000f18 0x20000F7C" -ex "quit" --batch 0x200004cd in ?? () JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3) JTAG tap: stm32.bs tap/device found: 0x06420041 (mfg: 0x020, part: 0x6420, ver: 0x0) target state: halted target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x0800013c msp: 0x20002000 Breakpoint 1 at 0x80029dd Note: automatically using hardware breakpoints for read-only addresses. Program received signal SIGTRAP, Trace/breakpoint trap. 0x200004cd in ?? () A debugging session is active. Inferior 1 [Remote target] will be detached. Quit anyway? (y or n) [answered Y; input not from terminal]
3. After successfully storing contents of memory We will need to convert the binary memory file to a file that can be plotted. To do this I have written a simple console application. It has 3 input parameters: data size, binary file and plot file. It reads bytes from binary file and writes argument and value (1-8 bytes) to specified plot file:
Mem2plot.exe 2 c:/data/p1.hex c:/data/p1.plot
Mem2plot.exe 2 c:/data/p2.hex c:/data/p2.plot
Mem2plot.exe 2 c:/data/p3.hex c:/data/p3.plot
4. Last but not least We have to plot the memory content. It can be done with Gnuplot or the plot file can be imported to some spreadsheet program. For this example I will use Gnuplot executed from command line:
gnuplot.exe -e "set terminal png size 1024,768;set output 'c:/data/pwm.png';
set ls 1 lw 2; set ls 2 lw 2;set ls 3 lw 2;
plot 'c:/data/p1.plot' with lines ls 1 title 'PWM1',
'c:/data/p2.plot' with lines ls 2 title 'PWM2',
'c:/data/p3.plot' with lines ls 3 title 'PWM3';"
Simple script:
@echo off REM directories set Pathname=c:/data set Pathname_plot=c:/Progra~1/gnuplot/bin set Pathname_m2p=c:/mem2plot REM files set VAR_MEM_FILE=%Pathname%/2.raw set VAR_PLOT_FILE=%Pathname%/2.plot set VAR_PNG_FILE=%Pathname%/2.png REM GDB set VAR_GDB_TARGET=remote localhost:3333 set VAR_GDB_RESET=monitor reset halt set VAR_GDB_BREAK=0x8005dd4 set VAR_GDB_START=0x20002374 set VAR_GDB_END=0x200023D8 set VAR_GDB_CMD=-ex "target %VAR_GDB_TARGET%" -ex "%VAR_GDB_RESET%" -ex "break *%VAR_GDB_BREAK%" -ex "continue" -ex "dump binary memory %VAR_MEM_FILE% %VAR_GDB_START% %VAR_GDB_END%" -ex "quit" REM MEM2PLOT set VAR_M2P_SIZE=2 REM GNUPLOT set VAR_GNUPLOT_CMD=set terminal png;set output '%VAR_PNG_FILE%'; plot '%VAR_PLOT_FILE%' REM set VAR_GNUPLOT_CMD=set terminal windows;plot '%VAR_PLOT_FILE%';pause -1; @echo on REM actual script gdb %VAR_GDB_CMD% --batch cd %Pathname_m2p% Mem2plot.exe %VAR_M2P_SIZE% %VAR_MEM_FILE% %VAR_PLOT_FILE% cd %Pathname_plot% gnuplot.exe -e "%VAR_GNUPLOT_CMD%"
These are all the things that We need to do in order to plot memory contents of an embedded system.
Modified script:
@echo off REM directories set Pathname=c:/data set Pathname_plot=c:/Progra~1/gnuplot/bin set Pathname_m2p=c:/mem2plot REM files set VAR_PNG_FILE=%Pathname%/pwm.png REM GDB set VAR_GDB_TARGET=remote localhost:3333 set VAR_GDB_RESET=monitor reset halt set VAR_GDB_BREAK=0x080029dd set VAR_GDB_CMD=-ex "target %VAR_GDB_TARGET%" -ex "%VAR_GDB_RESET%" -ex "break %VAR_GDB_BREAK%" -ex "continue" -ex "dump binary memory %pathname%/p1.hex 0x20000d88 0x20000DEC" -ex "dump binary memory %pathname%/p2.hex 0x20000e50 0x20000EB4" -ex "dump binary memory %pathname%/p3.hex 0x20000f18 0x20000F7C" -ex "quit" REM MEM2PLOT set VAR_M2P_SIZE=2 REM GNUPLOT set VAR_GNUPLOT_CMD=set terminal png size 1024,768;set output '%VAR_PNG_FILE%'; set ls 1 lw 2; set ls 1 lw 2; set ls 3 lw 2; plot '%pathname%/p1.plot' with lines ls 1 title 'PWM1', '%pathname%/p2.plot' with lines ls 2 title 'PWM2', '%pathname%/p3.plot' with lines ls 3 title 'PWM3'; @echo on REM actual script gdb %VAR_GDB_CMD% --batch cd %Pathname_m2p% Mem2plot.exe %VAR_M2P_SIZE% %pathname%/p1.hex %pathname%/p1.plot Mem2plot.exe %VAR_M2P_SIZE% %pathname%/p2.hex %pathname%/p2.plot Mem2plot.exe %VAR_M2P_SIZE% %pathname%/p3.hex %pathname%/p3.plot cd %Pathname_plot% gnuplot.exe -e "%VAR_GNUPLOT_CMD%"
And the result:
Contents of the buffer viewed in eclipse:
What gave me the idea for the script?
The idea came after using Texas Instruments Code Composer Studio IDE which gives the possibility to plot memory contents on a graph. At work I was doing a project on STM32F1 series microcontroller. The device was doing some voltage and current measuring with the internal ADC. I thought it would be good if I could plot the data without the need for sending it through serial port or some interfaces.
How to trigger the memory dump breakpoint?
To dump the memory we need to halt the target. It can be done with a breakpoint.
In my opinion it is good to set the breakpoint at some line we can trigger from an external interface.
For example if Your device uses serial port for debugging or any non critical transmission.
You can send a command that triggers the breakpoint. Another way is to implement a trigger in Your code. You can put an additional line which will be triggered on spacial occasions a and will be used for the breakpoint only.
No comments :
Post a Comment