Commit | Line | Data |
---|---|---|
9c66c9ff JM |
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 | |
b339b9f7 JM |
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 | |
9c66c9ff JM |
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 | |
b339b9f7 JM |
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 | |
9c66c9ff JM |
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 |