Commit | Line | Data |
---|---|---|
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 | |
8 | xtal EQU 4000000 | |
9 | baud 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) | |
15 | loader_size set 224 | |
16 | ||
17 | ; fit remap section in end of previous page | |
18 | ; so we dont need to rewrite the bootloader page | |
19 | remap_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 | ||
39 | Start 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 | |
48 | Main | |
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 | |
63 | AppVector | |
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 | |
72 | StartBoot | |
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 | ||
99 | SetBaud | |
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 | |
162 | CmdLoop | |
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 | ||
187 | ReadByte ; 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 | ||
196 | ReadCRC | |
197 | banksel PIR1 | |
198 | BTFSS PIR1, RCIF | |
199 | BRA $-1 | |
200 | banksel RCREG | |
201 | MOVF RCREG,W | |
202 | RETURN | |
203 | ||
204 | ||
205 | SendCRC ; copy the crc in as the thing to send | |
206 | MOVF crc,W | |
207 | SendByte ; 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 | ||
216 | SendError ; Say there was an error (must be an in subr) | |
217 | MOVLW 'E' | |
218 | CALL SendByte | |
219 | BRA CmdLoop | |
220 | ||
221 | ReadLine ; 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 | ||
247 | ReadLoop | |
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 | ||
268 | WriteLine ; 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 | |
285 | WriteLineRead | |
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 | ||
325 | LatchWord | |
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 | |
334 | LatchWrite | |
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 | |
344 | CommitWrite | |
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 | ||
371 | DoBoot | |
372 | RESET | |
373 | ||
374 | EndBoot | |
375 | END | |
376 |