chiark / gitweb /
service mode factory reset
[trains.git] / detpic / panic.asm
1 ;======================================================================
2 ; panic.asm
3 ;
4 ; This file implements panic_routine, which is called by the
5 ; `panic' macro in panic.inc.  See panic.inc for the functionality
6 ; of `panic'.
7
8         include common.inc
9
10 ;---------------------------------------------------------------------------
11 ; reserved access bank locations
12
13   udata_acs
14
15 psave_intcon    res     1
16 psave_bsr       res     1
17
18 panicst                         res     1
19 panicst_restart_i2c             equ     7
20 panicst_acked                   equ     5
21 panicst_ferroerr                equ     4
22 panicst_writeslave              equ     3
23 panicst_i2cmours                equ     2
24 panicst_i2cmenable              equ     1
25
26 panic_valcount                  res     1
27
28 panic_vars_section udata 0x060 + maxpics ; not available via access bank
29 ; used in panic routine for temporary storage:
30
31 flash_pattern           res     1
32 morse_counter           res     1
33 register_counter        res     1
34 bit_counter             res     1
35
36 panic_address   res     1       ; condensed form of message start addr.
37 panic_morse     res     1       ; # bytes of morse msg in panic readout
38 panic_regs      res     1       ; # registers in panic readout
39
40 t0l_count       res     1
41 t0h_count       res     1
42
43 psave_latc      res     1
44 psave_t         res     1
45 psave_tablat    res     1
46 psave_tblptr    res     3
47 psave_fsr0      res     2
48 psave_fsr1      res     2
49 psave_prod      res     2
50 psave_stkptr    res     1
51
52 stack_depth     equ     31
53 panic_stack     res     stack_depth*3
54
55 ;****************************************************************************
56
57 pan_ code
58
59 ;****************************************************************************
60
61
62 panic_routine @
63 ; switch off interrupts and power
64 ; reconfigure timer0 for writing diagnostic msg to the LED
65
66         mov_ff  INTCON, psave_intcon
67         bc_f    INTCON, GIEH   ; disable all interrupts
68
69         mov_ff  BSR, psave_bsr
70         banksel flash_pattern
71
72         mov_ff  LATC, psave_latc
73
74 ; now we have time to save registers etc
75 ; (turning off interrupts is urgent (we might get interrupted while
76 ;  panicing which would be bad because we might forget to panic).
77
78         mov_wf   panic_address
79
80         mov_ff  t, psave_t
81         mov_ff  TABLAT, psave_tablat
82         mov_ff  TBLPTRL, psave_tblptr
83         mov_ff  TBLPTRH, psave_tblptr+1
84         mov_ff  TBLPTRU, psave_tblptr+2
85         mov_ff  FSR0L, psave_fsr0
86         mov_ff  FSR0H, psave_fsr0+1
87         mov_ff  FSR1L, psave_fsr1
88         mov_ff  FSR1H, psave_fsr1+1
89         mov_ff  PRODL, psave_prod
90         mov_ff  PRODH, psave_prod+1
91         mov_ff  STKPTR, psave_stkptr
92
93         mov_lfsr panic_stack + stack_depth*3 - 1, 0
94         mov_lw  stack_depth
95         mov_wf  STKPTR
96 stacksave_loop
97         mov_ff  TOSU, POSTDEC0
98         mov_ff  TOSH, POSTDEC0
99         mov_ff  TOSL, POSTDEC0
100         dec_f_ifnz STKPTR
101         bra     stacksave_loop
102
103         clr_f    STKPTR         ; avoids stack overruns
104         clr_f   panicst
105
106         call    panic_kill_hook
107
108 ; re-initialise timer0 config, etc.
109         call    read_pic_no
110         bra_z   panic_setup_if_master
111         ; must be slave:
112
113 panic_setup_if_slave
114         movlw   (1<<TMR0ON) | morse_slave_t0scale
115         movwf   T0CON
116         movlw   morse_slave_t0inith
117         movwf   t0h_count
118         movlw   morse_slave_t0initl
119         movwf   t0l_count
120
121         bra     panic_setup_endif_masterslave
122
123 panic_setup_if_master
124         movlw   (1<<TMR0ON) | morse_master_t0scale
125         movwf   T0CON
126         movlw   morse_master_t0inith
127         movwf   t0h_count
128         movlw   morse_master_t0initl
129         movwf   t0l_count
130
131         pin_l   p0_booster_userfault
132
133         mov_lw  0x0b ; AAARGH
134         bt_f_if1 TXSTA, TXEN
135         call    serial_write_char
136 ;...
137 panic_setup_endif_masterslave
138
139 ; get # bytes of morse msg, # registers in panic readout, message start addr.
140 ; back from condensed message start addr. stored in panic_address
141
142 panic_loop
143         mov_lw  4 ; size of each message's details
144         mul_wf  panic_address
145         mov_ff  PRODL,TBLPTRL           
146         mov_ff  PRODH,WREG
147         add_lw  (morse_messages_start)/256
148         mov_wf  TBLPTRH
149         clr_f   TBLPTRU
150
151         tblrd   *+              ; read 1st byte of error message
152                                 ; (gives # bytes morse, # bytes registers)
153         dw      0xffff ; silicon errata: B4 issue 4
154
155         mov_ff  TABLAT,panic_morse
156         mov_lw  00001111b
157         and_wff panic_morse     ; panic_morse now contains # bytes of morse msgs
158
159         mov_ff  TABLAT,panic_regs
160         mov_lw  01110000b
161         and_wff panic_regs
162         swap_f  panic_regs      ; panic_regs now contains # registers to read
163
164         call    led_black
165         rcall   waiting16
166         rcall   morsemsg        ; transmit morse in red
167         call    led_black
168         rcall   waiting8
169         rcall   waiting4
170         rcall   registermsg     ; transmit contents of registers in 
171                                 ; red(=low) and blue(=high)
172         rcall   waiting16
173         bra     panic_loop
174
175 ;****************************************************************************
176 ; PANIC SUBROUTINES
177
178 morsemsg
179 ; wrapper round morse_readout to flash the per-pic led red for a morse msg
180
181 morse_msg_start
182         clr_f           morse_counter           ; clear loop counter
183
184 morse_loop
185         mov_fw          panic_morse
186         cmp_fw_ifge     morse_counter           ; if loop counter >=panic_morse
187         return                                  ; return to panic
188
189         tblrd           *+
190         mov_ff          TABLAT,flash_pattern
191         rcall           morse_readout
192         inc_f           morse_counter
193         bra             morse_loop
194
195
196 ;--------------------------
197 morse_readout
198
199 ; Flashes the per-pic led and black in a specified pattern.
200 ;
201 ; The pattern is specified as the state for 8 identically-long time
202 ; periods each as long as a morse `dot', encoded into a byte with
203 ; most significant bit first.
204 ;                       On entry                On exit
205 ; W                     any                     undefined
206 ; flash_pattern         flash pattern           preserved
207 ; bit_counter           any                     undefined
208
209         mov_lw          9
210         mov_wf          bit_counter
211         rr_f            flash_pattern
212
213 morse_readout_loop
214         dec_f_ifz       bit_counter             ; done all the bits yet ?
215         return
216         ; No:
217
218         rl_f            flash_pattern           ; top bit goes into N, 
219                                                 ;ie Negative if 1
220         bra_n           morse_readout_if_led_1
221
222 morse_readout_if_led_0
223         call            led_black
224         bra             morse_readout_endif_led
225
226 morse_readout_if_led_1
227         call            led_red
228
229 morse_readout_endif_led
230         rcall           waiting
231         bra             morse_readout_loop
232
233 ;--------------------------
234 ;--------------------------
235 registermsg
236
237 register_msg_start
238         clr_f           register_counter        ; clear loop counter
239
240 register_loop
241         mov_fw          panic_regs
242         cmp_fw_ifge     register_counter        ; if loop counter >=panic_regs
243         return                                  ; return to panic
244
245         tblrd           *+
246
247         mov_fw          TABLAT          ; TABLAT has the 8-bit version
248         mov_wf          FSR0L           ; of the address.  So, 8 bits
249                                         ; go straight into FSR0L.
250
251         mov_lw          0x0f            ; For FSR0H, we see if the
252         mov_fw          FSR0H           ; address XX is >=0x60.
253                                         ; If it is then we meant 0xfXX;
254         mov_lw          0x5f            ; if not then we meant 0x0XX.
255         cmp_fw_ifle     FSR0L           ; (This is just like PIC does
256         clr_f           FSR0H           ; for insns using Access Bank)
257
258         mov_ff          INDF0,flash_pattern
259         rcall           register_readout
260
261         inc_f           register_counter        ;increment loop counter
262
263         rcall           waiting8
264         bra             register_loop
265
266 ;--------------------------
267
268 register_readout
269
270 ; Flashes the per-pic led red(0) and green(1) in a specified pattern.
271 ; (black gap between each bit)
272 ;
273 ; The pattern is specified as the state for 8 identically-long time
274 ; periods each as long as a morse `dot', encoded into a byte with
275 ; most significant bit first.
276 ;                       On entry                On exit
277 ; W                     any                     undefined
278 ; flash_pattern         flash pattern           preserved
279 ; bit_counter           any                     undefined
280
281         clr_f   bit_counter             ; clear loop counter
282         rr_f    flash_pattern
283
284
285 register_readout_loop
286         mov_lw          8
287         cmp_fw_ifge     bit_counter             ; if loop counter >=8 (register 
288                                                 ; length), return
289         return
290
291         mov_lw          4
292         cmp_fw_ifne     bit_counter     ; if loop counter !=4 (nybble length), 
293                                         ; skip insertion of extra black space
294         bra             not_nybble_boundary
295         rcall           waiting4
296
297 not_nybble_boundary
298         rl_f            flash_pattern           ; top bit goes into N flag, 
299                                                 ; ie Negative if 1
300         bra_n           register_readout_if_led_1
301
302 register_readout_if_led_0
303         call            led_red
304         bra             register_readout_endif_led
305
306 register_readout_if_led_1
307         call            led_green
308
309 register_readout_endif_led
310         inc_f           bit_counter       ; increment loop counter
311         rcall           waiting
312         call            led_black
313         rcall           waiting
314         bra             register_readout_loop
315
316
317 ;****************************************************************************
318 ; GENERAL SUBROUTINES
319
320 ;----------------------------------------
321 waiting16       rcall   waiting8
322 waiting8        rcall   waiting4
323 waiting4        rcall   waiting2
324 waiting2        rcall   waiting
325 waiting
326 ; waits for a fixed interval, depending on the configuration of TMR0
327
328         bt_f_if1 idloc1,idloc1_master
329         pin_z   p0_booster_userfault
330
331         bc_f    INTCON,2        ; clear timer0 interrupt bit (p109)
332 ; Interrupt happens on overflow.  So start at 65535-morse_t0cycles:
333         mov_fw  t0h_count
334         mov_wf  TMR0H           ; p107 set high byte of timer0 (buffered,
335                                 ; only actually set when write to tmr0l occurs)
336         mov_fw  t0l_count
337         mov_wf  TMR0L           ; set timer0 low byte - timer now set
338 waiting_loop    ; wait for timer0 interrupt, or some other interrupt
339         bt_f_if1 INTCON,TMR0IF
340         return
341
342         bt_f_if1 idloc1, idloc1_master
343         bra     waiting_master
344         ; slave:
345
346         bt_f_if0 SSPCON1, SSPEN
347         bra     waiting_loop    ; no readouts if i2c is disabled
348         ; slave, i2c enabled:
349
350         bt_f_if1 PIR1, SSPIF
351         call    pan_i2cs_interrupt
352
353         bra     waiting_loop
354
355 ;****************************************************************************
356 ; MEMORY READOUT - CRASH DUMP
357
358 ;----------------------------------------
359 ; MASTER'S PANIC SERIAL PORT HANDLING
360
361 ;--------------------
362 waiting_master
363         bt_f_if1 PIR1,RCIF ; host sent us something ?
364         call    panicd_serialrx
365
366         bt_f_if0 SSPCON1, SSPEN
367         bra     waiting_loop
368         ; master, i2c enabled:
369
370         bt_f_if0 panicst, panicst_i2cmenable
371         bra     waiting_loop
372
373         bt_f_if1 PIR1, SSPIF
374         rcall   pan_i2cm_interrupt
375
376         bra     waiting_loop
377
378 ;----------
379 panicst_oerrferr
380         mov_fw  RCREG
381         xor_lw  0x11
382         bra_z   panic_reset
383         xor_lw  0x10 ^ 0x11
384         bra_nz  panicd_serialrx_err_loop
385         ; yay! host ack'd ferr/oerr
386         bc_f    panicst, panicst_ferroerr
387         return ; return from panicd_serialrx
388
389 ;----------
390 panicd_serialrx_err
391         bs_f    panicst, panicst_ferroerr
392         bc_f    RCSTA, RCEN     ; disable       } to clear FERR/OERR
393         mov_fw  RCREG           ; read RCREG    } (see PIC18FXX8 DS p182)
394         bs_f    RCSTA, RCEN     ; reenable      }
395 panicd_serialrx_err_loop
396         bt_f_if0 PIR1, RCIF ; wait for a byte 0x10 to ack the overrun/error
397         bra     panicd_serialrx_err_loop
398 ;...
399 ;----------
400 panicd_serialrx
401         pin_nz  p0_booster_userfault
402         bt_f_if1 RCSTA,FERR
403         bra     panicd_serialrx_err
404         bt_f_if1 RCSTA,OERR
405         bra     panicd_serialrx_err
406         bt_f_if1 panicst, panicst_ferroerr
407         bra     panicst_oerrferr
408
409         mov_fw  RCREG
410         bra     panicd_process_input_byte
411
412 ;----------------------------------------
413 ; CRASHREAD MASTER/SLAVE COMMON COMMAND BYTE HANDLING
414
415 ;----------
416 pan_i2csu_write_data
417         call    led_green
418 panicd_process_input_byte
419 ;               W       instruction from host or master
420         tst_w_ifnz
421         bra     write_ifnot_00
422         ; we've received 0x00:
423
424         mov_lfsr 0,1
425         bs_f    panicst, panicst_acked
426         return
427
428 ;----------
429 write_ifnot_00
430         bt_f_if0 panicst, panicst_acked ; well, ignore that !
431         bra     write_only_tellmode
432         ; OK, we have an instruction:
433
434         bt_w_if1 7 ; huh?
435         bra     write_if_setbytetowrite
436         bt_w_if1 6
437         bra     panic_crashread_setpointer
438         bt_f_if0 idloc1,idloc1_master
439         bra     write_ifnot0_ifnotmaster
440         ; the next few options are for master only:
441
442         bt_w_if1 5
443         bra     write_if_master_slaveselect
444         bt_w_if1 4
445         bra     write_if_master_masterread
446         bt_w_if0 3
447         bra     write_if_master_slaveread
448 ;...
449 write_ifnot0_ifnotmaster
450         xor_lw  0x09
451         bra_z   panic_reset
452         xor_lw  0x09
453 ;...
454 write_only_tellmode
455         xor_lw  0x0a
456         bra_z   panic_tellmode
457         ; nope, well, we ignore it
458         return
459
460 ;----------
461 panic_crashread_setpointer
462 ;  W                    byte from master or host        undefined
463 ;  FSR1*                crashread pointer               updated
464 ;  t, STATUS, PROD*     any                             undefined
465 ;  all others           any                             preserved
466         mov_wf  t
467         mov_lw  1<<6
468         mul_wf  FSR1L
469         mov_ff  PRODH, FSR1H
470         mov_fw  t
471         and_lw  0x3f
472         ior_wfw PRODL
473         mov_wf  FSR1L
474 panic_noop
475         return
476
477 ;======================================================================#
478 ; SPECIAL COMMANDS 0x08..0x0f
479
480 ;----------
481 panic_reset
482         reset
483
484 ;----------
485 panic_tellmode
486         bt_f_if0 idloc1,idloc1_master
487         return
488         mov_lw  0x0b
489         bc_f    panicst, panicst_acked
490         goto    serial_write_char
491
492 ;======================================================================
493 ; MASTER READOUT AND MASTER READOUT OF SLAVES
494
495 ;----------
496 write_if_setbytetowrite
497         bt_f_if0 idloc1,idloc1_master
498         return ; for master only
499
500         bc_w    7
501         mov_wf  panic_valcount
502         bs_f    panicst, panicst_writeslave
503         bs_f    panicst, panicst_i2cmenable
504         return
505
506 ;----------
507 write_if_master_slaveread
508         mov_wf  panic_valcount
509         bc_f    panicst, panicst_writeslave
510         return
511
512 ;----------
513 write_if_master_slaveselect
514         bc_w    5
515         btg_w   4
516         bs_f    panicst, panicst_i2cmours
517         bt_f_if1 panicst, panicst_writeslave
518         bra     pan_i2cm_write_start
519         bra     pan_i2cm_read_start
520
521 ;----------
522 write_if_master_masterread
523         bc_w    4
524         mov_wf  panic_valcount
525 write_if_master_masterread_loop
526         mov_fw  POSTINC1
527         call    serial_write_char
528         dec_f_ifnz panic_valcount
529         bra     write_if_master_masterread_loop
530         return
531
532 ;----------
533 pan_i2cmu_read_got_byte
534         bt_f_if0 panicst, panicst_i2cmours
535         return
536         call    serial_write_char
537         dec_f_ifnz panic_valcount
538         bra     pan_i2cm_read_another
539         return
540
541 ;----------
542 pan_i2cmu_write_next_byte
543         mov_fw  panic_valcount
544         bc_f    STATUS, Z
545         bt_f_if0 panicst, panicst_i2cmours
546         retlw   0x00
547         bt_f_if0 panicst, panicst_writeslave
548         bs_f    STATUS, Z
549         bc_f    panicst, panicst_writeslave
550         return
551
552 ;----------
553 pan_i2cmu_done
554         mov_lw  ' '
555         goto    serial_write_char
556
557 ;----------
558 pan_i2cmu_slave_no_ack
559         i2cpanic morse_SP
560
561 ;======================================================================
562 ; SLAVE I2C
563
564 pan_near_i2csu code
565 ;----------
566 pan_i2csu_write_begin
567         return
568
569 ;----------
570 pan_i2csu_read_begin
571         mov_lw  0x80 ; M0000000
572         bt_f_if0 panicst, panicst_acked
573         goto    i2cs_read_data
574 ;...
575 i2csu_read_panicd_ok
576         mov_fw  POSTINC1
577         goto    i2cs_read_data
578
579 ;----------
580 pan_i2csu_read_another
581         bt_f_if1 panicst, panicst_acked
582         bra     i2csu_read_panicd_ok
583         ; not ok
584         mov_lw  0x0b ; AARGH
585         goto    i2cs_read_data
586
587 near_gots code
588 ;----------
589 got_aargh @
590         panic   morse_T
591
592 command_crashed_section code 0x2100
593 ;----------
594 command_crashed @
595 panic_crashread_commanded @
596         panic   morse_E
597
598 ;***************************************************************************
599         include final.inc