This page describes a patch for the m6811-elf version of gdb that allows the use of the D-bug12 based BDM pods. This includes
This driver is an update of the older D-Bug12 pod driver. That driver did not support chips that had a PPAGE register.
The POD I am using is a MiniDragon+. Expect the same results from a Technological Arts Pod, Motrola 912EVB in pod mode, or from any 9S12DP256 development board with the approriate I/O pins connected to the BDM connector on another target board. Also expect the same results using d-bug12 in EVB mode on a development board without BDM (in which case no flash is availble for developer use, unfortunately).
Reasons for using this particular Pod:
gdb-ppage-patch-v2 you wil need gdb-6.0.tar.gz and m68hc1x-builder-2.91.tar.gz from the m6811-elf project .
mkdir /dist
cd /dist
wget http://www.freelabs.com/~whitis//software/gdb_dbug12/gdb-ppage-patch-v2
wget http://m68hc11.serveftp.org/m68hc1x-builder-2.91.tar.gz
wget http://ftp.gnu.org/pub/gnu/gdb/gdb-6.0.tar.gz
cd /usr/local/src
mkdir m6811
cd m6811
mkdir v2.91
cd v2.91
cp /dist/gdb-ppage-patch-v2 .
tar zxvf /dist/gdb-6.0.tar.gz
tar zxvf /dist/m68hc1x-builder-2.91.tar.gz
cd gdb-6.0
patch -p1 <../m68hc1x-builder-2.91/gdb-6.0-m68hc1x-20040222.diffs
patch -p1 <../gdb-ppage-patch-v2
./configure --target=m6811-elf --prefix=/usr --program-prefix=m6811-elf- --host=i686-pc-linux-gnu
make
make install
Cygwin is a set of tools that provide a unix like environment on top of windoze.
mkdir /dist
cd /dist
wget http://www.freelabs.com/~whitis//software/gdb_dbug12/gdb-ppage-patch-v2
wget http://m68hc11.serveftp.org/m68hc1x-builder-2.91.tar.gz
wget http://ftp.gnu.org/pub/gnu/gdb/gdb-6.0.tar.gz
cd /usr/local/src
mkdir m6811
cd m6811
mkdir v2.91
cd v2.91
cp /dist/gdb-ppage-patch-v2 .
tar zxvf /dist/gdb-6.0.tar.gz
tar zxvf /dist/m68hc1x-builder-2.91.tar.gz
cd gdb-6.0
patch -p1 <../m68hc1x-builder-2.91/gdb-6.0-m68hc1x-20040222.diffs
patch -p1 <../gdb-ppage-patch-v2
./configure --target=m6811-elf --prefix=/usr --program-prefix=m6811-elf-
make
make install
#make sure /usr/bin comes before the existing install of m6811 tools in path
# download program using srec9s12 before starting debugger
# note that serial ports under cygwin are /dev/com1, /dev/com2, etc.
# command line:
m6811-elf-gdb -x gdb-script obj/S12/hi7_load.elf
# or graphical:
ddd --debugger 'm6811-elf-gdb -x gdb-script' obj/S12/hi7_load.elf &
#Note: do not forget to set altclk on pod if your program changes PLL
#frequency: pod altclk 24000
compilation of gdb takes aobut half an hour on my laptop.
Reading memory properly sets and then restores the PPAGE register.
The disassemble command works for code in bank switched flash.
Setting breakpoints in flash works.
Be aware that there are two versions of the PC register
$pc - synthetic 32 bit register that contains the gcc/gdb address
corresponding to the PPAGE:PC if pointing to external
flash.
$ppc = processor (raw) PC register. 16 bits.
$page = processor PPAGE register 8 bits.
I will assume you know enough to replace "/dev/ttyUSB0" with the
appropriate port on your system and the name of your program.
The following commands must be given:
# Load program using srec9s12 first.
m6811-elf-objcopy --verbose --output-target=srec pintest_load.elf \
pintest_intermediate.s19
srec9s12 <pintest_intermediate.s19 >pintest_load.s19
srec9s12 --send_to_pod --pod_port=/dev/ttyUSB0 \
--input_file=pintest_load.s19 --srec_bytes=16 --delay_interval=1 \
--input_map=3
m6811-elf-gdb pintest_load.elf
(gdb) set architecture m68hc12 (REQUIRED even if elf file loaded)
(gdb) set remotebaud 115200
(gdb) target dbugS12 /dev/ttyUSB0
If gdb has started your program without authorization (see below for why):
Control-C
(gdb) pod reset
To start your program (after doing above)
(gdb) pod reset
(gdb) pod nobr // remove any leftover breakpoints on pod
(gdb) delete // remove any leftover breakpoints
// due to gdb bugs
(gdb) display/i $pc
(gdb) break main
(gdb) run
(breakpoint reached)
(gdb) clear main
(gdb) break emstdio_fputc
(gdb) cont
(breakpoint reached)
(gdb) print $ccr |= 0x10 // disable interrupts
(gdb) nexti // singlestep cpu instructions
(gdb) nexti
(gdb) nexti
(gdb) nexti
(gdb0 next // singlestep source lines
(gdb) next
(gdb) next
n
You don't have to stop at main as shown above before setting a breakpoint
somewhere eles.
Two commands have been added to gdb: "pod" and "addrcalc9s12".
Some useful commands:
set debug remote 1 // print commands sent to pod and responses
set debug remote 0 // turn back off
info program // display information about program
break main // set breakpoint at main()
info breakpoints // show breakpoints
clear main // clear breakpoint at main()
delete 1 // delete breakpoint 1
delete // delete all breakpoints
x/i $pc // show current instruction
display/i $pc // show current instruction each time program stops
print/x $ppc // show hardware PC register
print/x $pc // show synthetic PC register
print/x $page // show PPAGE register
print/x $d // show D register
print/x $x // show X register
print/x $y // show Y register
print/x $sp // show SP register
print $page=0x37 // set ppage register
// similarly for other registers
hex
x/xh $x // show 16 bit value pointed to by X register
x/xw $x // show 32 bit value pointed to by X register
x/xb $x // show 8 bit value pointed to by X register
x/10xb $x // show ten 8 bit values pointed to by X register
x/256xb 0x4000 // show 256 bytes at address 0x4000 (in gcc address
space, not banked)
cont // start/continue program
step // execute next line of source code
next // execute next line of source code, but don't
// trace into subroutine calls
// Note: sometimes fails, see below
stepi // execute next instruction
nexti // execute next instruction but don't
// trace into subroutine calls
until // try this at the bottom of a loop
list // show source code near $pc
where // stack trace
info frame // current stack frame info
info locals // show all local variables in current function
run // start program over from begining
print $ccr |= 0x10 // disable interrupts
print bar // show value of variable bar
print bar=123 // set value of variable bar
print foo(1,2,3) // run subroutine foo -- broken
disass foo // disassemble subroutine foo
info target // displays information on the various memory
// sections
where // broken
// first entry may be ok
up // broken
down // broken
set output-radix 16
set input-radix 16
New command: "pod":
pod command // execute command on pod and print results
// up to 1023 characters
pod reset // resset target
pod rd // display registers in D-bug12 format instead
// of gdb format
pod help // DON'T DO THIS
pod ALTCLK 24000 // set alternate BDM frequency
pod stop // stop program
// may want to do "x/i $pc" afterwards
New command: addrcalc9s12:
addrcalc9s12 cpu16 4000 // convert memory address
addrcalc9s12 banked 3E8000 // convert memory address
addrcalc9s12 mot_linear F4000 // convert memory address
addrcalc9s12 offset10000 104000 // convert memory address
addrcalc9s12 help
For example:
(gdb) addrcalc9s12 banked 3E89AB
CPU16: 49AB
Banked: 3E89AB
Motorola Linear:: F89AB
Offset10000: : 1089AB
Addrcalc9s12 is also availible as a standalone program as part of
the srec9s12 package.
Macro tricks:
The following commands will result in a register display each time
the system stops.
define hook-stop
pod rd
end
for some reason, "info registers" doesn't work in that macro
Pressing carriage return will repeat the last command. This is particularly useful for step, next, stepi, nexti.
Beware of executing any pod commands that may interfere with gdb; for example, tampering with breakpoints could cause trouble. Any command that does not return to a prompt could cause trouble. Commands such as "pod help" that print what look like prompt characters can cause trouble. "pod help" also waits for the user to press return after the first page.
The stepi and step commands usually use the bdm pod trace command so they do not require a breakpoint. However, next and nexti sometimes require a breakpoint, depending on whether they encounter a subroutine call. If you are short on breakpoints, try using step/stepi instead of next/nexti where possible.
When gdb starts, it will automatically begin executing your program without permission. This is a gdb bug if a "to_wait()" function has been defined in the target driver; omitting that function results in many other problems. When gdb starts, it will not only start your program it will wait for it to stop. Hit control-C to abort the wait and then issue a "pod reset" command.
The use of a boot loader (either freescales or mine) that allows you to download updates to your software without a BDM pod causes some problems for gdb. Gdb will be confused by the fact that there are two separate programs on the target and that you actually start in a program that it knows nothing about. Avoid the use of the run command in these situatiosn. Instead, do a "pod reset", "break main", and "continue" to start your program.
If your program switches from PLL to XTAL, it causes problems for the BDM pod. Use a command such as "pod altclk 24000" to tell the pod what the new frequency will be so it can automatically fall back to that frequency when the original one fails. Do not attempt to trace through changes to the PLL/busclock frequency or switching to PLL from XTAL operation. In fact, the BDM may not function for some time after such a change due to the clock frequency not being stable. Set a breakpoint some time after the call to the routine which changes the PLL frequency. Adding a delay loop to the PLL setting function helps insure the frequency is stable before additional code is executed, but if the delay isn't long enough you will still have problems.
Whether you are using the pod directly or with gdb, interrupts can cause problems while debugging. Single steps may jump into the interrupt routine. You may want to modify the contents of the CCR register to disable interrupts: "print ccr |= 0x10". Be aware, however, that turning off interrupts can also cause trouble. For example, if you have serial interrupts disabled, your program will hang waiting for the transmit queue to empty after it has printed enough.
# create a gdb initialization script (optional) to save typing
cat >gdb-script <<\...EOF...
set architecture m68hc12
set remotebaud 115200
set remote hardware-breakpoint-limit 2
target dbugS12 /dev/ttyUSB0
pod reset
pod nobr
display/i $pc
info registers
...EOF...
ddd --debugger 'm6811-elf-gdb -x gdb-script' myprogram.elf &
# or
gdb -x gdb-script myprogram.elf
As far as I know, nobody makes a USB serial adapter that actually works properly. This is in large part due to deficiencies in the USB communications class specification. Many of the issues have to do with flow control handling. Correct implementation requires offloading such handling to the adapter because the CPU can only communicate with the adapter infrequently. Because of these flaws, a 115200 baud serial port is effectively slowed down to much less than 9600 if flow control is enabled. In the case of GDB, the issue doesn't appear to be flow control (i.e. it happens with flow control disabled) but something similar. Belkin USB serial adapters are INSANELY slow with gdb. A simple next instruction can take 5 to 15 seconds (depending on the computer I tested on). This is not a problem with a byterunner (FTDI chip based) USB to serial adapter . Besides the flow control issues, I have noticed differences in different USB drivers handling of buffering.
Using the unix "stty" command or the windoze "mode" command, make sure that xon/xoff flow control is disabled on the serial port. Gdb appears to use the existing settings.
Revision 2 of this patch adds the to_wait() function and related code so that wait is called after various commands. It also adds a wait command you can execute. Wait will wait until D-Bug12 displays the "S>" prompt, meaning your program has stopped. It also prints the current location in a form recognized by ddd and can be used in situations where "ddd" is pointing to the wrong source line (for example if you have modified the program counter using pod commands). It also invalidates the register cache, eliminating stale data.
Misc NotesIf you have programs which take 16 bit pointers to a particular memory section in banked memory (for example, all of a particular type of readonly data structure has been moved to the same bank to save space in non-paged flash), don't expect things like
print *p
to work. This is not a problem with this driver. Limitations
in gcc, ld, and gdb prevent this. You will need to do some
fancy arithmatic and casting in your print command to translate
the pointer. If you step through your code until it sets
the appropriate ppage register value, then it might display properly.
You could call a function on the target cpu to print the function
on the serial port except that such function calls from the
debugger are currently broken. You can use the addrcalc9s12 command
added to gdb to calculate the address and then cast that to a pointer
of the approriate type:
i.e. for page=37, pointer=89ab
addrcalc9s12 banked 3E89AB
print *(foo_t *) 0x1089AB
You may use DDD, KDevelop, etc. as a GUI front end to gdb.
These patches were made against the prerelease 2.91 version of m6811-elf-gdb.
srec9s12 is availible from http://www.freelabs.com/~whitis/software/srec9s12
The first parameter is normally passed in the D register, additional paramters are passed on the stack. The return value is also passed in the D register.
Be careful of the limit of 2 hardware breakpoints. In addition to the breakpoints you set, gdb or ddd can set its own breakpoints when you use "nexti", "next", or "continue until here" commands. Do a "pod nobr" command to make sure there aren't any breakpoints already set that gdb doesn't know about. Use the "set remote hardware-breakpoint-limit 2" command.
Note that since the compiler/linker does not properly set the flag which indicates that the code is for an HCS12 cpu, this driver forces that flag to be set.
This driver is not supported.
The gdb support for the HCS12 is buggy as is the original driver this modified driver is based on. So, this driver is not by any stretch of the imagination up to my usual robust code standards.
Here is some info on files related to HCS12 BDM pods.
remote-bdm12.c - The high level code for the driver for the
keven ross? bdm12 pod.
remote-bdm12.h
bdm12.c - The low level code to speak the binary protocol
for the keven ross bdm12 pod.
bdm12.h
m68hc11-rom.c - The code to support the buffallo HC11 pod and
older versions of D-bug12 that did not support
banked memory. Inappropriately named, should
have started with "remote-"
m68hc11-tdep.c - The 68HC11/12 CPU specific debugging code
dbug-rom.c - The code to support the dbug based pods for
the coldfire processor. Inappropriately named, should
have started with "remote-"
remote.c - general remote support
remote-* - Support for debuggers on many other systems
not particularly relevent to 68HC11.c
*-rom.c - support for more debuggers that are not
particularly relevent.
There is a GDB Internals document but it omits a lot of important information.
This file is maintained by Mark Whitis (whitis@freelabs.com).
|
Software Development - Electronic Design - Embedded Systems - Device Drivers - System/Network Administration and Security - Motor Control, RobotCNC - Linux/Un*x - 25+ years experience The author of these pages is looking for a new gig. [RESUME] |
| Engineers and electronic hobbyists: The new Open Symbol Project is creating open schematic symbols and PCB footprints for a variety of different CAD packages. |
| Mark Whitis's Website | Home Page | Linux | Book: Linux Programming Unleashed | My Resume | Genealogical Data | Contact Info | Security | About |
All email messages received must pass the turing test or they will be considered SPAM. If it could have been written by a machine, it was.
Under no circumstances are you to email me with questions regarding windoze, any other microsoft operating system or application, or any software which runs under any form of windoze.
*