Detecting the cause of a reset/restart
Morgan Olsson [morgans.rt at telia.com] Morgans Reglerteknik, Hällekås, 277 35 KIVIK, SWEDEN tel +46(0)414-446620, fax +46(0)414-672324 Says:
If I implement a "system health scanner", and it detects a corrupted register, a routine finding an anomalyty, strange error, or something... Then i want to reboot the system immediately rather than wait for watchdog.So I want to effectively assert a hardware reset signal, that is guaranteed to reset every pheripheral, also any state that is not writeable as register.
If we can force Wdog reset we can also do some tricks:
There are in the PIC status bits that can tell wether it was a Watchdog reset. So the boot rotine checks that, and if it finds it was a watchdog reset it continues by reading a special flag that we keep clear always except we set it just before we force a watchdog reset. That flag might even be a whole register loaded with a message code from the routine that triggered the reset, and the boot routine may then report or log the specific error, or decide to do a special fastboot or whatever.
I have implemented the suggestion of Simon Nield, that makes it insensitive of the level and use of Porta pin 4 by sensing, adapting, and then retries if RA4 changed and made it fail this time.
To top it off, it is now failsafe even if PA4 has some signal/noise of a frequency that makes even the x number of retries fail and then reverts to just waiting for normal Watchdog reset at shortest prescaler.
LIST messg " * FAST FORCED RESET * prototyping file, revision 2.0 " messg " This program resets the PIC 31k times/second @ 4MHz Xtal " messg " Rigorously tested on an PIC16F877 datecode 9921BSL " messg " Morgan Olsson, morgans.rt@telia.com, November 2000 " NOLIST ;******************************* CONFIGURE *********************************** list p=16f877 __CONFIG _CP_OFF & _WDT_ON & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _DEBUG_ON & _CPD_OFF errorlevel -306 ;no Crossing page boundary warnings errorlevel -302 ;no bank warnings radix dec ;********************************** DEFINITION FILES ************************* include p16f877.inc LIST ;********************************** REGISTERS ******************************** T1 EQU 0x20 ;general Temporary register 1 ;********************************** RESET ************************************ ORG 0x000 nop ;Needed for ICD debugger clrf PCLATH goto Init ;********************************* INTERRUPT ********************************* ORG 0x004 goto $ ;if false interrupt stop here to indicate (never happens) ;********************************* INIT ************************************** Init: clrf STATUS ;Set up watchdog realistically as we normally use it clrwdt movlw b'11011101'; TMR0 on fosc/4, prescaler /32 to Watchdog movwf OPTION_REG ;PortE is used for monitoring clrf PORTE bsf STATUS,RP0 ;Bank 1 movlw b'00000010' ;Make Port E a digital port, movwf ADCON1 ;not analog inputs! ;-Indicator of personal taste. (PortE is made output later, see below) bcf STATUS,RP0 ;Bank 0 bsf PORTE,2 ;********************************* FAST RESET ********************************* ;Design Morgan Olsson, morgans.rt@telia.com FastReset: ;-Prepare clrf INTCON ;disable interrupts ;(Just to avoid spending time in an int) clrwdt ;without this line the reset fails peridically -with the ;wdog freqency- probably depending on Wdog OSC output phase. ;-some undocumented connection. movlw 3 ;max number of tries (use higher value in final code!) movwf T1 ;loop counter (works first time if RA4 is steady) FastResetLoop: ;-Setup registers bcf STATUS,RP0 ;Bank 0 movlw (1<<NOT_RBPU)|(1<<INTEDG)|(1<<T0CS)|(1<<T0SE)|(0<<PSA)|(0<<PS0) ; ( = set prescaler in from RA4 XOR T0SE, T0SE=High and prescale select = "/2") btfsc PORTA,4 ;Read state of the XOR gate's input from PA4, xorlw (1<<T0SE) ;set the other XOR input so XOR output is "1" bsf STATUS,RP0 ;Bank 1 movwf OPTION_REG ;Effectuate the setup bcf STATUS,RP0 ;Bank 0 clrf TMR0 ;clear prescaler (also TMR0, but irrelevant) ;-Now clock the prescaler by toggling T0SE, thus prescaler input go from 1 to 0 bsf STATUS,RP0 ;Bank 1 movlw (1<<T0SE) xorwf OPTION_REG,F ;-For testing, make Port E outputs in order to measure time from here, clrf TRISE ;until reset tristates portE again! ;Measured: 6 Xtal OSC cycles. Note; clrf effectuates ;during Q4, next instr during Q4 in next cycle, and from there ;to reset it is obviously only 2Q or one half instr time :) ;-Now the prescaler output apparently is "1", because... bsf OPTION_REG,PSA ;...assigning it to wdt cause immediate reset! ;--- if it did not work (maybe PORTA,4 have changed during this process): --- bcf STATUS,RP0 ;Bank 0 ;-Indicator of personal taste: bsf PORTE,1 ;FastReset failed at least once ;-Retry a few times! ;It might fail due to RA4 is changing, therefor we try again, but not forever! decfsz T1, F goto FastResetLoop ;-Indicator of personal taste: bsf PORTE,0 ;FastReset failed, waiting for Watchdog goto $ ;As last resort leave the Wdog in peace to time out as normal ;with shortest prescaler (already selected above). ;Because we are fiddling with the prescaler in the routine, and there are ;already some undocumented effects, and may be more, I do not feel sure that ;the watchdog will time out during theese conditions, therefor we just wait. ;Hard testing has proven it works as described! ;Testing have been performed feeding RA4 with 50% duty cycle square wave, ;sweeping from DC and up, and using max three tries (setting T1 = 3) ;The routine then begin "failing" (getting to goto $ and using normal Wdog) ;at first at about 22kHz, and then working again at 30-31kHz, then... etc. ;(all at 4MHz Xtal) ;Increasing the number of retries will narrow the non-working frequency bands, ;and increase the frequency of first "failure", thus increasing functionality. ;WATCHDOG NEED TO BE ENABLED IN CONFIG DIRECTIVE (AND/OR PROGRAMMER) END
See: