This application can connect to a target hardware (which contains some kind of programmable
controller) in several ways and helps you debugging the software running on this controller.
It is possible to read and write bytes, words and ranges of bytes. You can do this
interactively or using scripts to automate certain tasks.
To achieve this, the embedded controller needs to talk a certain protocol. Currently three
protocols are implemented:
-
A simple protocol using the synchronous three wire SPI (MOSI, MISO, CLK).
-
A simple protocol using an asynchronous serial line (TXD, RXD).
-
A block oriented protocol (which is faster than the previous one when
used with usb-to-serial-converters) using an asynchronous serial line (TXD, RXD).
Despite its name it is not limited to AVR controllers. Every device can debugged, provided it
implements one of those protocols.
This program is used to adjust settings for [lavrdev], too.
Several connections to the target controller are possible:
2.1. avrdev
avrdebug uses the block oriented protocol to talk to avrdev on a serial
line, so use the command line parameter -a ser2.
avrdev acts like a gateway to the target device. The target device may be
connected to avrdev via SPI or via a serial line. To tell avrdebug about
which way to go, use -i UART or -i SPI.
You may also use -i SELF, which enables you to debug avrdev itself.
2.2. Simple parallel port adapter
You can use a simple adapter on the parallel port to connect via SPI.
The parallel port SPI connection can be a dongle like the one used by
sp12 (atmel avr programmer):
Parallel port pin |
AVR pin |
Data1 |
/Reset |
Data7 |
MOSI |
Status7 |
MISO |
Data0 |
SCLK |
Control3 |
/SS this connection is optional! |
The pin /SS is pulled low while being connected to the target.
Use command line parameter -a par.
2.3. Serial interface
Well, just make a standard UART connection from the PC to your controller.
Of course you may use a usb-to-serial-converter, too.
You may use -a ser to use the simple serial protocol or -a ser2 to use
the block oriented serial protocol.
The target device needs to run some additional code to be able to talk to
avrdebug.
On the homepage there is an archive containing examples (currently only for
AVR devices).
As mentioned above there are three different methods of connecting to the
target:
3.1. SPI
todo: describe SPI settings
The target device is in slave mode, which means that the communication clock
is an input to it.
During one access, three bytes are exchanged.
-
in case of a write access, the master sends the value to be written.
In case of a read access, the value is undefined.
-
target sends the value of the adress — in case of a write access this
is the value before writing
The adress is limited to 15 bits.
3.2. Simple serial protocol
This protocol allows 16 adress bits and uses a seven bit CRC to make
communication more secure.
avrdev sends four or fives bytes to the target:
The target responds with two bytes in any case:
3.3. Block oriented serial protocol
I won’t describe that one here as it currently is only used between avrdebug
and avrdev (which in turn uses the simple serial protocol to talk to the
target device).
avrdebug does not have a GUI.
When compiled with libreadline, you have a command history and filename
completion using the tab key.
Lines starting with # or ; are ignored.
5.1. Simple commands
-
show help
-
h
-
quit
-
q
-
echo string
-
e "some text"
-
end of script file
-
eof
-
loop (restart) script file
-
loop
-
read script file
-
f FILENAME
-
sleep some µs
-
s NumberOf_µs
5.2. read, write, wait until
I’ll show them without command modifiers first and give examples rather than using
some syntax to describe their syntax ;-)
Every adress (A, B) and number (C, D) needs to be written decimal.
What to do |
command |
arguments |
Read byte at adress A |
r |
A |
Read D bytes starting from adress A |
r |
A * D |
Read bytes from adress A to B |
r |
A - B |
Write C to the byte at adress A |
w |
A : C |
Write C to the bytes from adress A to B |
w |
A - B : C |
Write C to D bytes starting from adress A |
w |
A * D : C |
Wait until the byte at A is equal to C |
u |
A == C |
Wait until the byte at A does not equal C |
u |
A != C |
Wait until the byte at A is greater than C |
u |
A > C |
Wait until the byte at A is smaller than C |
u |
A < C |
Every command prints one or more values in return.
When using the w command, the previous value is displayed, not the one you
are writing (as you do know that one anyway).
5.2.1. Optional command modifiers
The general syntax of the command including optional modifiers is
Command L DisplayModifier
in case you are using a numerical length L, or
Command [ w ] [DisplayModifier]
Command is one of (r, w, u), modifiers in square brackets are
optional and DisplayModifier is one of (u, s, h, q, Q)
The following sections will explain this in more detail.
How to specify the variables length
With the r and u commands you may read bytes, words (2 bytes) or any
number of bytes as one value. To read words (2 bytes) simply append w to
r or u.
You may also specify the number of bits numerically by appending a number L in
the range (8, 16, 24, 32) to the command. However, you have to use one of
the modifiers (DisplayModifier) explained in the following sections in this case.
How to suppress output
You can suppress output by adding q or Q to the command. They only
behave different with the u command (wait until): q means to only
display the value when it matched, Q never displays the value read.
How to chose number base
Optional arguments (u, s, h) are allowed with the commands r, w, u. They indicate
how to display the variables content: unsigned decimal, signed decimal, hexadecimal.
6.1. Some basic commands
# Trigger an algorithm in the target by setting a variable:
w267:2
# Wait until the trigger variable gets reset:
u267==0
# read some vars:
r270-300
ru400
r16u402-404
r16u402*2
rwu402-404
rws410
# reset those vars:
w270-300:0
w400:0
w410*2:0
# use 'eof' to enter interactive mode
eof
# use 'q' to quit the program
#q
6.2. Read values in a loop
You might use something like this to continuously read a set of variables to a
file, maybe to display them graphically or whatever:
e "this line is written only once"
loop_begin:
# Insert a newline. Useful when using table output, ignored otherwise.
newline
# Trigger an algorithm in the target by setting
# a variable, but don't display anything:
wQ 267 : 2
# Wait until the trigger variable gets reset,
# but don't display anything:
uQ 267 == 0
# read some vars:
r8u270*4
r16s 517
# use 'loop' to start from the beginning:
loop
To execute this script, use something like
avrdebug AdapterAndConnectionOptions -t -f ScriptFile > Outputfile
avrdebug AdapterAndConnectionOptions -t -f ScriptFile -o Outputfile
You have to give variable adresses numerically, which is not easy, as they
might change with every compilation of your firmware.
For interactive debugging, your toolchain should provide something like a
map file which lists variable names and adresses, so you may look them up
easily.
To make good use of script files I equipped my toolchain with some mechanism
which automatically compiles script files with symbolic names to files
with numerical adresses on every build.
7.1. tavrasm
For use with tavrasm (there is only one project on which I do still use it,
[lavrdev]) I have a tool which extracts variable adresses from the list
file and produces a file suitable for the c preprocessor, which in turn is
used to convert script files with symbolic names to files with numerical
adresses.
7.2. gcc
Is guess that most people today use some variant of the gcc for their
projects — I do not, so I can’t provide tools to convert script files in
this case, sorry…
But the gcc is able to produce a mapfile during the build and I guess it
should be possible to write a simple tool to extract variable names and
adresses…
Well, just execute avrdebug --help to get help about command line
arguments.
Jens Wilhelm Wulf, j.w.wulf at gmx dot net