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:
- 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:
- by introducing 1->0 transition on RB6 pin
- on POR/MCLR reset
- on breakpoint
- 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 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| INBUG | FRZ | SSTP | SHDW | BRB7 | BRB6 | BTS7 | BTS6 |
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 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 |
| BKA15 | BKA14 | BKA13 | BKA12 | BKA11 | BKA10 | BKA9 | BKA8 |
BDMSR0 (0xFB7)
| bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| BKA7 | BKA6 | BKA5 | BKA4 | BKA3 | BKA2 | BKA1 | BKA0 |
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