Hello,
I have an application utilizing the S08DZ60A microcontroller and the CodeWarrior 6.3 IDE. My application is resetting, and I'm suspecting it's the COP causing the reset. Does anyone have any suggestions for techniques on debugging:
1) where the COP reset is taking place?
2) capturing the SRS register just before reset to verify the source of the reset?
Any helpful tips on debugging COP resets would be greatly appreciated.
Thanks,
~belskyc
Solved! Go to Solution.
Hi Belskyc,
Here is the routine. It is pretty straightforward. Each system has about 20 MCUs in a networked environment, and this code is common to them all (both HC08s and S08s), but "ErrLog" is a macro specific to the circumstances of each MCU. The argument of ErrLog is in a common definition file.
This routine runs early in the startup code.
; ; ; ; Report the reason for this reset. ; LogReset: lda SRS ;get System Reset Status Register sta ACCUM0 ;store in page zero where we can bit-test brset SRS.PIN,ACCUM0,lr_1 ;SRSR: External Pin reset brset SRS.COP,ACCUM0,lr_2 ;SRSR: Computer Operating Properly reset brset SRS.ILOP,ACCUM0,lr_3 ;SRSR: Illegal Opcode reset brset SRS.ILAD,ACCUM0,lr_4 ;SRSR: Illegal Address reset brset SRS.POR,ACCUM0,lr_5 ;SRSR: Power-On Reset brset SRS.LVD,ACCUM0,lr_6 ;SRSR: Low Voltage Detect reset brset SRS.ICG,ACCUM0,lr_7 ;SRSR: Internal Clock Generation reset ; ErrLog E_ResetNONE ;report no Reset bits set rts ;return ; lr_1: ErrLog E_ResetPIN ;report External Reset Pin rts ;return ; lr_2: ErrLog E_ResetCOP ;report COP Counter Timout Reset rts ;return ; lr_3: ErrLog E_ResetILOP ;report Illegal Opcode Reset rts ;return ; lr_4: ErrLog E_ResetILAD ;report Illegal Address Reset rts ;return ; lr_5: ErrLog E_ResetPOR ;report Power-On Reset rts ;return ; lr_6: ErrLog E_ResetLVI ;report Low Voltage Detect Reset rts ;return ; lr_7: ErrLog E_ResetMonMod ;report Clock Generation reset rts ;return ;
Hi Belskyc,
You don't need to capture the SRS prior to the reset, as the SRS reflects the cause of the previous reset. I have a routine that runs after every reset and logs the cause. I can provide it if you want, but it is in assembly language.
As for determining where the code is getting hung-up and causing the watchdog to timeout, that is trickier. My approach is to disable the watchdog, and wait for the code to hang. Then issue a stop and look where the PC is. It was much easier with the HC08, where you could simply monitor the address-bus while the code was running.
Hi rocco,
Thanks for the reply. I'd be very interested in taking a look at this reset logging routine of yours. Could you please send it?
Also, good idea on disabling the Watchdog and seeing where the code hangs up. I'm going to try this.
Thanks,
~belskyc
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
Thanks to both rocco & bigmac for the COP debugging techniques. I was able to implement a simple C-routine that read the SRS early in startup and capture the SRS status bits leading me to the cause of my COP resets. For anyone that's interested, one thing I learned was that the SRS register is cleared with a read (at least on the S08DZ60A), so make sure to capture the SRS on the first read, and definitely make sure not to pet the watchdog (write to SRS) before reading the SRS status.
Regards,
~belskyc
Hello,
belskyc wrote:
For anyone that's interested, one thing I learned was that the SRS register is cleared with a read (at least on the S08DZ60A), so make sure to capture the SRS on the first read, and definitely make sure not to pet the watchdog (write to SRS) before reading the SRS status.
If this is true, it would indicate a serious omission from the datasheet/reference manual. However, it is documented that a reset initiated by the BDM will result in all SRS bits being cleared.
Regards,
Mac
Hi Belskyc,
Here is the routine. It is pretty straightforward. Each system has about 20 MCUs in a networked environment, and this code is common to them all (both HC08s and S08s), but "ErrLog" is a macro specific to the circumstances of each MCU. The argument of ErrLog is in a common definition file.
This routine runs early in the startup code.
; ; ; ; Report the reason for this reset. ; LogReset: lda SRS ;get System Reset Status Register sta ACCUM0 ;store in page zero where we can bit-test brset SRS.PIN,ACCUM0,lr_1 ;SRSR: External Pin reset brset SRS.COP,ACCUM0,lr_2 ;SRSR: Computer Operating Properly reset brset SRS.ILOP,ACCUM0,lr_3 ;SRSR: Illegal Opcode reset brset SRS.ILAD,ACCUM0,lr_4 ;SRSR: Illegal Address reset brset SRS.POR,ACCUM0,lr_5 ;SRSR: Power-On Reset brset SRS.LVD,ACCUM0,lr_6 ;SRSR: Low Voltage Detect reset brset SRS.ICG,ACCUM0,lr_7 ;SRSR: Internal Clock Generation reset ; ErrLog E_ResetNONE ;report no Reset bits set rts ;return ; lr_1: ErrLog E_ResetPIN ;report External Reset Pin rts ;return ; lr_2: ErrLog E_ResetCOP ;report COP Counter Timout Reset rts ;return ; lr_3: ErrLog E_ResetILOP ;report Illegal Opcode Reset rts ;return ; lr_4: ErrLog E_ResetILAD ;report Illegal Address Reset rts ;return ; lr_5: ErrLog E_ResetPOR ;report Power-On Reset rts ;return ; lr_6: ErrLog E_ResetLVI ;report Low Voltage Detect Reset rts ;return ; lr_7: ErrLog E_ResetMonMod ;report Clock Generation reset rts ;return ;