Order this document by:
AN1230/D
© MOTOROLA INC, 1996
SEMICONDUCTOR
MOTOROLA
APPLICATION NOTE
A Background Debugging Mode Driver
Package for Modular Microcontrollers
By Scott Howard
INTRODUCTION
Motorola's 16-bit and 32-bit modular microcontroller devices feature a unique mode of operation called
background debugging mode (BDM). When enabled, this mode allows an external host processor to control
a target microcontroller unit (MCU) and access both memory and I/O devices via a simple serial interface.
BDM can be very useful during initial debugging of control system hardware and software, and can also sim-
plify production-line testing and configuration of an end product.
This application note shows how to enable and control BDM using an IBM-compatible personal computer.
Driver routines and demonstration programs written in C are included to assist the user in quickly and easily
implementing a custom test jig or debug facility. The only additional hardware required is a simple hardware
interface attached to the PC-compatible parallel printer port.
BDM OVERVIEW
There are several considerations that affect the design of microcontroller emulation and debugging tools.
Conventional emulators use buffering circuitry to separate the processor from the prototype under develop-
ment, and connect to a target system using a long in-circuit emulation cable. The buffers and cable have a
significant impact on MCU bus timing, making truly transparent emulation very difficult and expensive to
achieve. This is especially true when the MCU is surface-mounted on a circuit board, since emulation cables
and connectors for surface-mount packages tend to be expensive. In addition, accesses to on-chip memory
and peripherals cannot easily be monitored in this way, particularly when the MCU operates as a single-
chip system with no external bus.
Background debugging mode was conceived as a way to eliminate these problems. BDM uses a small
amount of on-chip support logic, some additional microcode in the CPU module, and a dedicated serial port.
By routing background mode interface signals to a small, inexpensive header on the target prototype, the
designer can enable a host debug computer to take complete control of the target system – stopping it, ex-
amining and changing registers and memory locations, single-stepping, resetting, and restarting it – without
affecting normal operation in any way. None of the user resources of the chip or the target system, such as
timers, on-chip memory, or I/O pins are required to support debugging mode. The microcontroller runs at
its full rated speed with no timing restrictions imposed by an external emulator.
BDM is implemented in both the CPU16 and the CPU32 processor modules of the Motorola modular micro-
controller family. Thus any MCU that incorporates one of these processor modules includes the BDM inter-
face. This includes all M68HC16 devices and all M68300 devices starting with MC68330.
BDM is fully documented in Section 10 of the
CPU16 Reference Manual
(CPU16RM/AD), and in Section 7
of the
CPU32 Reference Manual
(CPU32RM/AD).
MOTOROLA AN1230/D
2
BDM OPERATION
Background debug mode is a special mode of operation of the CPU module. Three pins provide the hard-
ware interface to the MCU (BKPT/DSCLK, IPIPE0/DSO, and IPIPE1/DSI on devices that incorporate the
CPU16, BKPT/DSCLK, IPIPE/DSO, and IFETCH/DSI on devices that incorporate the CPU32). BDM must
be enabled by holding the BKPT pin low on the rising edge of RESET. A fourth pin, FREEZE, indicates
whether or not the MCU is in BDM.
During normal operation, the CPU fetches instructions from system memory and executes them, the
FREEZE signal is held low, and the pipeline state signals (IPIPE0 and IPIPE1 or IPIPE and IFETCH) allow
external hardware to track the operation of the instruction prefetch queue. When BDM has been enabled,
driving the BKPT pin low during normal instruction execution causes the CPU to finish executing the current
instruction, then enter background debugging mode. In BDM, FREEZE is driven high, and the BDM pins
change function to become a synchronous serial port. The BDM port is very similar in operation to a Motor-
ola serial peripheral interface (SPI) slave device; the BKPT pin becomes the development system clock
(DSCLK) pin. The DSCLK signal clocks data transfers between the host and the target MCU. IPIPE0 (or
IPIPE) becomes a development system output (DSO) pin, which carries data from the target MCU to the
host processor. IPIPE1 (or IFETCH) becomes a development system input (DSI) pin, which carries data
from the host processor to the target MCU.
The BDM serial interface transfers data in 17-bit words, most significant bit first. Each bit is transferred on
the rising edge of DSCLK, which must be generated by the host system. The MSB returned from the target
MCU is a status bit. The bit normally has a value of zero, but is set when an error or abnormal condition is
detected. The other 16 bits transfer data and/or commands between the host system and the MCU.
The CPU receives debug instructions via the interface port, executes them, and returns results (if any) to
the host system via the interface port. The debugging instructions are relatively simple, but provide all the
primitive operations required in a debugging environment.
To efficiently implement BDM in a product, Motorola recommends that a 10-pin header with the configura-
tion shown in Table 1 be used to connect the MCU to an external host. This configuration is used by Motor-
ola development tools and is also supported by several third-party tool vendors:
Table 1 BDM Connector Standard Pinout
Pin Number Pin Name Description
1 DS Data strobe from target MCU. Not used in current interface circuitry
2 BERR Bus error input to target. Allows development system to force bus error
when target MCU accesses invalid memory
3V
SS
Ground reference from target
4 BKPT/DSCLK Breakpoint input to target in normal mode; development serial clock in
BDM. Must be held low on rising edge of reset to enable BDM
5V
SS
Ground reference from target
6 FRZ Freeze signal from target. High level indicates target is in BDM
7 RESET Reset signal to/from target. Must be held low to force hardware reset
8IFETCH/DSI (CPU32)
IPIPE0/DSI (CPU16) Used to track instruction pipe in normal mode. Serial data input to target
from MCU in BDM
9V
CC
+5V supply from target. BDM interface circuit draws power from this supply
and also monitors 'target powered/not powered' status
10 IPIPE/DSO (CPU32)
IPIPE1/DSO (CPU16) Tracks instruction pipe in normal mode. Serial data output from target MCU
in BDM
AN1230/D MOTOROLA
3
INTERFACING TO AN IBM COMPATIBLE PC
The BDM interface requires synchronous timing, and other MCU status and control signals, such as RESET
and BERR, must also be monitored during BDM. These factors make a direct RS-232 BDM interface im-
practical. Instead, the IBM PC parallel printer port can be used to interface directly to the logic-level signals
of the target microcontroller. Software provides the synchronous timing required.
A hardware interface circuit must be used to reduce errors due to noise, and also to buffer microcontroller
signals so that they are not unduly loaded by the PC and cable. The code provided in this application note
supports two different interface circuits.
The first interface circuit is incorporated in the Motorola In-Circuit Debugger (ICD). The ICD product includes
an interface circuit board and a debug monitor program that runs on a host IBM-compatible computer. ICD
are available for CPU16 microcontrollers (Motorola part no. M68ICD16) and for CPU32 microcontrollers
(Motorola part no. M68ICD32).
The second interface circuit is the public-domain circuit shown in Figure 1. The circuit uses two 74HC series
logic devices and a minimum of passive components, making it inexpensive and easy to construct.
Figure 1 Public Domain BDM Interface Circuit
PC/BDM CONN
BKPT/
DSCLK
RESET
FREEZE
IFETCH/DSI
GND
VDD
GND
IPIPE/DSO
J
PRE
CLR CLK
Q
K
17
1
14
15
16
11
10
12
18
10K
.001 µF
1N4148
3
2
16
4
1
14
1
236
4
5
11 12
13 10
3
9
5
8
6
7
4
PC PRINTER PORT BDM CONNECTOR
MC74HC76N
MC74HC132AN
AB
DS
1
BERR
4
D
0.1 µF
VDD
VDD
MOTOROLA AN1230/D
4
SOFTWARE DRIVERS
The software drivers presented in this application note are written in C. The drivers are designed to be linked
into a user's debug or production test program. They perform the following functions for both CPU16 and
CPU32 targets:
• Initialize and de-initialize the parallel printer port interface
• Provide basic control functions to reset, stop, and start code execution on the target MCU,
and to monitor target status
• Read and write CPU registers, including system registers supported by the target MCU
• Read and write memory and memory-mapped I/O, in byte, word, and long word sizes
• Take advantage of memory block read and write operations supported by the target MCU
• Read S-records from an IBM PC disk file, and write the contents to target system memory
A typical application would begin by calling
Init
()
to initialize the driver package. It is a good practice to
apply a hardware reset to the target system after it is connected to the PC and powered up, since BDM is
not active unless the target is reset with the BKPT pin held low. This can be achieved by calling either
Reset
Chip
()
, which resets the target and allows it to run, or by calling
RestartChip
()
, which resets the
target and forces it into background mode immediately after the initial program counter and stack pointer
fetches.
The user's debug software can get the current status of the target by calling
GetStatus
()
. This function
call returns an integer value in which each bit indicates the state of one signal on the target. The type of
interface hardware used between the PC and the target determines which signals are available. Table 2
shows these status bits:
There are several other control functions as well.
StopChip
()
puts the target into background mode (if it
is not already) by holding the BKPT pin low until FREEZE is asserted.
StepChip
()
single-steps the target
by allowing one instruction to be fetched and executed before BKPT is asserted again.
RunChip
()
re-
sumes full-speed execution, either at a programmer-defined address or at the location pointed to by the
MCU program counter.
Reading and writing CPU registers using function calls
GetReg
()
and
PutReg
()
is straightforward.
These functions have an integer parameter that identifies whether the register is to be read or written. The
symbolic names for these register identifiers are defined in the include file
regnames.h
.
Reading and writing memory is only slightly more complex. Memory can be accessed in byte, word, or long
word format. The different access sizes are handled by function calls
GetByte
()
,
GetWord
()
,
GetLong
()
, and
PutByte
()
,
PutWord
()
, and
PutLong
()
. Memory accesses also use a memory space at-
tribute, represented by the function code value that is driven out on the FC[2:0] pins during the MCU mem-
ory access bus cycle. The memory space can be one of User Data (function code 1), User Code (function
code 2), Supervisor Data (function code 5), or Supervisor Code (function code 6). Memory space is selected
by calling function
SetFC
()
, passing the desired function code as a parameter. M68HC16 microcontrollers
always operate in supervisor mode, so for these, only function codes 5 and 6 are supported.
Table 2 Status Bits Returned from
GetStatus
()
Bit
Position Symbolic Name
(in 'trgtstat.h') Description Public-Domain
Interface ICD
Interface
Bit 0 TARGETRESET 1 if target in reset state (RESET = 0) Yes No
Bit 2 TARGETSTOPPED 1 if target in background mode (FREEZE = 1) Yes Yes
Bit 3 TARGETPOWER 1 if no power applied to target Yes No
Bit 4 TARGETNC 1 if BDM interface cable is disconnected Yes No
AN1230/D MOTOROLA
5
All functions operate whether the target MCU is running or stopped. For example, if the
GetReg
()
function
is called when the target is already in background mode, the BDM driver software simply fetches the con-
tents of the specified target register and returns it to the calling routine. However, if the target MCU is exe-
cuting code, the target MCU is temporarily halted, the specified register is retrieved, and the target MCU is
then immediately restarted. This provides some interesting capabilities. For instance, it is possible to mon-
itor RAM locations as the processor executes code, or to profile MCU code execution by periodically sam-
pling the value in the program counter.
ERROR HANDLING
All of the BDM drivers employ some level of error handling and retry. However, there are cases where the
driver cannot perform the requested function, such as trying to read a target register when the interface ca-
ble is disconnected. Returning an error code to the calling routine is not a good solution, since in that case
an error flag must be tested each time the interface function is called. Instead, when one of these cases is
encountered, the driver package calls a user-defined function called
DriverError
()
. This function is
passed through an integer error code which identifies the error condition.
Several actions are possible with
DriverError
()
. The easiest implementation is to simply report the er-
ror and then return control to the operating system. This is probably not satisfactory for most applications,
however, and a program which does not handle errors more gracefully is frustrating to the user. Another
approach is to use
setjmp
()
in the main loop of the program, and design
DriverError
()
to report the
problem, and then call
longjmp
()
to return to the mainline routine.
ACCESSING THE BDM DRIVER PACKAGE
The source code for this driver package is too large to be reproduced in this application note. However, a
current version of the source code is maintained on Motorola's Freeware Bulletin Board System.
The Freeware BBS can be accessed by modem at (512) 891-3733. Configure the interface for eight data
bits, no parity, and one stop bit. The BBS is compatible with any V.32 or Bell 212 modem operating at data
rates from 1200 to 9600 baud. Log on and check the MCU332 file area for an archive named BDMVx-y.ZIP,
where 'x' and 'y' represent the latest version number of the driver package.
MOTOROLA AN1230/D
6
FUNCTION REFERENCE
The driver package is contained in several files, listed in Table 3. To produce an executable program, the
user's program must be compiled and linked along with either bdm-icd.c or bdm-pd.c depending on which
interface hardware (ICD or Public-Domain, respectively) is used, and either bdmcpu32.c or bdmcpu16.c de-
pending upon whether the target system is an M68300 or M68HC16 device. The file bdm-util.c contains rou-
tines to read Motorola S-records from disk files and write the S-record contents to target memory, and must
be compiled and linked only if these S-record routines are needed in the user's program.
For convenience, the archive on the BBS includes pre-compiled small-model object files for Turbo C and
Borland C. The programs use some Borland compiler-specific features, such as library calls to perform port
I/O and directives to insert assembly-language code into the program; however, most PC compilers provide
these features, and conversion to another compiler will probably require only minor editing, compilation, and
retesting.
Table 4 contains a detailed BDM driver function reference.
Table 3 Source Files in the BDM Archive
Source File Optional? Description
bdmcpu16.c and
bdmcpu32.c No Contain high-level driver functions for the CPU16 and CPU32 tar-
gets, respectively. One driver must be compiled and linked into user
application to provide access to background mode interface.
bdm-icd.c and bdm-pd.c No Contain the low-level control routines for the ICD card and the public
domain circuit, respectively. One of these files must be compiled
and linked into user application to provide access to background
mode interface.
bdmcalls.h No Defines high-level function calls for use by external code; should be
included in any user program.
bdmerror.h No Define error codes passed to DriverError () user function.
Should be included in user program where DriverError () is de-
fined.
bdm-util.c Yes Contains the utility functions to read S-records from disk files and
write the contents of S-records into target memory. Only required if
program must read S-record files from disk and/or write S-records
to target memory.
bdm-util.h Yes Prototypes utility function calls (in bdm-util.c) for S-record ac-
cess. Should be included into user code if program must read S-
record files from disk and/or write S-records to target memory.
regs-16.h and regs-32.h Yes Define symbolic names for register identifiers passed to GetReg ()
and PutReg (). Only required if user calls GetReg () and PutReg
() to read and write target CPU registers.
trgtstat.h Yes Defines bit values returned by GetStatus () and GetStatusMask
() functions. Only required if user calls one of these functions.
textio.h Yes
This header file allows the user to select, using a #define constant,
whether the text output routines in do_load () use Borland's
cprintf/cputs/putch or the ANSI standard
printf/puts/putchar calls. It may also be included into user code
for text output to the PC's screen.
AN1230/D MOTOROLA
7
Table 4 BDM Driver Package Function Reference
Prototype Description Return Value
#include “bdmcalls.h”
unsigned ValidPorts
(void);
Checks the PC's BIOS data tables for the number
of parallel printer ports installed in the PC; returns
a bit vector representing which parallel ports
(LPT1, LPT2, and LPT3) are installed.
The return value has one bit set for
each parallel port (LPT1-LPT3)
which is in- stalled in the PC, i.e. bit
0 is set if LPT1 is installed, bit 1 for
LPT2, and bit 2 for LPT3.
#include “bdmcalls.h”
int Init (unsigned
Port, unsigned Speed);
The desired port (1 through 3, for LPT1 through
LPT3 respectively) is checked for validity, and if
available will be initialized to the desired bit rate to
communicate with the BDM interface circuit.
Returns a non-zero value if the ini-
tialization failed for any reason,
such as printer port not installed.
#include "bdmcalls.h"
void SetFC (void);
Sets the function code to be used when the BDM
drivers access target memory. The valid function
codes are 1 (user data), 2 (user program), 5 (su-
pervisor data), and 6 (supervisor code). The de-
fault is 5 (supervisor data). If an invalid code is
passed, the function code will remain at its previ-
ous setting.
Note: for M68HC16 microcontrollers, only 5 and 6
are valid.
Nothing.
#include "bdmcalls.h"
void DeInit (void);
Restores the parallel port hardware to its original
state before Init () was called. This function
should be called by user code before the program
exits to DOS. Nothing.
#include "bdmcalls.h"
unsigned GetStatus
(void);
Returns a bit vector representing the current sta-
tus of the target MCU. Some error conditions are
not detectable by both hardware interfaces.
Therefore, only those errors which can be detect-
ed by the interface in use will actually be reported.
The following bits are defined in
“trgtstat.h”, which is included
by “bdmcalls.h”. The state is true
when the corresponding bit is set to
1:
TARGETRESET: Target is in reset
state
TARGETHALT: Target is
halted
TARGETSTOPPED: Target is in
FREEZE state
TARGETINVALID: Target
interface is not initialized
#include "bdmcalls.h"
unsigned GetStatusMask
(void);
Returns a bit vector representing which bits are
valid in the return value of GetStatus ().
The following bits are defined in
“trgtstat.h”, which is included
by “bdmcalls.h”. Any bit set to 1
indicates that the GetStatus ()
function is capable of detecting and
returning the corresponding status:
TARGETRESET: Target is in reset
state
TARGETHALT: Target is
halted
TARGETSTOPPED: Target is in
FREEZE state
TARGETINVALID: Target
interface is not initialized
#include "bdmcalls.h"
int StopChip (void); Stops (places into FREEZE state) target MCU. Non-zero if the target was running
when StopChip () was called;
otherwise zero.
MOTOROLA AN1230/D
8
#include "bdmcalls.h"
void StepChip (void); Single-steps target MCU by one instruction. Nothing.
#include "bdmcalls.h"
void ResetChip (void);
Forces hardware reset on target MCU; leaves
MCU in running state. Nothing.
#include "bdmcalls.h"
void RestartChip
(void);
Resets target MCU, and stops execution on first
instruction fetch (after PC and SP are fetched
from vector table). If target does not stop, and the
ICD interface circuit is used, a bus error will be as-
serted on the target MCU to bring it into BDM; else
if the public-domain circuit is used, DriverError
() will be called with the appropriate error.
Nothing.
#include "bdmcalls.h"
void RunChip (LONG
where);
Starts execution of target MCU at address speci-
fied by 'where'. If 'where' is 0, execution starts at
address contained in Program Counter of target
MCU. Nothing.
#include "bdmcalls.h"
#include “regs-16.h”
(or)
#include "regs-32.h"
LONG GetReg (unsigned
which);
Retrieves and returns the contents of the target
CPU register indicated by 'which'. Symbolic val-
ues for the register codes are defined in the file
'regs-16.h' (CPU16 targets) and 'regs-
32.h' (CPU32 targets).
The data contained in the specified
register.
#include "bdmcalls.h"
#include "regs-16.h"
(or)
#include "regs-32.h"
void PutReg (unsigned
which, LONG data);
Writes the value 'data' into the target CPU register
indicated by 'which'. Symbolic values for the reg-
ister codes are defined in the file 'regs-16.h'
(CPU16 targets) and 'regs-32.h' (CPU32 tar-
gets).
Nothing.
#include "bdmcalls.h"
LONG GetByte (LONG
Where);
Performs a byte read on the specified memory lo-
cation and returns value retrieved.
Returns contents of byte-ad-
dressed memory at location
'Where'. Values returned are 0-
0xff.
#include "bdmcalls.h"
LONG GetWord (LONG
Where);
Performs a word read on the specified memory lo-
cation and returns value retrieved.
Returns contents of word-ad-
dressed memory at location
'Where'. Values returned are 0-
0xffff.
#include "bdmcalls.h"
LONG GetLong (LONG
Where);
Performs a longword read on the specified mem-
ory location and returns value retrieved. Returns contents of longword-ad-
dressed memory at location
'Where'.
#include "bdmcalls.h"
LONG DumpByte (LONG
Where);
Performs a byte read on the specified memory lo-
cation and returns value retrieved.
On CPU16 targets, this call is identical to GetByte
(). On CPU32 targets, a special BDM command
is used which is faster than a normal memory ac-
cess.
GetByte (), GetWord (), or GetLong ()
should be called first, to set the initial address for
memory subsequent memory writes; then any
number of
DumpByte (), DumpWord (), or DumpLong ()
calls may be made to read from following loca-
tions of memory.
Returns contents of byte-ad-
dressed memory at location
'Where'. Values returned are 0-0xff.
Table 4 BDM Driver Package Function Reference (Continued)
Prototype Description Return Value
AN1230/D MOTOROLA
9
#include "bdmcalls.h"
LONG DumpWord (LONG
Where);
Performs a word read on the specified memory lo-
cation and returns value retrieved.
On CPU16 targets, this call is identical to
GetWord (). On CPU32 targets, a special BDM
command is used which is faster than a normal
memory access. GetByte (), GetWord (), or
GetLong () should be called first, to set the initial
address for memory subsequent memory writes;
then any number of DumpByte (), DumpWord (),
or DumpLong () calls may be made to read from
following locations of memory.
Returns contents of word-ad-
dressed memory at location
'Where'. Values returned are 0-
0xffff.
#include "bdmcalls.h"
LONG DumpLong (LONG
Where);
Performs a longword read on the specified mem-
ory location and returns value retrieved.
On CPU16 targets, this call is identical to GetLong
(). On CPU32 targets, a special BDM command
is used which is faster than a normal memory ac-
cess.
GetByte (), GetWord (), or GetLong () should
be called first, to set the initial address for memory
subsequent memory writes; then any number of
DumpByte (), DumpWord (), or DumpLong ()
calls may be made to read from following loca-
tions of memory.
Returns contents of longword-ad-
dressed memory at location
'Where'
#include "bdmcalls.h"
void PutByte (LONG
Where, BYTE Data);
Performs a byte write at location 'Where', writing
the value 'Data'. Nothing.
#include "bdmcalls.h"
void PutWord (LONG
Where, WORD Data);
Performs a word write at location 'Where', writing
the value 'Data'Nothing.
#include "bdmcalls.h"
void PutLong (LONG
Where, LONG Data);
Performs a longword write at location 'Where',
writing the value 'Data'. Nothing.
#include "bdmcalls.h"
void FillByte (LONG
Where, BYTE Data);
Performs a byte write at location 'Where', writing
the value 'Data'.
On CPU16 targets, this call is identical to PutByte
(). On CPU32 targets, a special BDM command
is used which is faster than a normal memory ac-
cess.
PutByte (), PutWord (), or PutLong () should
be called first, to set the initial address for memory
subsequent memory writes; then any number of
FillByte (), FillWord (), or FillLong ()
calls may be made to write to following locations
of memory
Nothing.
#include "bdmcalls.h"
void FillWord (LONG
Where, WORD Data);
Performs a word write at location 'Where', writing
the value 'Data'.
On CPU16 targets, this call is identical to PutWord
(). On CPU32 targets, a special BDM command
is used which is faster than a normal memory ac-
cess.
PutByte (), PutWord (), or PutLong () should
be called first, to set the initial address for memory
subsequent memory writes; then any number of
FillByte (), FillWord (), or FillLong ()
calls may be made to write to following locations
of memory
Nothing.
Table 4 BDM Driver Package Function Reference (Continued)
Prototype Description Return Value
MOTOROLA AN1230/D
10
#include "bdmcalls.h"
void FillLong (LONG
Where, LONG Data);
Performs a longword write at location 'Where',
writing the value 'Data'.
On CPU16 targets, this call is identical to
PutLong (). On CPU32 targets, a special BDM
command is used which is faster than a normal
memory access. PutByte (), PutWord (), or
PutLong () should be called first, to set the initial
address for memory subsequent memory writes;
then any number of FillByte (), FillWord (),
or FillLong () calls may be made to write to fol-
lowing locations of memory
Nothing.
#include “bdm-calls.h”
#include "bdm-util.h"
#include <stdio.h>
int do_srec (srecord
*where, FILE *infile);
Reads one S-record from the file addressed by
'infile' and writes the contents into the srecord
structure '*where' in memory. The 'srecord'
structure is defined in the include file "bdm-
util.h".
When do_srec () returns indicating either no er-
ror or SREC_S9 (end of file record), the structure
'*where' contains the following information:
where->rectype holds the contents of the S-
record type field, one of the following values: 0, 1,
2, 3, 7, 8, or 9. (Note that a type 0 field is a header
field and should be ignored; types 7, 8, and 9 are
end-of-file records, causing do_srec to return
SREC_S9 instead of 0.)
where->reclen holds the contents of the record
length field of the S-record.
where->address holds the contents of the ad-
dress field of the S-record.
where->bytes [] holds the contents (if any) of the
data field of the S-record. The number of valid
bytes will be: where->reclen, minus the size of
the address field (2 for types 0, 1, and 9; 3 for
types 2 and 8; 4 for types 3 and 7), minus one.
Returns a status code representing
the success or failure of the read.
The codes are defined in the in-
clude file "bdm-util.h".
0: S-record was read OK -memory
structure contains valid data.
SREC_EOF: file ended before
end-of-file record found
SREC_FORMAT: file does not
match defined S-record format.
SREC_CHECKSUM: checksum
error in S-record.
SREC_S9: this S-record is the
end-of-file record as defined in the
Motorola S-record spec. This sta-
tus is not an error, but rather an in-
dication that the last record was
read from the file, and the user pro-
gram should not continue to call
do_srec ().
#include "bdm-calls.h"
#include "bdm-util.h"
void put_srec (srecord
*data, LONG
load_offset);
Writes the data contained in data->bytes to mem-
ory in the target system, at the address specified
by data->address plus load_offset. Type 0
records are ignored; type 7, 8, and 9 records
cause the global variable ExecuteAddress to be
set to the value data->address plus load_offset.
Nothing.
#include "bdm-calls.h"
#include "bdm-util.h"
int do_load (LONG
load_offset, char *in-
filename);
Opens the disk file named by 'infilename', reads
S-records from the file on at a time using do_srec
(), and writes the contents of the S-records to tar-
get memory using put_srec ().
Returns the same error codes as
do_srec (), with one addition: if
the file specified by 'infilename'
cannot be opened, do_load re-
turns the value -1.
Table 4 BDM Driver Package Function Reference (Continued)
Prototype Description Return Value
AN1230/D MOTOROLA
11
AN EXAMPLE PROGRAM
The BDM archive contains a file called test.c, which implements a simple monitor. The monitor allows a user
to examine any 256-byte range of target memory, display CPU registers, restart the target from power-on
reset, single-step the target, hardware reset the target, and load S-record files on disk into target memory.
A simple DriverError () routine reports errors in the target interface, then returns control to the user.
To produce an executable program for a CPU32 target, test.c must be compiled and linked with
bdmcpu32.c, test32.c, bdm-util.c, and either bdm-icd.c or bdm-pd.c, depending on the interface
hardware used. For a CPU16 target, test.c must be compiled and linked with bdmcpu16.c, test16.c,
bdm-util.c, and either the bdm-icd.c or bdm-pd.c. Test16.c and Test32.c contain the function
DumpRegisters (), which displays target CPU register content, and is therefore specific to the type of
CPU being controlled.
Test.c Source Code
/* test.c - test background mode drivers
* this program is a very simple monitor program which will allow the user
* examine and change memory and registers, start/stop/reset/single step, etc.
* Functions which are common to both CPU32 and CPU16 targets are in this file
* test16.c and test32.c contain the code specific to the target
*/
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <setjmp.h>
#include "bdmcalls.h"
#include "trgtstat.h"
#include "bdmerror.h"
#include "bdm-util.h"
#include "textio.h"
#define MaxBuffer 128
extern void DumpRegisters (void);
extern char *TargetName;
int GetCommandString (char *where, int count);
char ReturningToDOS [] = "Returning to DOS" NEWLINE;
jmp_buf Saviour;
/* DriverError is a function called by background mode drivers when error
*detected
* this version simply prints an error corresponding to the error code and exits
*/
static char *ErrorStrings [] =
{
NEWLINE "Unknown Error Encountered – Check Communications Speed" NEWLINE ,
NEWLINE "Power Failed on Target MCU" NEWLINE,
NEWLINE "Cable Disconnected on Target MCU" NEWLINE,
NEWLINE "No Response from Target MCU" NEWLINE,
NEWLINE "Can't Clock Target MCU while in Reset" NEWLINE ,
NEWLINE "Specified Parallel Port Not Available on this PC" NEWLINE
};
int ErrorCode, ErrorRW;
LONG ErrorAddress;
void DriverError (int ErrCode, int LastRW, LONG LastAddress)
{ErrorCode = ErrCode;
ErrorRW = LastRW;
ErrorAddress = LastAddress;
longjmp (Saviour, 1);
MOTOROLA AN1230/D
12
}
void ReportError (void)
{if (ErrorCode == BDM_FAULT_BERR)
printf (NEWLINE "Bus error %s address %lx" NEWLINE ,
ErrorRW ? "reading" : "writing",
ErrorAddress);
else puts (ErrorStrings [ErrorCode]);
}
int main ()
{unsigned CharCount, Counter, Counter1, SR, GotOne = 0, Ports = ValidPorts ();
int Stopped, Speed = -1, SelectedPort = 0;
char *ptr, Buffer [MaxBuffer], QuitFlag = '\0';
LONG LongTemp, MemDump = 0;
BYTE ByteTemp;
clrscr ();
printf ("Test Program for %s Background Mode Drivers" NEWLINE , TargetName);
printf ("Available LPT Ports: <");
for (SR = 1, Counter = 1; Counter <= 16; Counter++, SR <<= 1)
{if (SR & Ports)
{if (GotOne) putchar (',');
GotOne = 1;
printf ("%d", Counter);
}
}
if (!GotOne) puts ("none");
puts ( ">" NEWLINE );
if (!Ports)
{printf ("I need at least one parallel printer port to function!" NEWLINE
"%s", ReturningToDOS);
exit (1);
}
for (;;)
{puts ("Please select Printer Port:");
CharCount = GetCommandString (Buffer, MaxBuffer);
if (!CharCount || !sscanf (Buffer, "%d", &SelectedPort)) return 0;
do
{puts ("Please select Clock Speed (0-100): ");
CharCount = GetCommandString (Buffer, MaxBuffer);
if (!CharCount || !sscanf (Buffer, "%d", &Speed)) return 0;
}
while (Speed < 0 || Speed > 100);
if (setjmp (Saviour)) ReportError ();
else if (Init (SelectedPort, Speed))
printf ("Can't initialize port %d at speed %d" NEWLINE,
SelectedPort, Speed);
else break;
}
printf ("Port %d Initialized at Speed %d" NEWLINE , SelectedPort, Speed);
puts ("Resetting Target MCU to enable BDM" NEWLINE );
ResetChip ();
while (!QuitFlag)
{if (setjmp (Saviour)) ReportError ();
puts ("Enter Command DHMRSQ('H' for Help):");
GetCommandString (Buffer, MaxBuffer);
for (ptr = Buffer ;isspace (*ptr); ptr++) ;
switch (toupper (*ptr))
{
case 'B':
AN1230/D MOTOROLA
13
RestartChip ();
case 'D':
DumpRegisters ();
break;
case 'H':
printf ("Help for TEST (%s Target)" NEWLINE
"B: Begin Program Execution from Reset" NEWLINE
"D: Dump Target MCU Registers" NEWLINE
"H: Print This Help Summary" NEWLINE
"L: Load S-Record File into Target" NEWLINE
"M: Memory Hex/ASCII Display" NEWLINE
"R: Hardware Reset Target MCU" NEWLINE
"S: Single Step Target MCU" NEWLINE
"Q: Quit back to DOS" NEWLINE , TargetName);
break;
case 'L':
printf ("S-Record File to Load: ");
if (!GetCommandString (Buffer, MaxBuffer)) break;
PrintEachRecord = ".";
do_load (0, Buffer);
break;
case 'M':
printf ("Memory Dump start address in hex:");
GetCommandString (Buffer, MaxBuffer);
if (!sscanf (Buffer, "%lx", &LongTemp))
LongTemp = MemDump;
Stopped = StopChip ();
set_fc ();
for (Counter = 16; Counter; Counter--)
{printf ("%08lX ", LongTemp);
for (Counter1 = 16; Counter1; Counter1--)
printf ("%02X ", (BYTE) GetByte (LongTemp++));
LongTemp -= 16;
putchar (' ');
for (Counter1 = 16; Counter1; Counter1--)
{ByteTemp = GetByte (LongTemp++);
putchar (isprint (ByteTemp) ? ByteTemp : '.');
}
puts (NEWLINE);
}
MemDump = LongTemp;
restore_fc ();
if (Stopped) RunChip (0);
break;
case 'R':
printf ("Resetting Target MCU" NEWLINE );
ResetChip ();
break;
case 'S':
printf ("Single Step" NEWLINE );
StepChip ();
DumpRegisters ();
break;
case 'Q':
QuitFlag = 1;
}
}
DeInit ();
puts (ReturningToDOS);
return 0;
MOTOROLA AN1230/D
14
}
/* GetCommandString returns keyboard entry in buffer, to max length specified */
int GetCommandString (char *where, int count)
{char TempBuffer [MaxBuffer+2];
TempBuffer [0] = count;
strcpy (where, gets (TempBuffer));
puts (NEWLINE);
return TempBuffer [1];
}
AN1230/D MOTOROLA
15
NOTES
Motorola reserves the right to make changes without further notice to any products herein. Motorola makes no warranty, representation or guarantee regarding
the suitability of its products for any particular purpose, nor does Motorola assume any liability arising out of the application or use of any product or circuit, and
specifically disclaims any and all liability, including without limitation consequential or incidental damages. “Typical” parameters can and do vary in different
applications. All operating parameters, including “Typicals” must be validated for each customer application by customer’s technical experts. Motorola does not
convey any license under its patent rights nor the rights of others. Motorola products are not designed, intended, or authorized for use as components in systems
intended for surgical implant into the body, or other applications intended to support or sustain life, or for any other application in which the failure of the Motorola
product could create a situation where personal injury or death may occur. Should Buyer purchase or use Motorola products for any such unintended or
unauthorized application, Buyer shall indemnify and hold Motorola and its officers, employees, subsidiaries, affiliates, and distributors harmless against all claims,
costs, damages, and expenses, and reasonable attorney fees arising out of, directly or indirectly, any claim of personal injury or death associated with such
unintended or unauthorized use, even if such claim alleges that Motorola was negligent regarding the design or manufacture of the part. M is a
registered trademark of Motorola, Inc. Motorola, Inc. is an Equal Opportunity/Affirmative Action Employer.
TO OBTAIN ADDITIONAL PRODUCT INFORMATION:
USA/EUROPE: Motorola Literature Distribution;
P.O. Box 20912; Phoenix, Arizona 85036. 1-800-441-2447
JAPAN: Nippon Motorola Ltd.; Tatsumi-SPD-JLDC, Toshikatsu Otsuki,
6F Seibu-Butsuryu-Center, 3-14-2 Tatsumi Koto-Ku, Tokyo 135, Japan. 03-3521-8315
HONG KONG: Motorola Semiconductors H.K. Ltd.; 8B Tai Ping Industrial Park,
51 Ting Kok Road, Tai Po, N.T., Hong Kong. 852-26629298
MFAX: RMFAX0@email.sps.mot.com - TOUCHTONE (602) 244-6609
INTERNET: http://www.mot.com