Remove the debug LED controls
[bootloader] / mybootload.X / main.asm
1     radix dec
2
3     errorlevel -302
4
5 #include "p16f1455.inc"
6
7 ; CONFIG1
8  __config _CONFIG1, 0xFCC
9 ;; __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_SWDTEN & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
10 ; CONFIG2
11  __config _CONFIG2, 0x16CF
12 ; __CONFIG _CONFIG2, _WRT_OFF & _CPUDIV_NOCLKDIV & _USBLSCLK_48MHz & _PLLMULT_3x & _PLLEN_DISABLED & _STVREN_ON & _BORV_LO & _LPBOR_ON & _LVP_OFF
13
14
15 #define max_flash 0x2000
16 #define row_size  32
17
18 ; 16F1455 errata says self-program only works <= 4MHz clock
19 xtal    EQU 4000000
20 baud    EQU 19200
21
22 #include "spbrgselect.inc"
23
24 ; This is the smallest multiple of 32 that the bootloader
25 ; code fits into (minus the 4 for the remapped section)
26 loader_size     set 224
27
28 ; fit remap section in end of previous page
29 ; so we dont need to rewrite the bootloader page
30 remap_addr      set max_flash - loader_size - 4
31
32 ; Variables
33     cblock 0x20
34         buffer:80
35     endc
36
37     ; common ram section
38     cblock 0x70
39         cmd
40         crc
41         i
42         tmp
43     endc
44
45 ; ############ RESET ############
46 ; This is the normal reset vector
47 ; when a program is loaded, its version of these 4 will be moved
48 ; and replaced with our code to jump to the bootloader
49
50 Start CODE 0x0000
51     MOVLP   high(StartBoot)
52     GOTO    StartBoot
53     NOP
54     NOP
55 ; after this is the normal reset vector and rest of the loaded program
56
57
58 ; simple test program
59 Main
60 ;    banksel ANSELA
61 ;    CLRF    ANSELA
62 ;    banksel TRISA
63 ;    CLRF    TRISA
64 ;    CLRF    TRISC
65 ;    banksel PORTA
66 ;    BSF     PORTA,5     ; green on
67 ;    BCF     PORTA,4     ; red off
68 ;    SLEEP
69
70
71 ; At the far end of memory...
72 ; this is the relocated boot sector
73     ORG remap_addr
74 AppVector
75 ;    NOP
76     MOVLP   high(Main)
77     GOTO    Main    ; pretend program loaded
78     NOP
79     NOP
80
81 ; immediately followed by out bootloader
82     ORG     remap_addr+4
83 StartBoot
84
85     ; First configure the pin
86     ; 16f1455  RX=RC5 TX=RC4
87 ;    banksel TRISC
88 ;    BSF     TRISC,5   ; RC5 as input
89 ;    BCF     TRISC,4   ; RC4 as output
90     banksel PORTC
91     CLRF    PORTC
92
93     BTFSC   PORTC,5   ; RC5 is Clear (break state) carry on
94     BRA     AppVector   ; Was not clear, launch app instead
95
96     ; Lets start the bootloader properly
97     banksel OSCCON
98     MOVLW   b'00110100'
99     MOVWF   OSCCON      ; 4Mhz clock mode
100     BTFSS   OSCSTAT,HFIOFR
101     BRA     $-1         ; wait until oscillator is ready
102     MOVLW   b'00011001' ; Activate watchdog, 4 seconds
103     MOVWF   WDTCON
104
105 SetBaud
106     ; Set the baud rate and enable uart
107     banksel TXSTA
108     MOVLW   b'00100100' ; TXEN=1 SYNC=0 BRGH=1
109     MOVWF   TXSTA
110     banksel SPBRGL
111     MOVLW   spbrg_value
112     MOVWF   SPBRGL
113     CLRF    SPBRGH
114     banksel RCSTA
115     MOVLW   b'10010000' ; SPEN CREN
116     MOVWF   RCSTA
117
118 ; debug lights
119 ; debug RA5 green, RA4 red
120 ;    banksel ANSELA
121 ;    CLRF    ANSELA
122 ;    banksel TRISA
123 ;    CLRF    TRISA
124 ;    banksel PORTA
125 ;    BCF     PORTA,5     ; green off
126 ;    BSF     PORTA,4     ; red on
127     
128     ; Send the 'we heard you' ACK symbol
129     CLRF    crc
130     MOVLW   0x06
131     CALL    SendByte
132     MOVLW   'B'
133     CALL    SendByte
134     MOVLW   'L'
135     CALL    SendByte
136     
137     ; Wait for PC to drop the break condition
138     banksel PORTC
139     BTFSS   PORTC,5
140     BRA     $-1
141
142     ; Transmit device ID
143     banksel PMADRL
144     MOVLW   0x06  ; 0x8006 Device ID
145     MOVWF   PMADRL
146     CLRF    PMADRH
147     BSF     PMCON1,CFGS
148     BSF     PMCON1,RD
149     NOP
150     NOP
151     MOVF    PMDATH,W
152     CALL    SendByte
153     banksel PMDATL
154     MOVF    PMDATL,W
155     CALL    SendByte
156
157     ; Transmit location of bootloader, and thus top of flash
158     MOVLW   high(remap_addr)
159     CALL    SendByte
160
161     MOVLW   low(remap_addr)
162     CALL    SendByte
163
164     ; transmit csum to complete the welcome message
165     CALL    SendCRC
166
167     ; Wait here for instructions
168 CmdLoop
169     CLRWDT
170     CLRF    crc
171     CALL    ReadByte
172     MOVWF   cmd         ; keep it to re-examine
173
174     ; command 'R' read a row (32 words)
175     SUBLW   'R'
176     SKPNZ
177     BRA     ReadLine
178
179     ; command 'W' write a row (32 words)
180     MOVFW   cmd
181     SUBLW   'W'
182     SKPNZ
183     BRA     WriteLine
184
185     ; command 'B' reboot
186     MOVFW   cmd
187     SUBLW   'B'
188     SKPNZ
189     BRA     DoBoot
190
191     BRA     CmdLoop
192
193 ReadByte ; put it in W
194     banksel PIR1
195     BTFSS   PIR1, RCIF
196     BRA     $-1
197     banksel RCREG
198     MOVF    RCREG,W
199     ADDWF   crc,F
200     RETURN
201
202 ReadCRC
203     banksel PIR1
204     BTFSS   PIR1, RCIF
205     BRA     $-1
206     banksel RCREG
207     MOVF    RCREG,W
208     RETURN
209
210
211 SendCRC  ; copy the crc in as the thing to send
212     MOVF    crc,W
213 SendByte ; that is in W
214     ADDWF   crc,F
215     banksel PIR1
216     BTFSS   PIR1, TXIF
217     BRA     $-1
218     banksel TXREG
219     MOVWF   TXREG
220     RETURN
221
222 SendError ; Say there was an error (must be an in subr)
223     MOVLW   'E'
224     CALL    SendByte
225     BRA     CmdLoop
226
227 ReadLine ; read a row
228     CALL    ReadByte
229     banksel PMADRH
230     MOVWF   PMADRH  ; store the high byte
231     CALL    ReadByte
232     banksel PMADRL
233     ANDLW   0xE0    ; align to 32 word
234     MOVWF   PMADRL  ; store the low byte
235     CALL    ReadCRC ; read the checksum
236     SUBWF   crc,W
237     SKPZ             ; if crc-checksum !=0 goto Error
238     BRA     SendError
239 ; now lets send a record back to the host
240     MOVLW   row_size    ; 32 words
241     MOVWF   i
242     CLRF    crc         ; reset crc for outgoing message
243     MOVLW   'R'         ; warn that we are writing
244     CALL    SendByte
245     banksel PMADRH
246     MOVF    PMADRH,W    ; say what the start address is
247     ANDLW   0x7F        ; top bit is always set, duh
248     CALL    SendByte
249     banksel PMADRL
250     MOVF    PMADRL,W
251     CALL    SendByte
252
253 ReadLoop
254     banksel PMCON1
255     BCF     PMCON1,CFGS ; read program not config
256     BSF     PMCON1,RD
257     NOP
258     NOP
259     MOVF    PMDATH,W    ; send high byte
260     CALL    SendByte
261     banksel PMDATL
262     MOVF    PMDATL,W    ; send low byte
263     CALL    SendByte
264     banksel PMADRL
265     ; Assumption: this is 32 word aligned, will never cross boundary
266     INCF    PMADRL,F    ; increment address
267     DECFSZ  i,F         ; i--
268     BRA     ReadLoop    ; go around again
269     ; finished sending program words
270     CALL    SendCRC    ; send the crc
271     ; done, go back for next command
272     BRA     CmdLoop
273
274 WriteLine ; write a row
275     CALL    ReadByte
276     banksel PMADRH
277     MOVWF   PMADRH  ; store the high byte
278     CALL    ReadByte
279     banksel PMADRL
280     ANDLW   0xE0    ; align to 32 word
281     MOVWF   PMADRL  ; store the low byte
282     ; lets just store the bytes in buff until we are sure the checksum is good
283     banksel FSR0L
284     MOVLW   high(buffer)
285     MOVWF   FSR0H
286     MOVLW   low(buffer)
287     MOVWF   FSR0L
288     ; read row_size * 2 bytes
289     MOVLW   row_size * 2
290     MOVWF   i
291 WriteLineRead
292     CALL    ReadByte
293     MOVWI   FSR0++
294     DECFSZ  i,F
295     BRA     WriteLineRead
296     ; now read the crc and test
297     CALL    ReadCRC ; read the checksum
298     SUBWF   crc,W
299     SKPZ             ; if crc-checksum !=0 goto Error
300     BRA     SendError
301     ; everything is fine, commit to memory
302     ; first we have to erase the row
303     banksel PMCON1
304     BCF     PMCON1,CFGS ; program
305     BSF     PMCON1,FREE ; erase
306     BSF     PMCON1,WREN ; enable writes
307     MOVLW   0x55
308     MOVWF   PMCON2
309     MOVLW   0xAA
310     MOVWF   PMCON2
311     BSF     PMCON1,WR   ; commit
312     NOP
313     NOP     ; CPU goes to sleep for 2mS
314     BCF     PMCON1,WREN ; disable writes
315     ; now move the FSR back to the start
316     banksel FSR0L
317     MOVLW   high(buffer)
318     MOVWF   FSR0H
319     MOVLW   low(buffer)
320     MOVWF   FSR0L
321     MOVLW   row_size    ; need to do this once per word
322     MOVWF   i
323
324     ; setup for writing to latches
325     banksel PMCON1
326     BSF     PMCON1,WREN ; enable writes
327     BCF     PMCON1,CFGS ; program
328     BCF     PMCON1,FREE ; write not erase this time
329     BSF     PMCON1,LWLO ; into the latches
330
331 LatchWord
332     MOVIW   FSR0++
333     MOVWF   PMDATH
334     MOVIW   FSR0++
335     MOVWF   PMDATL
336     DECFSZ  i,F
337     BRA     LatchWrite
338     BRA     CommitWrite
339     ; just a latching write
340 LatchWrite
341     MOVLW   0x55
342     MOVWF   PMCON2
343     MOVLW   0xAA
344     MOVWF   PMCON2
345     BSF     PMCON1,WR   ; commit
346     NOP
347     NOP
348     INCF    PMADRL,F    ; move along
349     BRA     LatchWord
350 CommitWrite
351     BCF     PMCON1,LWLO ; real thing this time
352     MOVLW   0x55
353     MOVWF   PMCON2
354     MOVLW   0xAA
355     MOVWF   PMCON2
356     BSF     PMCON1,WR   ; commit
357     NOP
358     NOP             ; cpu stalls for 2mS
359     ; and we are finished
360     BCF     PMCON1,WREN ; disable writes
361     ; tell the other end we finished
362     CLRF    crc         ; reset crc for outgoing message
363     MOVLW   'W'         ; confirm the write command
364     CALL    SendByte
365     banksel PMADRH
366     MOVF    PMADRH,W    ; say what the start address is
367     ANDLW   0x7F        ; top bit is always set, duh
368     CALL    SendByte
369     banksel PMADRL
370     MOVF    PMADRL,W
371     ANDLW   0xE0        ; align to 32 word
372     CALL    SendByte
373     CALL    SendCRC
374     ; finished writing
375     BRA     CmdLoop
376
377 DoBoot
378     RESET
379
380 EndBoot
381     END
382