ISD51: Introduction

Introduction

ISD51 (In-System Debugger) is a new debug monitor technology for 8051 user programs. ISD51 consists of a configurable library that you link with your application program to provide debug support via the 8051 on-chip UART.

The software and hardware requirements of ISD51 are minimal. It can run from external or on-chip CODE space and requires no special hardware components like von Neumann-wired memory.

ISD51 works on both very small 8051 devices like the Philips LPC series and on complete systems that have access to the full CODE and XDATA address space.

Copyright (c) Keil Software, Inc. All rights reserved.


ISD51: What's New

What's New

The current release of ISD51 (Version 2) adds the following features:

  • Flash Breakpoints
  • User I/O via the Serial Debug Interface.
  • Address Range Setting for Memory Verify (using the CMP_START and CMP_END #defines ISD51.H).


ISD51: Features

Features

ISD51 provides the following features:

  • Controlled program execution with single-stepping and multiple software breakpoints.
  • Ability to view and change CPU registers and memory.
  • Access to Special Function Registers (SFRs).
  • Full speed program execution when no software breakpoints are set. Hardware breakpoints do not affect execution speed.
  • Support for Flash breakpoints on most devices. Flash breakpoints do not significantly affect execution speed.
  • Support for hardware breakpoint registers that are available on some 8051 variants.
  • Support for user serial I/O via the debugging interface.


ISD51: Requirements

Requirements

  • MCU with 100% 8051-compatible instruction set.
  • One 8051-compatible on-chip UART.
  • 500-700 bytes of program code—depending on the number of SFRs.
  • Six (6) bytes stack space.
  • One (1) byte IDATA RAM.
  • Two (2) bytes IDATA RAM for each software breakpoint defined. Hardware breakpoints and Flash breakpoints require no additional RAM.


ISD51: Restrictions

Restrictions

  • Extended 8051 instruction sets are not supported. ISD51 cannot be used with the Philips 80C51MX or the Dallas 390/3240/400 Devices.
  • Code banking is not supported. ISD51 cannot be used with code banking programs.
  • PDATA variables cannot be reviewed.
  • Breakpoints and single-stepping do not work in interrupt service routines unless hardware breakpoints or Flash breakpoints are used.


ISD51: Benefits

Benefits

  • No special hardware modifications to your target system are required.
  • ISD51 may be used with any standard 8051 derivative.
  • Program code can be stored in on-chip Flash/EPROM/ROM or in off-chip EPROM.
  • No von Neumann memory, no XDATA space, no registers, and no bit-addressable space is required.
  • ISD51 may be linked and shipped with the final end-product. ISD51 firmware is royalty-free.
  • ISD51 protects your software investment since it may only be used when the original source code is available.


ISD51: Availability

Availability

ISD51 is available starting with C51 Version 6.23. It is available only in the PK51 Professional Developer's Kit.


ISD51: Theory of Operation

Theory of Operation

ISD51 adds a serial interrupt function (the ISD51 Interrupt) for the 8051 UART to your user program. When ISD51 connects to the µVision2 Debugger, the 8051 enters the ISD51 interrupt function. While program execution is stopped, the 8051 program runs only the ISD51 interrupt function. When the µVision2 Debugger issues a Go command, the 8051 exits the ISD51 interrupt function and executes the user program.

If no breakpoints are set or if only hardware breakpoints or Flash breakpoints are set, the 8051 executes the user program at full speed. Flash breakpoints are easily configured for many 8051 devices with IAP and Flash block sizes 128 bytes and smaller.

If software breakpoints are set, the 8051 enters the ISD51 interrupt function after each 8051 CPU instruction. The ISD51 interrupt checks to see if the 8051 program reached a breakpoint address and, if so, begins communication with the µVision2 Debugger. 8051 programs execute considerably slower (about 100x) when software breakpoints are used.

The µVision2 Debugger sends an 0xA5 character to the ISD51 interrupt function to halt the user program and start communication with the debugger. Therefore, the 8051 program must be started when the µVision2 Debugger is invoked.


ISD51: Breakpoints

Breakpoints

ISD51 supports three different breakpoint technologies:

  • Hardware Breakpoints use special on-chip breakpoint registers found on some devices.
  • Flash Breakpoints use IAP (In-Application Programming) to replace breakpoint instructions with CALL instructions into ISD51.
  • Software Breakpoints are tested after each program instruction.

The following table lists the advantages and limitations of each breakpoint type.

Breakpoint Type | Advantages | Limitations
Hardware | Fast program execution speed. | Few breakpoint registers. Only available on some devices.
Flash | Fast program execution speed. | CALL instruction replaces three program bytes. Only available on some Flash devices.
Software | Supported on all devices. | Slow program execution speed.


ISD51: Hardware Breakpoints

Hardware Breakpoints

Hardware Breakpoints use special on-chip breakpoint registers found on only a few devices. Microcontrollers with hardware breakpoint registers support only a few breakpoints (typically 1-4). But, they require almost no overhead and allow programs to execute at full speed.

ISD51 currently supports hardware breakpoints on the TI MSC1210 devices. This feature must be enabled in the ISD51.H header file using the TI_MSC1210_BREAKS #define.

When this feature is enabled, hardware breakpoints may be used with these TI devices.

Known Issues

Following is a list of issues with hardware breakpoints on the MSC1210 devies:

  • Program execution may stop up to two CPU instructions after a breakpoint. This is a chip limitation and not a limitation of the software.
  • The Read and Write attributes are ignored for XDATA access breakpoints. Program execution stops on any access to the specified address.
  • Hardware breakpoints require use of the interrupt 6 vector (address 0x33). Unfortunately, this interrupt is also used for other on-chip peripherals such as the A/D Converter, (milli)second timer, PFI, and SPI interface. ISD51 redirects interrupts for these peripherals to interrupt 13 (address 0x6B). If your application uses peripherals that generate interrupt 6, you must change your interrupt service routine to use interrupt 13 instead.
  • Program execution may stop on the wrong address due to instruction prefetches. When a prefetch occurs on a break address, the breakpoint is triggered even when the instruction is not executed. This can happen in the following situations:
    1. Breakpoint after a loop:
      void func(void) {
  while(...) {
    ...;
  }
  ...;        // a breakpoint here may be triggered...
              // even when the loop has not completed
}
    2. Breakpoint at the beginning of a function:
      void func1(void) {
...
}

void func2(void) {  // a breakpoint here may be triggered
                    // when the CPU is at the end of func1
...
}

      Note

      • The linker does not locate functions in ascending sequence. Therefore, the function order in the C source module may not match the order in which functions are stored in memory. Review the function segment information in the linker map (*.M51) file or use the disassembly window to determine the function order in memory.
    3. Breakpoint after a function call:
      void func1(void) {
...
  func2();
...         // a breakpoint here may be triggered
            // at the beginning of func2
}

      Note

      • This affects the Step-Over command which inserts a breakpoint after CALL instructions. The CPU may stop at the beginning of the called function.


ISD51: Flash Breakpoints

Flash Breakpoints

Flash Breakpoints use IAP (In-Application Programming) to replace breakpoint instructions with CALL instructions into the ISD51 code. Flash breakpoints are supported on all devices that offer IAP and have relatively small Flash block sizes (128 bytes or less). Numerous Flash breakpoints can be enabled simultaneously. They require almost no overhead and allow programs to execute at full speed.

When you set a Flash breakpoint, ISD51 modifies the code memory and inserts a CALL instruction at the breakpoint address. When the breakpoint is reached, ISD51 is invoked (by the CALL). Run-time address checking (which is what software breakpoints do) is not required.

To use Flash breakpoints, you must configure ISD51 for your target MCU. There is a place in the ISD51.H header file where you may configure the Flash block size and the algorithm to program a block.

CBLK_SZ specifies the flash block size in bytes. If it is 0, Flash breakpoints are not enabled. If it is non-zero, a memory buffer (named CBLK) is reserved in IDATA for a single Flash block.

The CWRITE macro defines the flash erase and programming function. On entry, A contains the MSB and R0 contains the LSB of the Flash memory block to reprogram with data from the CBLK buffer. You must write the code that reprograms the Flash block.

Note

  • Example configurations for the Infineon C868, Philips LPC900, and TI MSC1210 include Flash breakpoints.

Known Issues

To perform a Flash breakpoint, ISD51 inserts a CALL instruction in the user program at the breakpoint address. This avoids extra hardware for the breakpoint logic. However, the CALL instruction occupies up to three bytes and may therefore cause side-effects when set before a label (jump target) on one-byte and two-byte CPU instructions. For example:

0100  E4        CLR     A
0101  74 03     MOV     A,#3
   .    .        .
   .    .        .
   .    .        .
0110  80 ED     SJMP    0101
  1. The user program executes to address 0x110. The next single-step will execute the SJMP 0101 instruction.
  2. A breakpoint is set at address 0x100 by writing a CALL instruction into the user program. The user program is modified as follows:
    0100  XX        LCALL           ; A CALL instruction is
0101  XX XX     ???             ; written at address 0x100.
   .    .        .
   .    .        .
   .    .        .
0110  80 ED     SJMP    0101
  3. When the user program continues execution at address 0x110 the program jumps to address 0x101. But, this memory location was modified when the breakpoint was set at address 0x100. The MOV A,#3 instruction is no longer in program memory and is not the instruction executed. And, the behavior of the user program is unpredictable.

To avoid this problem, in C applications use the disassembly window and check to see if the instruction sequence described above exists. The following C statements may cause such side-effects:

  • Breakpoint near the beginning of a loop. For example:
      while (...) {
    // Breakpoints near the beginning of
    // a loop start may cause problems.
    ...;
  }
  • Breakpoint near the end of a function. For example:
    void func1(void) {
  ...
}
    // Breakpoints near the end of a function
    // may modify the beginning of the next function.

void func2(void) {
  ...
}

Note

  • The linker does not locate functions in ascending sequence.


ISD51: Software Breakpoints

Software Breakpoints

ISD51 supports software breakpoints for all devices. When you set a software breakpoint, the breakpoint address is added to a table that ISD51 must check for each instruction that is executed. This check is performed in the ISD51 Interrupt.

If ISD51 detects that a software breakpoint has been reached, it begins communication with the µVision2 Debugger.

Note

  • Software breakpoints in ISD51 cause programs to execute considerably slower (about 100x) than normal.
  • Software breakpoints and single-stepping do not work in interrupt service routines.


ISD51: Side-Effects

Side-Effects

Debugging programs with ISD51 has some side-effects.

  • Hardware breakpoints and Flash breakpoints always work-even when the interrupt system is disabled. However, singled-stepping and software breakpoints work only when the ISD51 interrupt and the global interrupt system are enabled. You may, of course, disable ISD51 operation during critical program sections.
  • ISD51 allows breakpoints even in ROM. If software breakpoints are set, the 8051 program runs under control of the ISD51 interrupt function and execution speed is degraded about 100x (programs run 100 times slower).
  • Breakpoints and single-stepping are not possible in 8051 interrupt functions that have the same or higher interrupt priority level than the ISD51 interrupt.
  • If the ISD51 interrupt is enabled, it is possible to stop the 8051 program execution from within the µVision2 Debugger using the Stop toolbar button.


ISD51: Program Integration

Program Integration

The following steps are required to integrate ISD51 features into your application and debug using the µVision2 Debugger.

  1. Configure and include the ISD51 files in your project.
  2. Build the user program and burn it into the 8051 device with programming utilities like the Flash utilities from the silicon vendor, download programs from evaluation board providers, or an EPROM device programmer.
  3. Configure the µVision2 IDE and Debugger to use ISD51.

Programs that demonstrate how to add ISD51 capability are provided in the \KEIL\C51\ISD51\EXAMPLES folder.


ISD51: Software Configuration

Software Configuration

To add ISD51 support to your embedded application, you must:

  1. Copy ISD51.A51 and ISD51.H from the \C51\ISD51 folder into your project folder.
  2. Add ISD51.A51 to your µVision2 Project.
  3. Add ISD51.H to the C module that contains the main C function (using #include "ISD51.H").
  4. Check the configuration settings in ISD51.H and modify them, if necessary, to match your target hardware. The default configuration is suitable for classic 8051 devices with 256 bytes of on-chip DATA/IDATA and a standard 8051-compatible on-chip UART.
  5. Add serial port and baud rate initialization code for the on-chip UART to your C main function. You may copy this from the \KEIL\C51\EXAMPLES\HELLO example program.
  6. Add the appropriate ISD51 startup function to your C code.
    • ISDinit: Initializes ISD51 and starts user program. When the µVision2 Debugger connects, program execution halts.
    • ISDwait: Initializes ISD51 and waits until the µVision2 Debugger connects.
    • ISDcheck: Checks to see if the µVision2 Debugger has connected with the 8051. If so, the ISD51 interrupt is initialized. ISDcheck must be called periodically. You can do this in the main loop of your embedded application.

Sharing the ISD51 Serial Debug Interface

Your user program may share the serial port with ISD51. All serial I/O from your program is sent to and read from the Serial Window in the µVision2 Debugger.

To enable serial port sharing, you must enable the ISD51 serial I/O routines (putchar and _getkey) using the ISD_PUTCHAR and ISD_GETKEY #defines in ISD51.H. Once enabled, functions like printf and getchar communicate via the Serial Window. Since the UART is already configured for ISD51 communication, no additional initialization is required. In addition to the standard putchar ad _getkey functions, ISD51 also offers an _iskey function you may use to test for an available character to receive.


ISD51: Project Configuration

Project Configuration

Once you have added ISD51 to your program, you must configure the µVision2 IDE and Debugger for communication with the 8051 target system.

  1. Start the 8051 application on the target system before you start the µVision2 Debugger.
  2. In µVision2, select Project - Options for Target - Debug: Use: Keil ISD51 In-System Debugger.
  3. Enable Load Application at Startup so that the µVision2 Debugger loads the symbolic information for your 8051 program.
  4. Disable Go till main. Your user program is started by the hardware reset of the 8051 target system.
  5. Click Settings to open the ISD51 Driver Settings dialog and configure the ISD51 Options

COM Port Settings

These options configure how the PC serial port communicates with your target hardware.

  • Port: PC COM port used to connect to the 8051 target hardware.
  • Baudrate: Communication baud rate with the 8051 target hardware.
  • RTS Logical and DTR Logical: Level on the RTS or DTR lines of the COM Port.
    • Always High (Active): Signal is always active during µVision2 Debugger communication.
    • Always Low (Inactive): Signal is always inactive during µVision2 Debugger communication.
    • Reset High 500ms (Active): Signal is active for 500 mSec on Reset Command of µVision2 Debugger.
    • Reset Low 500ms (Inactive): Signal is inactive for 500 mSec on Reset Command of µVision2 Debugger.
    • Reset Pulse: 500ms High, 10ms Low: Signal is active for 500 mSec then inactive for 10ms on Reset Command of µVision2 Debugger.
    • Reset Pulse: 500ms Low, 10ms High: Signal is inactive for 500 mSec then active for 10ms on Reset Command of µVision2 Debugger.

Cache Options

The ISD51 driver implements memory caches to speed-up screen updates.

  • Disable the cache options to view actual (un-cached) values of DATA (and SFR), IDATA, or XDATA space when you halt program execution. This way you can be certain you are viewing the current values of I/O ports, timers, or memory-mapped peripherals.
  • Enable the cache options to obtain maximum performance.

Code Breakpoint Options

This option selects whether or not ISD51 uses software breakpoints, hardware breakpoints, or a combination of both.

  • If your target 8051 device does not support hardware breakpoints, you must select software breakpoints only.
  • If your target 8051 device supports hardware breakpoints, you must use software breakpoints when no hardware breakpoints are available.

Miscellaneous Options

  • Verify if Application in ROM is identical to current Project: Selects whether or not the µVision2 ISD51 Debugger Driver compares the program code in the 8051 target with the program code of the current project when initializing ISD51 communications. You may disable this option to speed-up the connection time of the debugger with the target system.

    If you do not wish to compare the entire application range or if your application contians configuration areas that should be excluded, you may configure the verify address range with CMP_START and CMP_END in the ISD51.H header file.

ISD51 Identification

This box displays the version number and other status information when the µVision2 Debugger connects to the ISD51 running on the 8051 target system. You may check this information when you open the ISD51 Driver Settings dialog during debugging.


ISD51: Debugging

Debugging

Once the µVision2 Debugger is configured, you may start debugging with Debug - Start/Stop Debug Session. The µVision2 Debugger connects to the 8051 target system via the ISD51 software.

ISD51 supports most µVision2 Debugger features. For instance, you may single-step through code, set breakpoints, and run your application. Variables may be viewed using the standard debugger features.

Note

  • It is not possible to use Debug - Memory Map to change the memory mapping of the 8051 system. The memory mapping of the 8051 target system depends on hardware components.
  • The Performance Analyzer and Code Coverage functions of the µVision2 Debugger are not available with ISD51.
  • The Periodic Window Update Option in the µVision2 Debugger may not be used with ISD51.


ISD51: Troubleshooting

Troubleshooting

If the µVision2 Debugger does not connect to the ISD51 hardware, you should first verify that the target system's serial interface is correctly configured. You may check this with the µVision2 Simulator as follows:

  1. Select Project - Options for Target - Debug: Use Simulator.
  2. Start program simulation with Debug - Start/Stop Debug Session. This loads the user program in simulation mode.
  3. Start running the user program (Debug - Go).
  4. Verify the settings of the UART with the Serial Port Dialog (Peripherals - Serial). The baud rate is displayed correctly if you have entered the correct XTAL frequency in Project - Options for Target - Target - XTAL. Typically, the baud rate does not match the PC baud rate 100%, but it should be within 2%.
  5. Check serial communications:
    • Open the serial communication window (View - Serial Window).
    • Right-click in the Serial Window and select Hex Mode from the context menu.
    • Enter sin=0xA5 in the Command Window to Input a 0xA5 character in the serial input stream.
    The µVision2 Simulator should then simulate the IDS51 interrupt and display 0xF7 followed by six more hex values in the serial window.

If everything is correctly configured and you are still unable to connect to the IDS51 hardware, try invoking the following function after initializing the serial interface.

/*
* Test Function:
* Verify serial communication with HyperTerminal
*/

void TestSerial (void) {
  char c = 'A';

  TI = 1;
  while (1) {
    if (RI) {
      c = SBUF;
      RI = 0;
    }

  while (!TI);

  TI = 0;
  SBUF = c;
  }
}

This function outputs a character via the 8051 on-chip serial port. The character A is transmitted initially. If a character is received on the 8051's serial port, that character is then transmitted.

You may use a terminal program like HyperTerminal to verify that the 8051 transmits the letter A and that other characters you type are echoed.


ISD51: Function Reference

Function Reference

The following pages describe the ISD51 In-System Debugger functions. These functions are listed in alphabetical order and each is divided into several sections:

Summary: | Briefly describes the routine's effect, lists include file(s) containing its declaration and prototype, illustrates the syntax, and describes any arguments.
Description: | Provides a detailed description of the routine and how it is used.
Return Value: | Describes the value returned by the routine.
See Also: | Names related routines.
Example: | Gives a function or program fragment demonstrating proper use of the function.


ISD51: _iskey

_iskey

Summary
#include "isd51.h"

bit _iskey (void);
Description The _iskey routine is an ISD51 function that checks to see if a serial character is ready for the user program.

Note

  • To use this function in your ISD51 Applications, you must enable the ISD51 putchar and _getkey functions using the ISD_PUTCHAR and ISD_GETKEY defines in ISD51.H.
Return Value The _iskey routine returns a value of 0 if no input character is available or a value of 1 if an input character is available.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51.
--------------------------------------------*/
Init_UART ();
ISDinit ();

while (1)
  {
  unsigned char c;

  while (!_iskey())
    {
    }

  c = _getkey();
  printf ("I got a %c\n", c);
  }
}


ISD51: ISDbreak

ISDbreak

Summary
#include "isd51.h"

void ISDbreak (void);
Description | The ISDbreak routine forces execution of the ISD51 interrupt function. This allows you to hard-code breakpoints into your target program. Communication must be established with the µVision2 Debugger before you invoke this routine.
Return Value | None.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51 and wait until the
uVision2 Debugger starts.
--------------------------------------------*/
Init_UART ();
ISDwait ();

while (1)
  {
  ISDbreak();   // Halt here
  .
  .
  .
  }
}


