5 #include "cpuselect.inc"
7 ; 16F1455 errata says self-program only works <= 4MHz clock
11 #include "spbrgselect.inc"
13 ; This is the smallest multiple of 32 that the bootloader
14 ; code fits into (minus the 4 for the remapped section)
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
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
44 ; after this is the normal reset vector and rest of the loaded program
55 ; BSF PORTA,5 ; green on
56 ; BCF PORTA,4 ; red off
60 ; At the far end of memory...
61 ; this is the relocated boot sector
66 GOTO Main ; pretend program loaded
70 ; immediately followed by out bootloader
74 ; First configure the pin
75 ; 16f1455 RX=RC5 TX=RC4
77 ; BSF TRISC,5 ; RC5 as input
78 ; BCF TRISC,4 ; RC4 as output
87 BTFSC SERIAL_PORT,SERIAL_RXPIN ; RC5 is Clear (break state) carry on
88 BRA AppVector ; Was not clear, launch app instead
90 ; Lets start the bootloader properly
93 MOVWF OSCCON ; 4Mhz clock mode
95 BRA $-1 ; wait until oscillator is ready
96 MOVLW b'00011001' ; Activate watchdog, 4 seconds
100 ; Set the baud rate and enable uart
102 MOVLW b'00100100' ; TXEN=1 SYNC=0 BRGH=1
109 MOVLW b'10010000' ; SPEN CREN
113 ; debug RA5 green, RA4 red
119 ; BCF PORTA,5 ; green off
120 ; BSF PORTA,4 ; red on
122 ; Send the 'we heard you' ACK symbol
131 ; Wait for PC to drop the break condition
133 BTFSS SERIAL_PORT,SERIAL_RXPIN
138 MOVLW 0x06 ; 0x8006 Device ID
151 ; Transmit location of bootloader, and thus top of flash
152 MOVLW high(remap_addr)
155 MOVLW low(remap_addr)
158 ; transmit csum to complete the welcome message
161 ; Wait here for instructions
166 MOVWF cmd ; keep it to re-examine
168 ; command 'R' read a row (32 words)
173 ; command 'W' write a row (32 words)
187 ReadByte ; put it in W
205 SendCRC ; copy the crc in as the thing to send
207 SendByte ; that is in W
216 SendError ; Say there was an error (must be an in subr)
221 ReadLine ; read a row
224 MOVWF PMADRH ; store the high byte
227 ANDLW 0xE0 ; align to 32 word
228 MOVWF PMADRL ; store the low byte
229 CALL ReadCRC ; read the checksum
231 SKPZ ; if crc-checksum !=0 goto Error
233 ; now lets send a record back to the host
234 MOVLW row_size ; 32 words
236 CLRF crc ; reset crc for outgoing message
237 MOVLW 'R' ; warn that we are writing
240 MOVF PMADRH,W ; say what the start address is
241 ANDLW 0x7F ; top bit is always set, duh
249 BCF PMCON1,CFGS ; read program not config
253 MOVF PMDATH,W ; send high byte
256 MOVF PMDATL,W ; send low byte
259 ; Assumption: this is 32 word aligned, will never cross boundary
260 INCF PMADRL,F ; increment address
262 BRA ReadLoop ; go around again
263 ; finished sending program words
264 CALL SendCRC ; send the crc
265 ; done, go back for next command
268 WriteLine ; write a row
271 MOVWF PMADRH ; store the high byte
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
282 ; read row_size * 2 bytes
290 ; now read the crc and test
291 CALL ReadCRC ; read the checksum
293 SKPZ ; if crc-checksum !=0 goto Error
295 ; everything is fine, commit to memory
296 ; first we have to erase the row
298 BCF PMCON1,CFGS ; program
299 BSF PMCON1,FREE ; erase
300 BSF PMCON1,WREN ; enable writes
305 BSF PMCON1,WR ; commit
307 NOP ; CPU goes to sleep for 2mS
308 BCF PMCON1,WREN ; disable writes
309 ; now move the FSR back to the start
315 MOVLW row_size ; need to do this once per word
318 ; setup for writing to latches
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
333 ; just a latching write
339 BSF PMCON1,WR ; commit
342 INCF PMADRL,F ; move along
345 BCF PMCON1,LWLO ; real thing this time
350 BSF PMCON1,WR ; commit
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
360 MOVF PMADRH,W ; say what the start address is
361 ANDLW 0x7F ; top bit is always set, duh
365 ANDLW 0xE0 ; align to 32 word