Unofficial PIC18 BDM debug module desciption


This page contains material which is derived partly from public domain information, but mostly guessed only. It seems to work, however.
Use this information at your own risk, for personal research and personal use only. Author is not responsible for any damage, like broken PICs, crashed computers, sleepless nights, unsatisfied wives etc...
No commercial use allowed.

Microchip encorporates background debug module (BDM) module in all PIC18F devices, enabling them to be debugged in circuit. First device having BDM on board was PIC16F877 and derivatives - and this is the last device with offcial BDM module description. Following devices kept this secret, also all members of newer PIC families were released without description how their debug module works. I'll try to do this for PIC18 devcies in this document.

Entering debug mode

For using debug mode, two conditions had to be satisfied:
There is reset (POR, MLCR or by executing RESET instruction) after programming, before entering debug mode.
Actual entering debug mode is done in one of four ways:
  1. by introducing 1->0 transition on RB6 pin
  2. on POR/MCLR reset
  3. on breakpoint
  4. or after executing any instruction while single stepping is active
First two conditions can be achieved without prior entering debug mode, another two (setting breakpoint or enabling single stepping) are possible only during debug mode.
Entering BDM means entering vector at address 0x200028. There must be instruction to jump at address in valid FLASH range, where debug executive resides.

Leaving debug mode

Once debug mode entered, it can be left by executing undocumented TRET instruction. This instruction seems to be identical to RETURN instruction, but it also clears DEBUG, INBUG bit. Opcode for TRET is 0x00E1.

BDM registers

BDM is controlled by one main register and three shadow registers.
Main control register of BDM is DEBUG register at address 0xFD4 (notice gap at SFR map in all PIC18F devices).

DEBUG (0xFD4)
bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
INBUGFRZSSTPSHDWBRB7BRB6BTS7BTS6

INBUG - this readable bit is set in debug mode and clear during executing user code
FRZ - this bit is clear by default. Setting this bit enables peripheral freezing in debug mode
SSTP - this bit is clear by default. Setting this bit enables single step operation. After return from debug mode, only one instruction will be executed before entering debug mode again.
SHDW - this bit is clear by default. Setting this bit enables shadow registers BDMSR0, BDMSR1, BDMSR2
BRB7 - bit to manipulate RB7 in debug mode, without affecting actual content of  PORTB,7 register
BRB6 - bit to manipulate RB6 in debug mode, without affecting actual content of  PORTB,6 register
BTS7 - bit to manipulate TRISB7 in debug mode, without affecting actual content of  TRISB,7 register
BTS6 - bit to manipulate TRISB6 in debug mode, without affecting actual content of  TRISB,6 register

There are also at least three shadow registers, accessible only when DEBUG,SHDW bit is set:

BDMSR2 (0xFB9)
bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
????BKA19BKA18BKA17BKA16

BDMSR1 (0xFB8)
bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
BKA15BKA14BKA13BKA12BKA11BKA10BKA9BKA8

BDMSR0 (0xFB7)
bit 7bit 6bit 5bit 4bit 3bit 2bit 1bit 0
BKA7BKA6BKA5BKA4BKA3BKA2BKA1BKA0

BKA[19..0] forms 20 bit wide register, holding address of breakpoint. When PC=BKA, BDM takes control and debug mode is entered.
? fields are bits with unknown meaning, for now. Don't touch it.

Communication with target device

All communication with target device is done by RB6 and RB7 lines and MCLR.
Before entering debug mode, target device (TD) has to be programmed using ICSP, so debugger implemntation has to contain also programmer implementation. Except of user code, TD has to have two additional regions programmed - debug vector and debug executive, for PIC18Fxxxx devices. For PIC18FxxJxx devcies, there are differences, covered later.
Debug executive (DE) is program, which takes control after entering debug mode by BDM in TD. Its function is to communicate with debugger by RB6 and RB7 lines, using custom protocol. BDM does not support this communication by any way other than providing bits to manipulate with those pins and appropriate TRIS bits (see description of DEBUG register). Best place for DE is last few pages of FLASH memory, in order to not interfere with user program. Properly written DE can be smaller than 512B, or 256 program words.
Debug vector (DV) is single instruction to redirect program execution into DE after entering debug mode. Memory region where DV resides, is ordinary FLASH block and must be erased and written in the same way as any other FLASH block. For PIC18FxxJxx devices, region where DV resides, is larger and complete DE will fit here (If you look at MPLAB help, you can find table about which resourced are consumed in order to use ICD. Those ones with no FLASH consumed allow to put complete DE into DV region).
After programming (using ICSP) user code, DE and DV, MCLR has to be toggled to start execution of code. After reset, BDM takes control, forces PC to DV, where it executes instruction to enter DE in FLASH memory. Here is the point, where DE takes control and is fully responsible for communication with debugger. The same process is executed after introducing falling edge at RB6 pin, while running user code (this can be used to stop program flow). In all cases, except of POR or MCLR RESET, before forcing PC to DV, current PC value s saved on stack and stack pointer is incremented, so that TRET instruction can revert PC value to point before execution interrupt. After POR or MCLR reset, stack pointer is equal to zero, so TRET instruction can't do this. Because of this, DE has to check stack pointer and when it is equal to zero (situation after MCLR or POR reset), it has to increase stack pointer and clear TOSL, TOSH and TOSU registers - this forces PC return to correct address 0 after leaving DE.
It is good idea to use both RB6 and RB7 pins to create simple bidirectional synchronous (in order to be not dependant on target clock) serial protocol.
From protocol point of view, DE could be quite simple. Reading and writing registers, FLASH and EEPROM should be implemented, along with setting breakpoint address or single stepping. On debugger side, it is a bit more complicated.

What is missing here

As a lot of those information are guessed only, it is incomplete. For example, I don't know how to set more than one breakpoint - for devices which allow more than one breakpoint.
If you have further information to improve this document, contact me.


How to...

I made small handheld debugger which allows editing source code, assembling it, flashing into program memory and debugging of PIC18xxxx, PIC18FxxJxx and PIC18FxxKxx devices. It employs all priciples described above, you can find also source codes for both DE and debugger part.


Updated 18.3.2011
Back to P18debug