ISD51: ISDcheck

ISDcheck

Summary
#include "isd51.h"

void ISDcheck (void);
Description | The ISDcheck routine checks to see if the µVision2 Debugger is trying to connect with the target system. If it is, ISD51 is initialized for communication. If you use ISDcheck to initialize ISD51, your program must periodically invoke it.
Return Value | None.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51.
--------------------------------------------*/
Init_UART ();
ISDinit ();

while (1)
  {
/*--------------------------------------------
Check to see if the uVision2 Debugger started.
--------------------------------------------*/
  ISD_check();
  .
  .
  .
  }
}


ISD51: ISDdisable

ISDdisable

Summary
#include "isd51.h"

void ISDdisable (void);
Description | ISDdisable function disables the ISD51 interrupt. If you use this routine to disable the ISD51 interrupt you must use ISDenable to re-enable it.
Return Value | None.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51 and wait until the
uVision2 Debugger starts.
--------------------------------------------*/
Init_UART ();
ISDwait ();

while (1)
  {
  ISDdisable ();  // Begin critical section
  .
  .
  .
  ISDenable ();   // End critical section
  .
  .
  .
  }
}


ISD51: ISDenable

ISDenable

Summary
#include "isd51.h"

void ISDenable (void);
Description | ISDenable enables the ISD51 interrupt. If you use ISDdisable to disable the ISD51 interrupt, you must use ISDenable to re-enable it.
Return Value | None.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51 and wait until the
uVision2 Debugger starts.
--------------------------------------------*/
Init_UART ();
ISDwait ();

