Hello belskyc,
Like Rocco, I have had occasion to chase the cause of unexpected resets for an assembly program, and to distinguish between COP, ILAD, and ILOP resets. In my situation, if one of these events did occur, I report a message string to the SCI at the conclusion of initialisation, just prior to entering the main loop.
I have also developed a means of reporting the start address of the application subroutine being executed when the reset occurred.
A debug subroutine GET_CALL is called using a macro RSDEBUG, and this may be used by including the macro name right at the start of each application subroutine you wish to test. The purpose of the debug subroutine is to derive from the stack, the address at which the debug subroutine is called, and to store this to a memory location. If the call occurs at the beginning of the application subroutine, the stored address will be that of the application subroutine (as would be listed in a symbol table).
As each monitored subroutine is executed, the stored address would normally be updated. However, should one of the error reset conditions occur, we require to inhibit further updates until the stored address can be examined. This is achieved using a control flag that is manipulated by a further debug sub-routine DB_CTRL, that would be called early in the initialisation process, before other subroutines (or ISRs), that might need to be monitored, are called.
;_DEBUG_ ; Enable reset source debugRSDEBUG: MACRO ; Reset source debug macro IFDEF _DEBUG_ JSR GET_CALL ; Get address of this call ENDIF ENDM
; Debug RAM variables: IFDEF _DEBUG_DBADDR DS.W 1 ; Debug: SR return addressDBFLAG DS.B 1 ; Debug control flag ENDIF
;**************************************************************; DEBUG PROCESS:;**************************************************************; RESET DEBUG CONTROL; A zero value in DBFLAG prevents over-write of stored address; value after an ILAD, ILOP or COP error reset occurs.RST_MASK EQU mSRS_ILAD|mSRS_ILOP|mSRS_COP ; Reset maskDB_CTRL: IFDEF _DEBUG_ CLRX LDA SRS AND #RST_MASK ; Reset mask BNE *+3 ; Skip next if error reset INCX ; Enable address update STX DBFLAG ENDIF RTS;-------------------------------------------------------------- IFDEF _DEBUG_; GET ADDRESS OF THIS SUBROUTINE CALLGET_CALL: PSHX ; Save current values PSHH LDX DBFLAG BEQ SRR1 ; Exit if flag is clear LDHX 3,SP AIX #-3 ; Address at start of call STHX DBADDR ; Save value to RAMSRR1: PULH ; Restore original values PULX RTS ENDIF
For completeness, the subroutines that I used to display both the reset type and the last subroutine address -
IFDEF _DEBUG_; DISPLAY CALL ADDRESS (HEXADECIMAL)DSP_CALL: LDA DBADDR PSHA NSA BSR DISPHEX PULA BSR DISPHEX LDA DBADDR+1 PSHA NSA BSR DISPHEX PULA BSR DISPHEX LDA #' ' JSR PUTCHR LDA DBFLAG+1 PSHA NSA BSR DISPHEX PULADISPHEX: ; Display hexadecimal digit AND #$0F ADD #'0' CMP #'9' BLS *+4 ADD #7 JSR PUTCHR ; Put character to FIFO buffer RTS ENDIF;--------------------------------------------------------------; DISPLAY RESET TYPEDISP_RST: IFDEF _DEBUG_ SEND_STR RST_TYPE ; Reset type LDX #RESET_EV ; First reset type POR LDA SRS ; System reset statusDR1: LSLA BCS DR2 ; Branch if status bit is set INCX ; Next reset type TSTA ; Test for remaining bit active BNE DR1 ; Loop for next bit if so RTS DR2: ; X = message index value JSR SENDSTR ; Send string data to FIFO buffer LDA DBFLAG BNE *+5 ; Skip next if non-zero JSR DSP_CALL ; Display SR call address LDA #1 ; Revert to normal flag state STA DBFLAG ENDIF RTS
I guess that it is possible that the code could be adapted for C usage. However the returned address would likely differ from the function address listed in the map file. This is because there will be intervening code to store parameters and create local variables on the stack.
Regards,
Mac