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