while (1)
  {
  ISDdisable ();  // Begin critical section
  .
  .
  .
  ISDenable ();   // End critical section
  .
  .
  .
  }
}


ISD51: ISDinit

ISDinit

Summary
#include "isd51.h"

void ISDinit (void);
Description | The ISDinit routine initializes ISD51 for communication with the µVision2 Debugger. It does not wait for communication to be established. After invoking this routine, your target program continues execution normally.
Return Value | None.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51.
--------------------------------------------*/
Init_UART ();
ISDinit ();

while (1)
  {
/*--------------------------------------------
Check to see if the uVision2 Debugger started.
--------------------------------------------*/
  ISD_check();
  .
  .
  .
  }
}


ISD51: ISDwait

ISDwait

Summary
#include "isd51.h"

void ISDwait (void);
Description | The ISDwait routine initializes ISD51 for communication with the µVision2 Debugger and waits until communication is established. This function returns after the µVision2 Debugger connects with ISD51.
Return Value | None.
Example
#include "isd51.h"

void main (void)
{
.
.
.
/*--------------------------------------------
Initialize the 8051 UART.
Then, initialize ISD51 and wait until the
uVision2 Debugger starts.
--------------------------------------------*/
Init_UART ();
ISDwait ();

while (1)
  {
  .
  .
  .
  }
}