|
|
| |
|
|

795,-
EURO

|
|
|
|
|
|
Tips and tricks
Some random tips and tricks for using ZY1000 and JTAG debuggers generally.
Problems with starting a CDT debug session
If CDT debugging works on the first try, great!
Embedded debugging can be quite complex with unique quirks that have to
be understood and dealt with for each setup. No two setups are alike!
Otherwise CDT is the wrong place to try to debug the GDB + hardware debugger setup
as it does not yield intuitive and detailed feedback in response to each
careful step in setting up debug chain for embedded systems.
The sequence below just a suggestion on how to debug, there are of course
many other ways to do so.
By only advancing to the next level when each level of problems are solved,
you get better feedback on problems.
- First check cables & voltages, etc.
- Start with ZY1000 telnet. The next stage is the command line
version of GDB. If you are having trouble figuring out what is happening,
set "debug_level 3" in your ZY1000 config script and look in the log.
- Issue then a "reset run". This will should be able to enumerate the
JTAG toolchain.
- Issue a "reset init". This will reset and halt the target, then run
commands to initialize the target. That is to set up the memory map,
and basic poeripherals. If you only reset and halt the target "reset halt",
you will probably not be able to issue a GDB load or program flash.
- Verify that you can read memory (help mdw) and modify ram (help mww).
- Test the flash if necessary. "reset init" + "flash erase" and
fill the flash with some data(using flash write_image or flash fill). Type
help flash.
- If you have a flash configured, you can program flash by issuing
a GDB load, provided that the address of the .elf image is that of the
flash chip. If you have an .elf image that is copied from flash to
RAM upon startup, you'll need to add an offset to the GDB load command.
Type help load in GDB.
- At this point you are ready to connect to ZY1000 using the GDB
command line version.
- Next there is the issue of breakpoints. GDB will use hardware
breakpoints for the memory regions set up as read only. Type "info
mem" in the GDB console.
- If you have not set up flash regions in your reset init script,
then GDB will use software breakpoints by default, which will fail
for flash regions. The solution is to add a "gdb_override_breakpoint"
command in your reset init script to force hardware breakpoints.
- At this point you should try to single step from GDB command
line version.
- Next try setting a breakpoint and issuing a "continue" command
and verify that the CPU breaks as expected at the breakpoint site.
- At this point you are ready to try to set up a debug session
in Zylin Embedded CDT.
GDB init sequence
If you have a working ZY1000 reset init sequence, then the GDB script should
be quite straightforward:
# Connect to ZY1000
target remote 10.0.0.69:3333
# reset target and run initialisation script.
# all commands to ZY1000 are prefixed with "monitor".
monitor reset init
# load application into RAM
#
# If the target configuration script has been set up with flash
# and the address of the image is in flash, then ZY1000 will program
# the application into flash, erasing any data in the sectors
# where the application is to be programmed.
load
# set program counter to start of application.
# We use ZY1000 to do this because it is more robust
# than trying to do so with GDB. GDB can often be quite
# confused when trying to evaluate stack frames outside
# C code.
monitor reg pc 0x20000000
# To sync things up, we step a single instruction
stepi
A question that might occur to you: what belongs in the reset init script and
what belongs in GDB init script? The answer to this is to a degree a matter
of preference. Perhaps one thing to keep in mind is that scripts executing
on the ZY1000 will execute faster than a long sequence of monitor commands.
Speeding up GDB load
One way to speed up GDB load significantly is to upload the
executable via http before the GDB load session is launched.
Typically this would be done by adding a command to post the stripped
executable to ZY1000 at the end of the build file. The executable then
only has to be uploaded over TCP/IP once every time it changes. Also,
there will normally be enough time between completion of build and
launching a debug session that the executable can be uploaded.
Add the following to the end of your build file:
cp yourapp.elf app.elf
arm-elf-strip app.elf
curl --form form_filecontent=@app.elf 10.0.0.69/ram/cgi/fastload.tcl
Replace "load" in your GDB init file with:
# load image from RAM disk on ZY1000
monitor fast_load
Running ZY1000 at 16MHz, you should expect an increase from ~400kBytes/s to ~1.1mBytes/s.
GDB low level debugging
When debugging low level or early startup code, it might be a good idea *NOT* to
use a graphical GDB GUI until you have stepped into the C source code.
If you use the command line version of GDB, you have a much more precise
control over what commands that are sent to the target. A GUI can, to be helpful,
start reading variables on the stack, etc. When debugging code that is setting
up the stack, then obviously that is the last thing you want.
GDB embedded vs. PC application debugging
There are some important differences to keep in mind when debugging embedded
applications using GDB vs. debugging PC applications.
For embedded, GDB does not launch the application, nor does GDB necessarily even load the application.
GDB attaches to the target. The target can be in any state: powered down, running, halted. Upon
attaching to the target GDB will issue a halt, which may or may not succeed, after which
GDB will enter the halted state.
- Tricky! even if GDB is halted, that does not mean that
the target is halted. You can use GDB "monitor" commands to e.g. reset the target into
the halted state.
- Tricky #2! this means that you have to be somewhat skeptial of the
CPU register info GDB reports immediately after attaching to the target, since GDB may
be out of sync with the target. Use "monitor reg XX" to read the actual value of a register.
"monitor reg XX" will return an error message if the target is in the running state or
otherwise unresponsive.
For an application running out of flash, you would typically specify the executable on the GDB command
line and the executable would only be used by GDB to read out symbols. The actual application would
be programmed in flash by a JTAG debugger beforehand or the ZY1000 can also redirect the GDB "load" to
a flash programming command(including erasing any existing application).
The difference between loading symbols and loading applications is illustrated by the GDB "load"
vs. "symbol" command. The former loads the application AND symbols, whereas the latter only
loads the symbols. It is possible to load multiple symbol files into GDB at the same time, e.g.
bootloader + application.
Target configuration script
Before you can use the ZY1000 to debug your board or program flash, you need a
target configuration script.
The purpose of the target configuration script is to specify to ZY1000 what target
is connected and how to set up a minimal configuration for that target that will
enable uploading code to program flash, upload code to RAM and debug the target.
To get a target script right can be anything from trivial to quite difficult. This
is because there can be a high level of necessary complexity to setting up the target.
The good news is that once done, you'll probably never have to touch that script again.
ZY1000 comes with a lot of target configuration scripts that can be selected from a dropdown menu.
You should start with a target script that closely resembles what you need and modify
it to suit your purposes.
That tricky init sequence
If you don't know how write an init sequence for your target, then there are a couple of resources that
you can resort to:
- Do you have source code(machine code probably) to set up the target? You can try translating that
machine code to a init sequence. Most often this will boil down to a dozen
or two of "mww" commands in the reset event sequence. If this can be done
easily, then it is probably the preferable way of doing things.
- Do you have an application binary that sets up the RAM that you can program to flash?
If you are able to program that application to flash, then you can use "resume"
and "halt" in your reset init
sequence. This will let the CPU run for a short time, enough to set up RAM. Afterwards,
you should be able to upload RAM using e.g. GDB load. Note that making a minimal
reset init script that sets up flash can be a LOT easier than setting up
the RAM.
- Hit the datasheets. If you read through the datasheets you should find all
the information required to set up your target buried in there. This can be
quite a time consuming process and it is fairly likely that someone has done
this for you.
- A bit more esotheric approach: if you have internal memory for your CPU, then you may be able to use
the binaries of an application to set things up. The early startup code for
an application is almost certainly position independent. This should allow you
to load the beginning of that application into the internal RAM and execute the
first few instructions. You'll have do a bit of manual disassembly to determine
how much of the beginning of the application you need. Use objcopy -O binary to
create a binary file and truncate that binary file.