-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathBootloader.asm
More file actions
823 lines (696 loc) · 24.5 KB
/
Bootloader.asm
File metadata and controls
823 lines (696 loc) · 24.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
; 06/04/11 Roger Healey - Turn both LEDs on while bootloading as per other CBUS modules
; 20/04/11 Mike Bolton - Changed CAN bit rate for 8 MHz resonator
; 4/1/13 Pete Brownlow - User vectors set back to 0x800 for FCU compatibility
; 1/2/17 Pete Brownlow - Add conditional assembly to build for k or F series PIC
; - set clock rate defaults for PIC type, overridable by assembler def in project options
; - Initialise BRGCON1 before jumping to applcation, so that application code need have no clock speed hard coded
;
;*************************************************************** * * * * * * * * * * * * * * ;*
;* CBUS bootloader
;* Based on the Microchip botloader 'canio.asm' tho which full acknowledgement is made.
;* Relevant information is contained in the Microchip Application note AN247
; This part of the CBUS firmware is distributed under the Microchip
; license which requires that it is only used on Microchip hardware.
; See page 15 of <http:\\ww1.microchip.com/downloads/en/AppNotes/00247a.pdf>
; for details of the Microchip licensing. This bootloader is distributed with
; the CBUS software as a "system library" as defined in section 1 of the GNU Public
; license and is not licensed under GNU or Creative Commons.
; You must conform to Microchip license terms in respect of the bootloader.
;*
;* Basic Operation:
;* The following is a CAN bootloader designed for PIC18F microcontrollers
;* with built-in CAN such as the PIC18F458. The bootloader is designed to
;* be simple, small, flexible, and portable.
;*
;
;
;*
;* Commands:
;* Put commands received from source (Master --> Slave)
;* The count (DLC) can vary.
;* XXXXXXXXXXX 0 0 8 XXXXXXXX XXXXXX00 ADDRL ADDRH ADDRU RESVD CTLBT SPCMD CPDTL CPDTH
;* XXXXXXXXXXX 0 0 8 XXXXXXXX XXXXXX01 DATA0 DATA1 DATA2 DATA3 DATA4 DATA5 DATA6 DATA7
;*
;*
;* ADDRL - Bits 0 to 7 of the memory pointer.
;* ADDRH - Bits 8 - 15 of the memory pointer.
;* ADDRU - Bits 16 - 23 of the memory pointer.
;* RESVD - Reserved for future use.
;* CTLBT - Control bits.
;* SPCMD - Special command.
;* CPDTL - Bits 0 - 7 of 2s complement checksum
;* CPDTH - Bits 8 - 15 of 2s complement checksum
;* DATAX - General data.
;*
;* Control bits:
;* MODE_WRT_UNLCK-Set this to allow write and erase operations to memory.
;* MODE_ERASE_ONLY-Set this to only erase Program Memory on a put command. Must be on 64-byte
;* boundary.
;* MODE_AUTO_ERASE-Set this to automatically erase Program Memory while writing data.
;* MODE_AUTO_INC-Set this to automatically increment the pointer after writing.
;* MODE_ACK-Set this to generate an acknowledge after a 'put' (PG Mode only)
;*
;* Special Commands:
;* CMD_NOP 0x00 Do nothing
;* CMD_RESET 0x01 Issue a soft reset after setting last EEPROM data to 0x00
;* CMD_RST_CHKSM 0x02 Reset the checksum counter and verify
;* CMD_CHK_RUN 0x03 Add checksum to special data, if verify and zero checksum
;* CMD_BOOT_TEST 0x04 Just sends a message frame back to verify boot mode.
;* Modified version of the Microchip code by M Bolton 30/10/09
;
; The user program must have the folowing vectors
; User code reset vector 0x0800
; User code HPINT vector 0x0808
; user code LPINT vector 0x0818
; Checksum is 16 bit addition of all programmable bytes.
; User sends 2s complement of addition at end of program in command 0x03 (16 bits only)
;**********************************************************************************
#ifdef __18F25K80
#define CPUF18K
#else
#ifdef __18F26K80
#define CPUF18K
#else
#define CPUF18F
#endif
#endif
#ifdef __18F25K80
#include P18F25K80.INC
#endif
#ifdef __18F26K80
#include P18F26K80.INC
#endif
#ifdef __18F2480
#include P18F2480.INC
#endif
#ifdef __18F2580
#include P18F2580.INC
#endif
#ifdef __18F2585
#include P18F2585.INC
#endif
#ifdef __18F2680
#include P18F2680.INC
#endif
; #include P18F2585.INC
; Processor dependant definitions
#ifdef CPUF18F
#define PAGE_CANREG .15
#endif
#ifdef CPUF18K
#define PAGE_CANREG .14
#define PAGE_ANCON .15
#endif
; definitions originally in canio.def
#define MODE_SELF_VERIFY ;Enable self verification of written data (undefine if not wanted)
#define HIGH_INT_VECT 0x0808 ;HP interrupt vector redirect. Change if target is different
#define LOW_INT_VECT 0x0818 ;LP interrupt vector redirect. Change if target is different.
#define RESET_VECT 0x0800 ;start of target
#define CAN_CD_BIT RXB0EIDL,0 ;Received control / data select bit
#define CAN_PG_BIT RXB0EIDL,1 ;Received PUT / GET bit
#define CANTX_CD_BIT TXB0EIDL,0 ;Transmit control/data select bit
#define CAN_TXB0SIDH B'10000000' ;Transmitted ID for target node
#define CAN_TXB0SIDL B'00001000'
#define CAN_TXB0EIDH B'00000000' ;
#define CAN_TXB0EIDL B'00000100'
#define CAN_RXF0SIDH B'00000000' ;Receive filter for target node
#define CAN_RXF0SIDL B'00001000'
#define CAN_RXF0EIDH B'00000000'
#define CAN_RXF0EIDL B'00000111'
#define CAN_RXM0SIDH B'11111111' ;Receive masks for target node
#define CAN_RXM0SIDL B'11101011'
#define CAN_RXM0EIDH B'11111111'
#define CAN_RXM0EIDL B'11111000'
; Set default clock rate if not specified in project options
; If CLKMHZ is not defined, default to 64MHz on K series and 16MHz on F series
; Set define of CLKMHZ in project options to override this default
; Note - these frequencies are clock frequency NOT resonator frequency.
; If your config definitions specify the x4 PLL (which is usual), the clock frequency will be 4 times the resonator frequency
#ifndef CLKMHZ
#ifdef CPUF18F
#define CLKMHZ .16
#endif
#ifdef CPUF18K
#define CLKMHZ .16
#endif
#endif
#define CAN_BRGCON1 (CLKMHZ/4)-1 ; Work out BRGCON value from clock MHz
; #define CAN_BRGCON1 B'00000111' ;Previous hard coded value for 8MHz resonator with x4 PLL
#define CAN_BRGCON2 B'10011110'
#define CAN_BRGCON3 B'00000011'
#define CAN_CIOCON B'00100000' ;CAN I/O control
; ************************************************************ ** * * * * * * * * * * * * * * *
; ************************************************************ ** * * * * * * * * * * * * * * *
#ifndef EEADRH
#define EEADRH EEADR+ 1
#endif
#define TRUE 1
#define FALSE 0
#define WREG1 PRODH ; Alternate working register
#define WREG2 PRODL
#define MODE_WRT_UNLCK _bootCtlBits, 0 ; Unlock write and erase
#define MODE_ERASE_ONLY _bootCtlBits, 1 ; Erase without write
#define MODE_AUTO_ERASE _bootCtlBits, 2 ; Enable auto erase before write
#define MODE_AUTO_INC _bootCtlBits, 3 ; Enable auto inc the address
#define MODE_ACK _bootCtlBits, 4 ; Acknowledge mode
#define ERR_VERIFY _bootErrStat, 0 ; Failed to verify if set
#define CMD_NOP 0x00
#define CMD_RESET 0x01
#define CMD_RST_CHKSM 0x02
#define CMD_CHK_RUN 0x03
#define CMD_BOOT_TEST 0x04
; ************************************************************
; RAM addresses used by boot. can also be used by application.
CBLOCK 0
_bootCtlMem
_bootAddrL ; Address info
_bootAddrH
_bootAddrU
_unused0 ;(Reserved)
_bootCtlBits ; Boot Mode Control bits
_bootSpcCmd ; Special boot commands
_bootChkL ; Chksum low byte fromPC
_bootChkH ; Chksum hi byte from PC
_bootCount
_bootChksmL ; 16 bit checksum
_bootChksmH
_bootErrStat ;Error Status flags
ENDC
; end of bootloader RAM
;************************************************************
;****************************************************************
; Bootloader code
; *****************************************************************************
;_STARTUPCODE 0x00
ORG 0x0000
; *****************************************************************************
bra _CANInit
bra _StartWrite
; *****************************************************************************
;_INTV_H CODE 0x08
ORG 0x0008
; *****************************************************************************
goto HIGH_INT_VECT
; *****************************************************************************
;_INTV_L CODE 0x18
ORG 0x0018
; *****************************************************************************
goto LOW_INT_VECT
; **************************************************************
; Code start
; **************************************************************
ORG 0x0020
;_CAN_IO_MODULE CODE
; ************************************************************ ** * * * * * * * * * * * * * * *
; Function: VOID _StartWrite(WREG _eecon_data)
;PreCondition: Nothing
;Input: _eecon_data
;Output: Nothing. Self write timing started.
;Side Effects: EECON1 is corrupted; WREG is corrupted.
;Stack Requirements: 1 level.
;Overview: Unlock and start the write or erase sequence to protected
; memory. Function will wait until write is finished.
;
; ************************************************************ ** * * * * * * * * * * * * * * *
_StartWrite
movwf EECON1
btfss MODE_WRT_UNLCK ; Stop if write locked
return
movlw 0x55 ; Unlock
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1, WR ; Start the write
nop
btfsc EECON1, WR ; Wait (depends on mem type)
bra $ - 2
return
; ************************************************************ ** * * * * * * * * * * * * * * *
; Function: _bootChksm _UpdateChksum(WREG _bootChksmL)
;
; PreCondition: Nothing
; Input: _bootChksmL
; Output: _bootChksm. This is a static 16 bit value stored in the Access Bank.
; Side Effects: STATUS register is corrupted.
; Stack Requirements: 1 level.
; Overview: This function adds a byte to the current 16 bit checksum
; count. WREG should contain the byte before being called.
;
; The _bootChksm value is considered a part of the special
; register set for bootloading. Thus it is not visible. ;
;*************************************************************** * * * * * * * * * * * *
_UpdateChksum:
addwf _bootChksmL, F ; Keep a checksum
btfsc STATUS, C
incf _bootChksmH, F
return
;************************************************************ ** * * * * * * * * * * * * * * *
;
; Function: VOID _CANInit(CAN, BOOT)
;
; PreCondition: Enter only after a reset has occurred.
; Input: CAN control information, bootloader control information ; Output: None.
; Side Effects: N/A. Only run immediately after reset.
; Stack Requirements: N/A
; Overview: This routine is technically not a function since it will not
; return when called. It has been written in a linear form to
; save space.Thus 'call' and 'return' instructions are not
; included, but rather they are implied. ;
; This routine tests the boot flags to determine if boot mode is
; desired or normal operation is desired. If boot mode then the
; routine initializes the CAN module defined by user input. It
; also resets some registers associated to bootloading.
;
; ************************************************************ ** * * * * * * * * * * * * * * *
_CANInit:
movlb PAGE_CANREG ; Set Bank for certain CAN registers
movlw CAN_BRGCON1 ; Set bit rate first so application code can work out clock MHz
movwf BRGCON1
; See if we are in boot mode or normal execution
clrf EECON1
setf EEADR ; Point to last location of EEDATA
setf EEADRH
bsf EECON1, RD ; Read the control code
nop
incfsz EEDATA, W
goto RESET_VECT ; Jump to the application if not in boot mode
clrf _bootSpcCmd ; Reset the special command register
movlw 0x1C ; Reset the boot control bits
movwf _bootCtlBits
; bcf TRISB, CANTX ; Set the TX pin to output - presumably not required as Mike had commented it out
; Initialise CAN registers
movlw CAN_RXF0SIDH ; Set filter 0
movwf RXF0SIDH
movlw CAN_RXF0SIDL
movwf RXF0SIDL
comf WREG ; Prevent filter 1 from causing a receive event
movwf RXF1SIDL ;
movlw CAN_RXF0EIDH
movwf RXF0EIDH
movlw CAN_RXF0EIDL
movwf RXF0EIDL
movlw CAN_RXM0SIDH ; Set mask
movwf RXM0SIDH
movlw CAN_RXM0SIDL
movwf RXM0SIDL
movlw CAN_RXM0EIDH
movwf RXM0EIDH
movlw CAN_RXM0EIDL
movwf RXM0EIDL
; Note - BRGCON1 initialised first above
movlw CAN_BRGCON2
movwf BRGCON2
movlw CAN_BRGCON3
movwf BRGCON3
#ifdef CPUF18K
movlb PAGE_ANCON
clrf ANCON0
clrf ANCON1
#endif
#ifdef CPU18F
movlw B'00001110'
movwf ADCON1
#endif
movlw CAN_CIOCON ; Set IO
movwf CIOCON
clrf CANCON ; Enter Normal mode
;TODO - work out generic way of setting LEDs even if on different port - maybe only for CANEther is different?
;TODO - set these to default to usual LEDs on most CBUS boards - probably set in defines at top
bcf TRISC,0
bcf TRISC,2
bcf PORTC,0 ;green LED on
bcf PORTC,2 ;yellow LED on
; These are for default values
bcf TRISB,7
bcf TRISB,6
bsf PORTB,7 ;gren LED on
bsf PORTB,6 ;yellow LED on
; ************************************************************ ** * * * * * * * * * * * * * * *
; This routine is essentially a polling loop that waits for a
; receive event from RXB0 of the CAN module. When data is
; received, FSR0 is set to point to the TX or RX buffer depending
; upon whether the request was a 'put' or a 'get'.
; ************************************************************ ** * * * * * * * * * * * * * * *
_CANMain
bcf RXB0CON, RXFUL ; Clear the receive flag
_wait
clrwdt ; Clear WDT while waiting
btfss RXB0CON, RXFUL ; Wait for a message
bra _wait
_CANMainJp1
lfsr 0, RXB0D0
movf RXB0DLC, W
andlw 0x0F
movwf _bootCount
movwf WREG1
bz _CANMain
_CANMainJp2 ;?
; ************************************************************** * * * * * * * * * * * * * * *
; Function: VOID _ReadWriteMemory()
;
; PreCondition:Enter only after _CANMain().
; Input: None.
; Output: None.
; Side Effects: N/A.
; Stack Requirements: N/A
; Overview: This routine is technically not a function since it will not
; return when called. It has been written in a linear form to
; save space.Thus 'call' and 'return' instructions are not
; included, but rather they are implied.
;This is the memory I/O engine. A total of eight data bytes are received and decoded. In addition two control bits are received, put/get and control/data.
;A pointer to the buffer is passed via FSR0 for reading or writing.
;The control register set contains a pointer, some control bits and special command registers.
;Control
;<PG><CD><ADDRL><ADDRH><ADDRU><_RES_><CTLBT>< SPCMD><CPDTL><CPDTH>
;Data
;<PG>< CD>< DATA0>< DATA1>< DATA2>< DATA3>< DATA4>< DATA5>< DATA6>< DATA7>
;PG bit: Put = 0, Get = 1
;CD bit: Control = 0, Data = 1
; ************************************************************ ** * * * * * * * * * * * * * * *
_ReadWriteMemory:
btfsc CAN_CD_BIT ; Write/read data or control registers
bra _DataReg
; ************************************************************ ** * * * * * * * * * * * * * * * ; This routine reads or writes the bootloader control registers,
; then executes any immediate command received.
_ControlReg
lfsr 1, _bootAddrL ;_bootCtlMem
_ControlRegLp1
movff POSTINC0, POSTINC1
decfsz WREG1, F
bra _ControlRegLp1
; *********************************************************
; This is a no operation command.
movf _bootSpcCmd, W ; NOP Command
bz _CANMain
; bz _SpecialCmdJp2 ; or send an acknowledge
; *********************************************************
; This is the reset command.
xorlw CMD_RESET ; RESET Command
btfss STATUS, Z
bra _SpecialCmdJp4
setf EEADR ; Point to last location of EEDATA
setf EEADRH
clrf EEDATA ; and clear the data (FF OR 3FF depending on PIC)
movlw b'00000100' ; Setup for EEData
rcall _StartWrite
;TODO - sort out LEDs
bsf PORTC,0 ;yellow LED off
bcf PORTB,6 ;yellow LED off - default on CBUS boards
reset
; *********************************************************
; This is the Selfcheck reset command. This routine
; resets the internal check registers, i.e. checksum and
; self verify.
_SpecialCmdJp4
movf _bootSpcCmd, W
xorlw CMD_RST_CHKSM
bnz _SpecialCmdJp1
clrf _bootChksmH
clrf _bootChksmL
bcf ERR_VERIFY
clrf _bootErrStat
bra _CANMain
; RESET_CHKSM Command
; Reset chksum
; Clear the error verify flag
;This is the Test and Run command. The checksum is
; verified, and the self-write verification bit is checked.
; If both pass, then the boot flag is cleared.
_SpecialCmdJp1
movf _bootSpcCmd, W ; RUN_CHKSM Command
xorlw CMD_CHK_RUN
bnz _SpecialCmdJp3
movf _bootChkL, W ; Add the control byte
addwf _bootChksmL, F
bnz _SpecialCmdJp2
movf _bootChkH, W
addwfc _bootChksmH, F
bnz _SpecialCmdJp2
btfsc ERR_VERIFY ; Look for verify errors
bra _SpecialCmdJp2
bra _CANSendOK ;send OK message
_SpecialCmdJp2
bra _CANSendNOK ; or send an error acknowledge
_SpecialCmdJp3
movf _bootSpcCmd, W ; RUN_CHKSM Command
xorlw CMD_BOOT_TEST
bnz _CANMain
bra _CANSendBoot
; ************************************************************** * * * * * * * * * * * * * * *
; This is a jump routine to branch to the appropriate memory access function.
; The high byte of the 24-bit pointer is used to determine which memory to access.
; All program memories (including Config and User IDs) are directly mapped.
; EEDATA is remapped.
_DataReg
; *********************************************************
_SetPointers
movf _bootAddrU, W ; Copy upper pointer
movwf TBLPTRU
andlw 0xF0 ; Filter
movwf WREG2
movf _bootAddrH, W ; Copy the high pointer
movwf TBLPTRH
movwf EEADRH
movf _bootAddrL, W ; Copy the low pointer
movwf TBLPTRL
movwf EEADR
btfss MODE_AUTO_INC ; Adjust the pointer if auto inc is enabled
bra _SetPointersJp1
movf _bootCount, W ; add the count to the pointer
addwf _bootAddrL, F
clrf WREG
addwfc _bootAddrH, F
addwfc _bootAddrU, F
_SetPointersJp1 ;?
_Decode
movlw 0x30
cpfslt WREG2
bra _DecodeJp1
bra _PMEraseWrite
_DecodeJp1
movf WREG2,W
xorlw 0x30
bnz _DecodeJp2
bra _CFGWrite
_DecodeJp2
movf WREG2,W
xorlw 0xF0
bnz _CANMain
bra _EEWrite
f
; Program memory < 0x300000
; Config memory = 0x300000
; EEPROM data = 0xF00000
; ************************************************************ ** *
; ************************************************************** *
; Function: VOID _PMRead()
; VOID _PMEraseWrite ()
;
; PreCondition:WREG1 and FSR0 must be loaded with the count and address of
; the source data.
; Input: None.
; Output: None.
; Side Effects: N/A.
; Stack Requirements: N/A
; Overview: These routines are technically not functions since they will not
; return when called. They have been written in a linear form to
; save space.Thus 'call' and 'return' instructions are not
; included, but rather they are implied.
;These are the program memory read/write functions. Erase is available through control flags. An automatic erase option is also available.
; A write lock indicator is in place to ensure intentional write operations.
;Note: write operations must be on 8-byte boundaries and must be 8 bytes long. Also erase operations can only occur on 64-byte boundaries.
; ************************************************************ ** * * * * * * * * * * * * * * *
_PMEraseWrite:
btfss MODE_AUTO_ERASE
bra _PMWrite
_PMErase:
movf TBLPTRL, W
andlw b'00111111'
bnz _PMWrite
_PMEraseJp1
movlw b'10010100'
rcall _StartWrite
_PMWrite:
btfsc MODE_ERASE_ONLY
bra _CANMain
movf TBLPTRL, W
andlw b'00000111'
bnz _CANMain
movlw 0x08
movwf WREG1
_PMWriteLp1 ; Load the holding registers
movf POSTINC0, W
movwf TABLAT
rcall _UpdateChksum ; Adjust the checksum
tblwt*+
decfsz WREG1, F
bra _PMWriteLp1
#ifdef MODE_SELF_VERIFY
movlw 0x08
movwf WREG1
_PMWriteLp2
tblrd*- ; Point back into the block
movf POSTDEC0, W
decfsz WREG1, F
bra _PMWriteLp2
movlw b'10000100' ; Setup writes
rcall _StartWrite ; Write the data
movlw 0x08
movwf WREG1
_PMReadBackLp1
tblrd*+ ; Test the data
movf TABLAT, W
xorwf POSTINC0, W
btfss STATUS, Z
bsf ERR_VERIFY
decfsz WREG1, F
bra _PMReadBackLp1 ; Not finished then repeat
#else
tblrd*- ; Point back into the block
; Setup writes
movlw b'10000100' ; Write the data
rcall _StartWrite ; Return the pointer position
tblrd*+
#endif
bra _CANMain
; ************************************************************** * * * * * * * * * * * * * * *
; Function: VOID _CFGWrite()
; VOID _CFGRead()
;
; PreCondition:WREG1 and FSR0 must be loaded with the count and address of the source data.
; Input: None.
; Output: None.
; Side Effects: N/A.
; Stack Requirements: N/A
; Overview: These routines are technically not functions since they will not
; return when called. They have been written in a linear form to
; save space. Thus 'call' and 'return' instructions are not
; included, but rather they are implied.
;
; These are the Config memory read/write functions. Read is
; actually the same for standard program memory, so any read
; request is passed directly to _PMRead.
;
; ************************************************************ ** * * * * * * * * * * * * * * *
_CFGWrite
#ifdef MODE_SELF_VERIFY ; Write to config area
movf INDF0, W ; Load data
#else
movf POSTINC0, W
#endif
movwf TABLAT
rcall _UpdateChksum ; Adjust the checksum
tblwt* ; Write the data
movlw b'11000100'
rcall _StartWrite
tblrd*+ ; Move the pointers and verify
#ifdef MODE_SELF_VERIFY
movf TABLAT, W
xorwf POSTINC0, W
#endif
decfsz WREG1, F
bra _CFGWrite ; Not finished then repeat
bra _CANMain
; ************************************************************** * * * * * * * * * * * * * * *
; Function: VOID _EERead()
; VOID _EEWrite()
;
; PreCondition:WREG1 and FSR0 must be loaded with the count and address of
; the source data.
; Input: None.
; Output: None.
; Side Effects: N/A.
; Stack Requirements: N/A
; Overview: These routines are technically not functions since they will not
; return when called. They have been written in a linear form to
; save space. Thus 'call' and 'return' instructions are not
; included, but rather they are implied.
;
; This is the EEDATA memory read/write functions.
;
; ************************************************************ ** * * * * * * * * * * * * * * *
_EEWrite:
#ifdef MODE_SELF_VERIFY
movf INDF0, W
#else
movf POSTINC0, W
#endif
movwf EEDATA
rcall _UpdateChksum
movlw b'00000100'
rcall _StartWrite
#ifdef MODE_SELF_VERIFY
clrf EECON1
bsf EECON1, RD
nop
movf EEDATA, W
xorwf POSTINC0, W
btfss STATUS, Z
bsf ERR_VERIFY
#endif
infsnz EEADR, F
incf EEADRH, F
decfsz WREG1, F
bra _EEWrite
bra _CANMain
; Read the data
; Adjust EEDATA pointer
; Not finished then repeat
; Load data
; Adjust the checksum
; Setup for EEData
; and write
; Read back the data ; verify the data ; and adjust pointer
; Adjust EEDATA pointer
; Not finished then repeat
; ************************************************************** * * * * * * * * * * * * * * *
; Function: VOID _CANSendAck()
; VOID _CANSendResponce ()
;
; PreCondition:TXB0 must be preloaded with the data.
; Input: None.
; Output: None.
; Side Effects: N/A.
; Stack Requirements: N/A
; Overview: These routines are technically not functions since they will not
; return when called. They have been written in a linear form to
; save space. Thus 'call' and 'return' instructions are not
; included, but rather they are implied. ;
; These routines are used for 'talking back' to the source. The
; _CANSendAck routine sends an empty message to indicate
; acknowledgement of a memory write operation. The
; _CANSendResponce is used to send data back to the source. ;
; ************************************************************ ** * * * * * * * * * * * * * * *
_CANSendMessage
btfsc TXB0CON,TXREQ
bra $ - 2
movlw CAN_TXB0SIDH
movwf TXB0SIDH
movlw CAN_TXB0SIDL
movwf TXB0SIDL
movlw CAN_TXB0EIDH
movwf TXB0EIDH
movlw CAN_TXB0EIDL
movwf TXB0EIDL
bsf CANTX_CD_BIT
btfss CAN_CD_BIT
bcf CANTX_CD_BIT
bsf TXB0CON, TXREQ
bra _CANMain ; Setup the command bit
_CANSendOK ;send OK message
movlw 1 ;a 1 is OK
movwf TXB0D0
movwf TXB0DLC
bra _CANSendMessage
_CANSendNOK ;send not OK message
clrf TXB0D0 ;a 0 is not OK
movlw 1
movwf TXB0DLC
bra _CANSendMessage
_CANSendBoot
movlw 2 ;2 is confirm boot mode
movwf TXB0D0
movlw 1
movwf TXB0DLC
bra _CANSendMessage
END