;---------------------------------------------------------------------------
; reserved access bank locations
- udata_acs
+ udata_acs
+psave_intcon res 1
+psave_bsr res 1
+
+panicst res 1
+panicst_restart_i2c equ 7
+panicst_acked equ 5
+panicst_ferroerr equ 4
+panicst_writeslave equ 3
+panicst_i2cmours equ 2
+panicst_i2cmenable equ 1
+
+panic_valcount res 1
+
+panic_vars_section udata 0x060 + maxpics ; not available via access bank
; used in panic routine for temporary storage:
flash_pattern res 1
panic_morse res 1 ; # bytes of morse msg in panic readout
panic_regs res 1 ; # registers in panic readout
+t0l_count res 1
+t0h_count res 1
+
+psave_latc res 1
+psave_t res 1
+psave_tablat res 1
+psave_tblptr res 3
+psave_fsr0 res 2
+psave_fsr1 res 2
+psave_prod res 2
+psave_stkptr res 1
+
+stack_depth equ 31
+panic_stack res stack_depth*3
;****************************************************************************
- code
+pan_ code
;****************************************************************************
-panic_routine
+
+panic_routine @
; switch off interrupts and power
; reconfigure timer0 for writing diagnostic msg to the LED
- clr_f INTCON ; disable all interrupts EVER
- bc_f PORTC,1 ; switch off booster
+ mov_ff INTCON, psave_intcon
+ bc_f INTCON, GIEH ; disable all interrupts
-; now we have time to copy the panic message address out of WREG
-; (turning off interrupts is urgent (we might get interrupted while
+ mov_ff BSR, psave_bsr
+ banksel flash_pattern
+
+ mov_ff LATC, psave_latc
+
+; now we have time to save registers etc
+; (turning off interrupts is urgent: we might get interrupted while
; panicing which would be bad because we might forget to panic).
mov_wf panic_address
-
-; re-initialise timer0 config
- bc_f T0CON,6 ; p107 Timer0 -> 16bit mode
- bc_f T0CON,5 ; timer0 use internal clock
- bc_f T0CON,3 ; use prescaler
- bc_f T0CON,2 ; }
- bs_f T0CON,1 ; } prescale value 1:16 (13ms x 16)
- bs_f T0CON,0 ; }
+ mov_ff t, psave_t
+ mov_ff TABLAT, psave_tablat
+ mov_ff TBLPTRL, psave_tblptr
+ mov_ff TBLPTRH, psave_tblptr+1
+ mov_ff TBLPTRU, psave_tblptr+2
+ mov_ff FSR0L, psave_fsr0
+ mov_ff FSR0H, psave_fsr0+1
+ mov_ff FSR1L, psave_fsr1
+ mov_ff FSR1H, psave_fsr1+1
+ mov_ff PRODL, psave_prod
+ mov_ff PRODH, psave_prod+1
+ mov_ff STKPTR, psave_stkptr
+
+ mov_lfsr panic_stack + stack_depth*3 - 1, 0
+ mov_lw stack_depth
+ mov_wf STKPTR
+stacksave_loop
+ mov_ff TOSU, POSTDEC0
+ mov_ff TOSH, POSTDEC0
+ mov_ff TOSL, POSTDEC0
+ dec_f_ifnz STKPTR
+ bra stacksave_loop
+
+ clr_f STKPTR ; avoids stack overruns
+ clr_f panicst
+
+ call panic_kill_hook
+
+; re-initialise timer0 config, etc.
+ call read_pic_no
+ bra_z panic_setup_if_master
+ ; must be slave:
+
+panic_setup_if_slave
+ movlw (1<<TMR0ON) | morse_slave_t0scale
+ movwf T0CON
+ movlw morse_slave_t0inith
+ movwf t0h_count
+ movlw morse_slave_t0initl
+ movwf t0l_count
+
+ bra panic_setup_endif_masterslave
+
+panic_setup_if_master
+ movlw (1<<TMR0ON) | morse_master_t0scale
+ movwf T0CON
+ movlw morse_master_t0inith
+ movwf t0h_count
+ movlw morse_master_t0initl
+ movwf t0l_count
+
+ pin_l p0_booster_userfault
+
+ mov_lw 0x0b ; AAARGH
+ bt_f_if1 TXSTA, TXEN
+ call serial_write_char
+;...
+panic_setup_endif_masterslave
; get # bytes of morse msg, # registers in panic readout, message start addr.
; back from condensed message start addr. stored in panic_address
tblrd *+ ; read 1st byte of error message
; (gives # bytes morse, # bytes registers)
+ dw 0xffff ; silicon errata: B4 issue 4
mov_ff TABLAT,panic_morse
mov_lw 00001111b
swap_f panic_regs ; panic_regs now contains # registers to read
call led_black
- call waiting
- call waiting
- call waiting
- call waiting
- call morsemsg ; transmit morse in red
+ rcall waiting16
+ rcall morsemsg ; transmit morse in red
call led_black
- call waiting
- call waiting
- call waiting
- call waiting
- call registermsg ; transmit contents of registers in
+ rcall waiting8
+ rcall waiting4
+ rcall registermsg ; transmit contents of registers in
; red(=low) and blue(=high)
- goto panic_loop
+ rcall waiting16
+ bra panic_loop
;****************************************************************************
; PANIC SUBROUTINES
tblrd *+
mov_ff TABLAT,flash_pattern
- call morse_readout
+ rcall morse_readout
inc_f morse_counter
- goto morse_loop
+ bra morse_loop
;--------------------------
; flash_pattern flash pattern preserved
; bit_counter any undefined
- mov_lw 8
+ mov_lw 9
mov_wf bit_counter
rr_f flash_pattern
call led_red
morse_readout_endif_led
+ rcall waiting
bra morse_readout_loop
;--------------------------
clr_f FSR0H ; for insns using Access Bank)
mov_ff INDF0,flash_pattern
- call register_readout
+ rcall register_readout
inc_f register_counter ;increment loop counter
- call waiting
- call waiting
- goto register_loop
+ rcall waiting8
+ bra register_loop
;--------------------------
mov_lw 4
cmp_fw_ifne bit_counter ; if loop counter !=4 (nybble length),
; skip insertion of extra black space
- goto not_nybble_boundary
- call waiting
+ bra not_nybble_boundary
+ rcall waiting4
not_nybble_boundary
rl_f flash_pattern ; top bit goes into N flag,
register_readout_endif_led
inc_f bit_counter ; increment loop counter
- call waiting
+ rcall waiting
call led_black
- call waiting
+ rcall waiting
bra register_readout_loop
; GENERAL SUBROUTINES
;----------------------------------------
+waiting16 rcall waiting8
+waiting8 rcall waiting4
+waiting4 rcall waiting2
+waiting2 rcall waiting
waiting
; waits for a fixed interval, depending on the configuration of TMR0
+ bt_f_if1 idloc1,idloc1_master
+ pin_z p0_booster_userfault
+
bc_f INTCON,2 ; clear timer0 interrupt bit (p109)
- clr_f TMR0H ; p107 set high byte of timer0 to 0 (buffered,
+; Interrupt happens on overflow. So start at 65535-morse_t0cycles:
+ mov_fw t0h_count
+ mov_wf TMR0H ; p107 set high byte of timer0 (buffered,
; only actually set when write to tmr0l occurs)
- clr_f TMR0L ; set timer0 low byte - timer now set to 0000h
-waiting_loop
- bt_f_if0 INTCON,TMR0IF
- bra waiting_loop ; wait for timer0 interrupt
- return
+ mov_fw t0l_count
+ mov_wf TMR0L ; set timer0 low byte - timer now set
+waiting_loop ; wait for timer0 interrupt, or some other interrupt
+ bt_f_if1 INTCON,TMR0IF
+ return
+ bt_f_if1 idloc1, idloc1_master
+ bra waiting_master
+ ; slave:
+
+ bt_f_if0 SSPCON1, SSPEN
+ bra waiting_loop ; no readouts if i2c is disabled
+ ; slave, i2c enabled:
+
+ bt_f_if1 PIR1, SSPIF
+ call pan_i2cs_interrupt
+
+ bra waiting_loop
;****************************************************************************
+; MEMORY READOUT - CRASH DUMP
+
+;----------------------------------------
+; MASTER'S PANIC SERIAL PORT HANDLING
+
+;--------------------
+waiting_master
+ bt_f_if1 PIR1,RCIF ; host sent us something ?
+ call panicd_serialrx
+
+ bt_f_if0 SSPCON1, SSPEN
+ bra waiting_loop
+ ; master, i2c enabled:
+
+ bt_f_if0 panicst, panicst_i2cmenable
+ bra waiting_loop
+
+ bt_f_if1 PIR1, SSPIF
+ rcall pan_i2cm_interrupt
+
+ bra waiting_loop
+
+;----------
+panicst_oerrferr
+ mov_fw RCREG
+ xor_lw 0x11
+ bra_z panic_reset
+ xor_lw 0x10 ^ 0x11
+ bra_nz panicd_serialrx_err_loop
+ ; yay! host ack'd ferr/oerr
+ bc_f panicst, panicst_ferroerr
+ return ; return from panicd_serialrx
+
+;----------
+panicd_serialrx_err
+ bs_f panicst, panicst_ferroerr
+ bc_f RCSTA, RCEN ; disable } to clear FERR/OERR
+ mov_fw RCREG ; read RCREG } (see PIC18FXX8 DS p182)
+ bs_f RCSTA, RCEN ; reenable }
+panicd_serialrx_err_loop
+ bt_f_if0 PIR1, RCIF ; wait for a byte 0x10 to ack the overrun/error
+ bra panicd_serialrx_err_loop
+;...
+;----------
+panicd_serialrx
+ pin_nz p0_booster_userfault
+ bt_f_if1 RCSTA,FERR
+ bra panicd_serialrx_err
+ bt_f_if1 RCSTA,OERR
+ bra panicd_serialrx_err
+ bt_f_if1 panicst, panicst_ferroerr
+ bra panicst_oerrferr
+
+ mov_fw RCREG
+ bra panicd_process_input_byte
+
+;----------------------------------------
+; CRASHREAD MASTER/SLAVE COMMON COMMAND BYTE HANDLING
+
+;----------
+pan_i2csu_write_data
+ call led_green
+panicd_process_input_byte
+; W instruction from host or master
+ tst_w_ifnz
+ bra write_ifnot_00
+ ; we've received 0x00:
+
+ mov_lfsr 0,1
+ bs_f panicst, panicst_acked
+ return
+
+;----------
+write_ifnot_00
+ bt_f_if0 panicst, panicst_acked ; well, ignore that !
+ bra write_only_tellmode
+ ; OK, we have an instruction:
+
+ bt_w_if1 7 ; huh?
+ bra write_if_setbytetowrite
+ bt_w_if1 6
+ bra panic_crashread_setpointer
+ bt_f_if0 idloc1,idloc1_master
+ bra write_ifnot0_ifnotmaster
+ ; the next few options are for master only:
+
+ bt_w_if1 5
+ bra write_if_master_slaveselect
+ bt_w_if1 4
+ bra write_if_master_masterread
+ bt_w_if0 3
+ bra write_if_master_slaveread
+;...
+write_ifnot0_ifnotmaster
+ xor_lw 0x09
+ bra_z panic_reset
+ xor_lw 0x09
+;...
+write_only_tellmode
+ xor_lw 0x0a
+ bra_z panic_tellmode
+ ; nope, well, we ignore it
+ return
+
+;----------
+panic_crashread_setpointer
+; W byte from master or host undefined
+; FSR1* crashread pointer updated
+; t, STATUS, PROD* any undefined
+; all others any preserved
+ mov_wf t
+ mov_lw 1<<6
+ mul_wf FSR1L
+ mov_ff PRODH, FSR1H
+ mov_fw t
+ and_lw 0x3f
+ ior_wfw PRODL
+ mov_wf FSR1L
+panic_noop
+ return
+
+;======================================================================#
+; SPECIAL COMMANDS 0x08..0x0f
+
+;----------
+panic_reset
+ reset
+
+;----------
+panic_tellmode
+ bt_f_if0 idloc1,idloc1_master
+ return
+ mov_lw 0x0b
+ bc_f panicst, panicst_acked
+ goto serial_write_char
+
+;======================================================================
+; MASTER READOUT AND MASTER READOUT OF SLAVES
+
+;----------
+write_if_setbytetowrite
+ bt_f_if0 idloc1,idloc1_master
+ return ; for master only
+
+ bc_w 7
+ mov_wf panic_valcount
+ bs_f panicst, panicst_writeslave
+ bs_f panicst, panicst_i2cmenable
+ return
+
+;----------
+write_if_master_slaveread
+ mov_wf panic_valcount
+ bc_f panicst, panicst_writeslave
+ return
+
+;----------
+write_if_master_slaveselect
+ bc_w 5
+ btg_w 4
+ bs_f panicst, panicst_i2cmours
+ bt_f_if1 panicst, panicst_writeslave
+ bra pan_i2cm_write_start
+ bra pan_i2cm_read_start
+
+;----------
+write_if_master_masterread
+ bc_w 4
+ mov_wf panic_valcount
+write_if_master_masterread_loop
+ mov_fw POSTINC1
+ call serial_write_char
+ dec_f_ifnz panic_valcount
+ bra write_if_master_masterread_loop
+ return
+
+;----------
+pan_i2cmu_read_got_byte
+ bt_f_if0 panicst, panicst_i2cmours
+ return
+ call serial_write_char
+ dec_f_ifnz panic_valcount
+ bra pan_i2cm_read_another
+ return
+
+;----------
+pan_i2cmu_write_next_byte
+ mov_fw panic_valcount
+ bc_f STATUS, Z
+ bt_f_if0 panicst, panicst_i2cmours
+ retlw 0x00
+ bt_f_if0 panicst, panicst_writeslave
+ bs_f STATUS, Z
+ bc_f panicst, panicst_writeslave
+ return
+
+;----------
+pan_i2cmu_done
+ mov_lw ' '
+ goto serial_write_char
+
+;----------
+pan_i2cmu_slave_no_ack
+ i2cpanic morse_SP
+
+;======================================================================
+; SLAVE I2C
+
+pan_near_i2csu code
+;----------
+pan_i2csu_write_begin
+ return
+;----------
+pan_i2csu_read_begin
+ mov_lw 0x80 ; M0000000
+ bt_f_if0 panicst, panicst_acked
+ goto i2cs_read_data
+;...
+i2csu_read_panicd_ok
+ mov_fw POSTINC1
+ goto i2cs_read_data
+
+;----------
+pan_i2csu_read_another
+ bt_f_if1 panicst, panicst_acked
+ bra i2csu_read_panicd_ok
+ ; not ok
+ mov_lw 0x0b ; AARGH
+ goto i2cs_read_data
+
+near_gots code
+;----------
+got_aargh @
+ panic morse_T
+
+command_crashed_section code 0x2100
+;----------
+command_crashed @
+panic_crashread_commanded @
+ panic morse_E
+
+;***************************************************************************
include final.inc