1. Purpose of this application
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.
2. Hardware interfaces
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 |
|
Data7 |
|
Status7 |
|
Data0 |
|
Control3 |
|
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.
3. Interface software running on the target
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.
First byte:
-
master sends low byte of adress
-
target sends 0x00
Second byte:
-
master sends high byte of adress, logically anded with 0x7F. The MSB is set for a write access and cleared for a read access.
-
target sends 0x01
Third byte:
-
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:
-
first byte
-
MSB is set
-
bit 6 is cleared for a read access, set for a write access
-
bits 4 and 5 are unused
-
the lower nibble contains adress information
-
-
second byte
-
MSB is cleared
-
seven bits of adress information
-
-
third byte
-
MSB is cleared
-
five bits of adress information
-
bit 1 is unused
-
bit 0 contains data
-
-
fourth byte (only in case of write access)
-
MSB is cleared
-
seven bits of data
-
-
last byte
-
MSB is cleared
-
seven bits CRC
-
The target responds with two bytes in any case:
-
first byte: data read at the adress (in case of a write access this has been read before writing)
-
second byte
-
MSB is cleared
-
seven bits CRC
-
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).
4. User interface
avrdebug does not have a GUI.
When compiled with libreadline, you have a command history and filename completion using the tab key.
5. User commands
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, break
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 |
The break command b is similar to the wait until command w, but instead of waiting until the condition is satified, it checks only once and aborts script execution if the condition is true.
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).
New feature: adresses A and B can be strings; their numerical
values are read from a map file (out/asm/appl.sramdef
or
out/asm-after-pp/SRAM.txt
) which contains lines like
#define some_name 935
New feature: you can add an offset to adress A, examples:
w16s 950 + 2 : -3748
r16s s32SomeValue + 2
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.
Command is one of (r
, w
, u
, b
) 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
, u
and b
commands you may read bytes, words (2 bytes) or any
number of bytes as one value.
The number of bits is specified 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.
5.3. user variable
todo: how to use
6. Example script files
The script files below are written with numerical adresses, which is what avrdebug needs. Using it this way is cumbersome; take a look at the following chapter for better usage.
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
r16u402-404
r16s410
# 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
or
avrdebug
AdapterAndConnectionOptions -t -f
ScriptFile -o Outputfile
7. Integrate with your toolchain
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, so
newline
wQ Debug__b8ReadADC : 1
uQ Debug__b8ReadADC == 0
ruw Debug__au16ADC * 8
loop
is automatically translated to something like
newline
wQ 2168 : 1
uQ 2168 == 0
ruw 1783 * 8
loop
There is a new feature which does part of that job for you by replacing names by values read from a map file, see above.
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…
8. Command line arguments
Well, just execute avrdebug --help
to get help about command line
arguments.