Sun Mar 20 22:54:22 EDT 2011

Unofficial PIC18 BDM debug module desciption

Jaromir Sukuba has published some info on the PIC18 in-circuit
debugger functionality[1].  Great!

[1] http://jaromir.xf.cz/hdeb/bdm/bdm.html

Here's a mirror:


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:

    * disabling all code protect bits in configuration bytes

    * programming DEBUG configuration bit  into logical 0 (this forces
      RB6 and RB7 to debug IO pins)

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

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).

bit 7	bit 6	bit 5	bit 4	bit 3	bit 2	bit 1	bit 0

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 POR TB,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 7	bit 6	bit 5	bit 4	bit 3	bit 2	bit 1	bit 0
?	?	?	?	BKA19	BKA18	BKA17	BKA16

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

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

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