In-Circuit Debugging (ICD) with MPLAB

Versions 2.1.0.0 or higher of the Swordfish compiler now generates a debug file (*.cof) which can be used to single step code and view variables in MPLAB. This article assumes the reader is familiar with the MPLAB environment and has access to a suitable In Circuit Debug (ICD) module. For my tests, I used a Junebug board which is available from Blue Room Electronics*. The Junebug is powered from your computers USB port and is a PICkit 2 compatible programmer and debugger based around the 18F1320 microcontroller. The Swordfish code used is shown later in this article.

*Sadly, Blue Room Electronics no longer seem to be trading. However, this article should still be of use for people wishing to use ICD.

Swordfish as a Language Toolsuite

The first thing you need to do is make sure you have Swordfish installed as a language tool in MPLAB. You can find more information on installing in MPLAB here. Please note that if you already have Swordfish installed as a language tool, you may still need to update the "TLSFBasic.ini" file. This is really important, as MPLAB needs to know that the compiler now generates a *.cof file for debugging. If you are not sure, just open your current "TLSFBasic.ini" and see if has the entry:

 Debug=COF

If it does not you should overwrite the file with the latest set of *.mtc and *.ini files.

Creating a Project

When you have done all the above, you can now create a new project in MPLAB. I used MPLAB version 8.1 - here are the steps used:

  • Create a new project using PROJECT...NEW from the main menu.
  • Select the language tool using PROJECT...SELECT LANGUAGE TOOLSUITE from the main menu
  • Select the correct device (in this case, 18F1320) using CONFIGURE...SELECT DEVICE from the main menu.
  • Select VIEW...PROJECT and under the "Source Files" add your main Swordfish program.

Please note that you should just add the main program to "Source Files". If you have any custom modules you want to add to the project, you should use "Other Files". This is shown in the image to the left.

Your main Swordfish program file should always reside in the same folder as you MPLAB project file. That is, the program in "Source Files" must be in the same folder as the MPLAB *.mcp and *.mcw files. You will know you haven't done this when Swordfish reports a successful build but MPLAB does not! Custom modules under "Other Files" do not have to be held in the same folder as the MPLAB project files. Also remember that MPLAB does not like spaces in path or filenames.

We have now setup a simple project under MPLAB. Next, you need to plug in your ICD board and power it up and select DEBUGGER...SELECT TOOL from the main menu. The Junebug is a Pickit2 compatible programmer and debugger, so that's what is selected.

If all goes well, the following will be displayed in the MPLAB output window:

 Initializing PICkit 2 version 0.0.3.30
 Found PICkit 2 - Operating System Version 2.31.0
 Target power not detected - Powering from PICkit 2 ( 5.00V)
 PIC18F1320 found (Rev 0x7)
 PICkit 2 Ready

Software Requirements

When using ICD, there are a number of things you need to do in software to make sure everything works correctly. These are (a) reserve a few bytes in upper ROM and RAM and (b) enable the DEBUG configuration fuse. Here's how it's done with Swordfish:

#variable _maxram = _maxram - $C    // constrain RAM
#variable _maxrom = _maxrom - $1C0  // constrain ROM
Config DEBUG = ON                   // DEBUG fuse ON

The number of bytes reserved vary from device to device. The values shown above are for the 18F1320, which can be found in the MPLAB online documentation under "HELP...TOPICS...MPLAB ICD2...Resources Used by MPLAB ICD 2". The DEBUG = true configuration fuse is used for ICD. It is very important that the DEBUG configuration is not used if you are building release code or you are not going to use ICD. If this fuse is enabled, your program will not run outside of the ICD environment. The best thing to do is create an #option, so you can easily enable or disable ICD. This is the code I used in the "Junebug.bas" module, shown later:

// if you want to use ICD, then set '#option ICD = true' in your main program
// before you include this module...
#if IsOption(ICD) And ICD
#option ISR_SHADOW = false
#variable _maxram = _maxram - $C    // constrain RAM
#variable _maxrom = _maxrom - $1C0  // constrain ROM
Config DEBUG = ON                   // DEBUG fuse ON

You may also notice I've disabled interrupt shadow registers. According to the Microchip documentation shadow registers can get corrupted when placing a breakpoint in an ISR. This code plays it safe and will context save important registers in software, rather than hardware shadow registers.

Building the Project

Assuming you have carried out all of the above steps, we are now ready to build and debug! The main program and module code for this article can be found here:

To build, either use the menu bar PROJECT...BUILD or press the build icon on the main toolbar. If all goes well, you should see something like:

 Clean: Deleting intermediary and output files.
 Clean: Done.
 Executing: "C:\Program Files\Mecanique\SwordfishSE\SESwordfish.exe" Program.bas -p18F1320
 Swordfish BASIC Compiler (SE) 2.1.0.0 Copyright (c) 2007 Mecanique
 All Rights Reserved.
 ROM used : 497 Bytes (6.42%)
 RAM used : 44 Bytes (18.03%)
 Loaded C:\Program Files\Mecanique\SwordfishSE\Samples\Junebug\Program.COF.
 BUILD SUCCEEDED: Tue Jun 17 09:49:26 2008

in the MPLAB output window. Next, program the code by using DEBUGGER...PROGRAM from the main menu bar or press the "Program Target" toolbar icon. When programming has finished, you can start executing your code by selecting DEBUGGER...RUN from the main menu or by pressing the "Run" toolbar icon.

You can automate all the above steps in MPLAB by selecting DEBUGGER...SETTINGS from the main menu bar and selecting

  • Program after a successful build
  • Run after a successful program

Debugging

You normally add a breakpoint by double clicking on a source code line. Note that when using ICD, you are limited to the number of breakpoints you can use. In the case of the 18F1320 it is one breakpoint. You can add a breakpoint either (a) before you run the ICD process or (b) by pausing the ICD process. In this example, a breakpoint is placed on the following line:

When button 2 of the Junebug board is pressed, the program will stop executing like this:

You can now single step through your code, allowing you to follow the program logic. By selecting VIEW...WATCH from the main toolbar, you can also view variable values:

One feature of ICD is that is uses breakpoint skidding. This means that the debugger halts one address after the actual breakpoint. In most situations you will not notice this as Swordfish, like other high level languages, generates multiple ASM instructions for each high level construct. However, in cases where only one instruction is generated for a high level command, you will see the debugger halt on the instruction following the breakpoint. If this happens, either place your breakpoint earlier in your code or insert a NOP.