This chapter outlines the simple procedures involved in debugging an application with NiceMon.
Here is an example with tips on writing a program that can be debugged with NiceMon.
See Accommodating NiceMon for the list of requirements.
Extra care is needed when modifying registers used by NiceMon. Make sure when using sbit or rbit instructions on registers that NiceMon uses that they don't conflict with the settings required by NiceMon.
Also make sure that registers initialized with X A,## don't conflict with NiceMon settings either. This can be a little tricky. The constant used to initialize the register may need to be different depending on whether NiceMon is used or not.
A convenient way to deal with this problem is to use macros that are conditionally defined for use with or without NiceMon. Example macros are given in debug.inc
; These macros can be used instead of
; loading a constant into a register used
; by NiceMon.
;
; These macros ensure that the configuration will won't
; disturb NiceMon.
.macro NICEMON_CNTRL value
.mloc NICEMON_CNTRL_MASK
.mloc NICEMON_CNTRL_VALUE
NICEMON_CNTRL_MASK = B'11110111
NICEMON_CNTRL_VALUE = B'00001000
.ifdef DEBUG_NICEMON
ld CNTRL,#((value AND NICEMON_CNTRL_MASK) OR NICEMON_CNTRL_VALUE)
.else
ld CNTRL,#value
.endif
.endm
.macro NICEMON_ICNTRL value
.mloc NICEMON_ICNTRL_MASK
.mloc NICEMON_ICNTRL_VALUE
NICEMON_ICNTRL_MASK = B'11110011
NICEMON_ICNTRL_VALUE = B'00000100
.ifdef DEBUG_NICEMON
ld ICNTRL,#((value AND NICEMON_ICNTRL_MASK) OR NICEMON_ICNTRL_VALUE)
.else
ld ICNTRL,#value
.endif
.endm
.macro NICEMON_PSW value
.mloc NICEMON_PSW_MASK
.mloc NICEMON_PSW_VALUE
NICEMON_PSW_MASK = B'11111010
NICEMON_PSW_VALUE = B'00000101
.ifdef DEBUG_NICEMON
ld PSW,#((value AND NICEMON_PSW_MASK) OR NICEMON_PSW_VALUE)
.else
ld PSW,#value
.endif
.endm
.macro NICEMON_PORTGC value
.mloc NICEMON_PORTGC_MASK
.mloc NICEMON_PORTGC_VALUE
NICEMON_PORTGC_MASK = B'10001111
NICEMON_PORTGC_VALUE = B'00010000
.ifdef DEBUG_NICEMON
ld PORTGC,#((value AND NICEMON_PORTGC_MASK) OR NICEMON_PORTGC_VALUE)
.else
ld PORTGC,#value
.endif
.endm
.macro NICEMON_PORTGD value
.mloc NICEMON_PORTGD_MASK
.mloc NICEMON_PORTGD_VALUE
NICEMON_PORTGD_MASK = B'11011111
NICEMON_PORTGD_VALUE = B'00100000
.ifdef DEBUG_NICEMON
ld PORTGC,#((value AND NICEMON_PORTGD_MASK) OR NICEMON_PORTGD_VALUE)
.else
ld PORTGD,#value
.endif
.endm
If the debug macros are used, your program only needs to specify the constants required by your program. The macro will make sure the NiceMon configuration is not disturbed.
Adding the statement DEBUG_NICEMON = 1 will direct the macros to alter the configuration.
NiceMon requires interrupts to operate properly. So your interrupt sub routines must coexist with NiceMon. This fact puts constraints on your program.
NiceMon will enable interrupts when it returns control to the user program. This causes a problem when trying to single step through an interrupt sub routine. When NiceMon returns from a single step it automatically re-enables interrupts, even if interrupts were disabled before NiceMon gained control. The effect of this is that subsequent interrupts will re-enter and restart the interrupt handler.
The interrupt can be debugged if the interrupt source is disabled. The debug.inc include file has a macro that can be used to debug the timer 1a interrupt handler.
; This macro can be used to enable debugging of
; the timer 1a interrupt handler.
;
; If the timer interrupt is disabled, break points
; can be set in the interrupt handler.
;
; NiceMon will enable global interrupts so disabling
; the timer interrupt ensures that subsequent interrupts
; don't mess with the debugging.
;
; The symbol DEBUG_TIMER_1A_ISR must be defined for this
; macro to have an effect.
;
; DEBUG_TIMER_1A_ISR = 1
.macro NICEMON_DEBUG_TIMER_1A_ISR_ENTER
.ifdef DEBUG_NICEMON
.ifdef DEBUG_TIMER_1A_ISR
rbit T1ENA,PSW ; disable timer 1a interrupt
.endif
.endif
.endm
; This macro is used to re-enable
; the timer 1a interrupt
.macro NICEMON_DEBUG_TIMER_1A_ISR_EXIT
.ifdef DEBUG_NICEMON
.ifdef DEBUG_TIMER_1A_ISR
sbit T1ENA,PSW ; enable timer 1a interrupt
.endif
.endif
.endmThe tutorial.asm example shows how this macro can be used.
timer_1a_isr:
NICEMON_DEBUG_TIMER_1A_ISR_ENTER ; this is required to
; debug the interrupt handler
push A ; save A
ld a,B ; save B
push A
ld a,PSW ; save C and HC
push A
ld a,count3
inc a
x a,count3
rbit T1PNDA,PSW ; reset timer 1a pending flag
ld A,PORTD
xor A,#001 ; toggle port D pin 0
x A,PORTD
pop A ; restore C and HC
rc
ld B,#PSW
ifbit 7,A
sbit 7,[B]
ifbit 6,A
sbit 6,[B]
pop A ; restore B
x A,B
pop A ; restore A
NICEMON_DEBUG_TIMER_1A_ISR_EXIT ; this is required to
; debug the interrupt handler
reti