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