MOTOROLA Order this document by: A N 1 2 3 0 / D SEMICONDUCTOR 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 simplify 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 development, 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 singlechip 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, examining 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 microcontroller family. Thus any MCU that incorporates one of these processor modules includes the BDM interface. 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). (c) MOTOROLA INC, 1996 BDM OPERATION Background debug mode is a special mode of operation of the CPU module. Three pins provide the hardware 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 Motorola 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 configuration shown in Table 1 be used to connect the MCU to an external host. This configuration is used by Motorola 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 3 VSS 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 5 VSS 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 8 IFETCH/DSI (CPU32) IPIPE0/DSI (CPU16) Used to track instruction pipe in normal mode. Serial data input to target from MCU in BDM 9 VCC +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 MOTOROLA 2 AN1230/D 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 impractical. 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. VDD 4 PC PRINTER PORT 17 3 MC74HC76N PRE 2 1 J CLR 16 K Q CLK BDM CONNECTOR 14 1 1 .001 F 2 MC74HC132AN 4 3 B A 5 1 DS 4 BERR 6 4 BKPT/ DSCLK 14 7 RESET 6 FREEZE 15 16 11 10 10K 8 1N4148 12 18 11 D 12 0.1 F 13 VDD IFETCH/DSI 5 GND 9 VDD 3 GND 10 IPIPE/DSO PC/BDM CONN Figure 1 Public Domain BDM Interface Circuit AN1230/D MOTOROLA 3 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: Table 2 Status Bits Returned from GetStatus () Bit Position Symbolic Name (in 'trgtstat.h') Bit 0 TARGETRESET Bit 2 Description 1 if target in reset state (RESET = 0) TARGETSTOPPED 1 if target in background mode (FREEZE = 1) Bit 3 Bit 4 TARGETPOWER 1 if no power applied to target TARGETNC 1 if BDM interface cable is disconnected Public-Domain Interface ICD Interface Yes No Yes Yes Yes No Yes No 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 () resumes 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 attribute, represented by the function code value that is driven out on the FC[2:0] pins during the MCU memory 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. MOTOROLA 4 AN1230/D 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 contents of the specified target register and returns it to the calling routine. However, if the target MCU is executing 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 monitor RAM locations as the processor executes code, or to profile MCU code execution by periodically sampling 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 cable 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 error 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. AN1230/D MOTOROLA 5 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 depending upon whether the target system is an M68300 or M68HC16 device. The file bdm-util.c contains routines 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 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 targets, 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 defined. 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 access. Should be included into user code if program must read Srecord 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. 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. textio.h Table 4 contains a detailed BDM driver function reference. MOTOROLA 6 AN1230/D Table 4 BDM Driver Package Function Reference Prototype Description Return Value #include "bdmcalls.h" Checks the PC's BIOS data tables for the number The return value has one bit set for each parallel port (LPT1-LPT3) of parallel printer ports installed in the PC; returns which is in- stalled in the PC, i.e. bit a bit vector representing which parallel ports unsigned ValidPorts 0 is set if LPT1 is installed, bit 1 for (LPT1, LPT2, and LPT3) are installed. (void); LPT2, and bit 2 for LPT3. #include "bdmcalls.h" The desired port (1 through 3, for LPT1 through Returns a non-zero value if the iniLPT3 respectively) is checked for validity, and if tialization failed for any reason, available will be initialized to the desired bit rate to int Init (unsigned such as printer port not installed. communicate with the BDM interface circuit. Port, unsigned Speed); 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#include "bdmcalls.h" pervisor data), and 6 (supervisor code). The default is 5 (supervisor data). If an invalid code is Nothing. passed, the function code will remain at its previvoid SetFC (void); ous setting. Note: for M68HC16 microcontrollers, only 5 and 6 are valid. #include "bdmcalls.h" Restores the parallel port hardware to its original state before Init () was called. This function Nothing. should be called by user code before the program void DeInit (void); exits to DOS. 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: #include "bdmcalls.h" Returns a bit vector representing the current status of the target MCU. Some error conditions are TARGETRESET: Target is in reset not detectable by both hardware interfaces. state unsigned GetStatus Therefore, only those errors which can be detect- TARGETHALT: Target is (void); ed by the interface in use will actually be reported. halted TARGETSTOPPED: Target is in FREEZE state TARGETINVALID: Target interface is not initialized 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: #include "bdmcalls.h" Returns a bit vector representing which bits are unsignedGetStatusMask valid in the return value of GetStatus (). (void); 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" Non-zero if the target was running when StopChip () was called; otherwise zero. Stops (places into FREEZE state) target MCU. int StopChip (void); AN1230/D MOTOROLA 7 Table 4 BDM Driver Package Function Reference (Continued) Prototype Description Return Value #include "bdmcalls.h" Single-steps target MCU by one instruction. Nothing. Forces hardware reset on target MCU; leaves MCU in running state. Nothing. void StepChip (void); #include "bdmcalls.h" void ResetChip (void); Resets target MCU, and stops execution on first #include "bdmcalls.h" 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- Nothing. void RestartChip serted on the target MCU to bring it into BDM; else (void); if the public-domain circuit is used, DriverError () will be called with the appropriate error. #include "bdmcalls.h" Starts execution of target MCU at address specified by 'where'. If 'where' is 0, execution starts at Nothing. address contained in Program Counter of target void RunChip (LONG MCU. where); #include "bdmcalls.h" #include "regs-16.h" Retrieves and returns the contents of the target (or) CPU register indicated by 'which'. Symbolic val#include "regs-32.h" ues for the register codes are defined in the file 'regs-16.h' (CPU16 targets) and 'regs32.h' (CPU32 targets). LONG GetReg (unsigned which); The data contained in the specified register. #include "bdmcalls.h" #include "regs-16.h" Writes the value 'data' into the target CPU register (or) indicated by 'which'. Symbolic values for the reg#include "regs-32.h" ister codes are defined in the file 'regs-16.h' Nothing. (CPU16 targets) and 'regs-32.h' (CPU32 targets). void PutReg (unsigned which, LONG data); #include "bdmcalls.h" LONG GetByte (LONG Where); #include "bdmcalls.h" LONG GetWord (LONG Where); #include "bdmcalls.h" LONG GetLong (LONG Where); Returns contents of byte-adPerforms a byte read on the specified memory lo- dressed memory at location cation and returns value retrieved. 'Where'. Values returned are 00xff. Returns contents of word-adPerforms a word read on the specified memory lo- dressed memory at location 'Where'. Values returned are 0cation and returns value retrieved. 0xffff. Returns contents of longword-adPerforms a longword read on the specified memdressed memory at location ory location and returns value retrieved. 'Where'. Performs a byte read on the specified memory location and returns value retrieved. On CPU16 targets, this call is identical to GetByte (). On CPU32 targets, a special BDM command #include "bdmcalls.h" is used which is faster than a normal memory access. Returns contents of byte-addressed memory at location GetByte (), GetWord (), or GetLong () LONG DumpByte (LONG should be called first, to set the initial address for 'Where'. Values returned are 0-0xff. Where); memory subsequent memory writes; then any number of DumpByte (), DumpWord (), or DumpLong () calls may be made to read from following locations of memory. MOTOROLA 8 AN1230/D Table 4 BDM Driver Package Function Reference (Continued) Prototype Description Performs a word read on the specified memory location and returns value retrieved. On CPU16 targets, this call is identical to #include "bdmcalls.h" GetWord (). On CPU32 targets, a special BDM command is used which is faster than a normal memory access. GetByte (), GetWord (), or LONG DumpWord (LONG GetLong () should be called first, to set the initial Where); 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. Return Value Returns contents of word-addressed memory at location 'Where'. Values returned are 00xffff. Performs a longword read on the specified memory location and returns value retrieved. On CPU16 targets, this call is identical to GetLong (). On CPU32 targets, a special BDM command #include "bdmcalls.h" is used which is faster than a normal memory acReturns contents of longword-adcess. dressed memory at location GetByte (), GetWord (), or GetLong () should 'Where' LONG DumpLong (LONG be called first, to set the initial address for memory Where); subsequent memory writes; then any number of DumpByte (), DumpWord (), or DumpLong () calls may be made to read from following locations of memory. #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 Nothing. the value 'Data' #include "bdmcalls.h" void PutLong (LONG Where, LONG Data); Performs a longword write at location 'Where', writing the value 'Data'. Nothing. 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 #include "bdmcalls.h" is used which is faster than a normal memory access. Nothing. PutByte (), PutWord (), or PutLong () should void FillByte (LONG be called first, to set the initial address for memory Where, BYTE Data); subsequent memory writes; then any number of FillByte (), FillWord (), or FillLong () calls may be made to write to following locations of memory 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 #include "bdmcalls.h" is used which is faster than a normal memory access. Nothing. PutByte (), PutWord (), or PutLong () should void FillWord (LONG be called first, to set the initial address for memory Where, WORD Data); subsequent memory writes; then any number of FillByte (), FillWord (), or FillLong () calls may be made to write to following locations of memory AN1230/D MOTOROLA 9 Table 4 BDM Driver Package Function Reference (Continued) Prototype Description Return Value Performs a longword write at location 'Where', writing the value 'Data'. On CPU16 targets, this call is identical to #include "bdmcalls.h" PutLong (). On CPU32 targets, a special BDM command is used which is faster than a normal memory access. PutByte (), PutWord (), or Nothing. void FillLong (LONG PutLong () should be called first, to set the initial Where, LONG Data); 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 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 "bdmutil.h". When do_srec () returns indicating either no error or SREC_S9 (end of file record), the structure '*where' contains the following information: #include"bdm-calls.h" where->rectype holds the contents of the S#include "bdm-util.h" 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 #include field and should be ignored; types 7, 8, and 9 are end-of-file records, causing do_srec to return int do_srec (srecord SREC_S9 instead of 0.) *where, FILE *infile); where->reclen holds the contents of the record length field of the S-record. where->address holds the contents of the address 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 include 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 status is not an error, but rather an indication that the last record was read from the file, and the user program should not continue to call do_srec (). #include"bdm-calls.h" Writes the data contained in data->bytes to mem#include "bdm-util.h" ory in the target system, at the address specified by data->address plus load_offset. Type 0 Nothing. void put_srec (srecord records are ignored; type 7, 8, and 9 records cause the global variable ExecuteAddress to be *data, LONG set to the value data->address plus load_offset. load_offset); #include"bdm-calls.h" #include "bdm-util.h" 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 tarint do_load (LONG load_offset, char *in- get memory using put_srec (). filename); MOTOROLA 10 Returns the same error codes as do_srec (), with one addition: if the file specified by 'infilename' cannot be opened, do_load returns the value -1. AN1230/D 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 * examine and change memory and * Functions which are common to * test16.c and test32.c contain */ #include #include #include #include #include #include #include "bdmcalls.h" #include "trgtstat.h" #include "bdmerror.h" #include "bdm-util.h" #include "textio.h" #define MaxBuffer monitor program which will allow the user registers, start/stop/reset/single step, etc. both CPU32 and CPU16 targets are in this file the code specific to the target 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); AN1230/D MOTOROLA 11 } 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': MOTOROLA 12 AN1230/D RestartChip (); case case 'D': DumpRegisters (); break; '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; AN1230/D MOTOROLA 13 } /* 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]; } MOTOROLA 14 AN1230/D NOTES AN1230/D MOTOROLA 15 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: JAPAN: HONG KONG: MFAX: INTERNET: Motorola Literature Distribution; P.O. Box 20912; Phoenix, Arizona 85036. 1-800-441-2447 Nippon Motorola Ltd.; Tatsumi-SPD-JLDC, Toshikatsu Otsuki, 6F Seibu-Butsuryu-Center, 3-14-2 Tatsumi Koto-Ku, Tokyo 135, Japan. 03-3521-8315 Motorola Semiconductors H.K. Ltd.; 8B Tai Ping Industrial Park, 51 Ting Kok Road, Tai Po, N.T., Hong Kong. 852-26629298 RMFAX0@email.sps.mot.com - TOUCHTONE (602) 244-6609 http://www.mot.com