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