;
; MR-9090 bootloader
;
; LICENSE
; Creative Commons Attribution-NonCommercial-ShareALike 2.5
;
; You are free:
;
; * to copy, distribute, display, and perform the work
; * to make derivative works
;
; Under the following conditions:
;
; 1. Attribution. You must attribute the work in the manner specified by the
; author or licensor.
; 2. Noncommercial. You may not use this work for commercial purposes.
; 3. Share Alike. If you alter, transform, or build upon this work, you may
; distribute the resulting work only under a license identical to this one.
;
; * For any reuse or distribution, you must make clear to others the license
; terms of this work.
; * Any of these conditions can be waived if you get permission from the
; copyright holder.
;
; Your fair use and other rights are in no way affected by the above.
;
; This is a human-readable summary of the Legal Code.
; See full license at http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode
;
; Copyright: Marko Kanala (raato@mulletronic.com).
;
; put program start vector at 0x0004
#define BOOTSTRAP 0x0004
; bootloader vars
cblock 0
expected
hcounter
lcounter
bl_wait1
bl_wait2
bl_wait3
timeout
endc
cblock 10
buffer:64
endc
; 18f442 == 16k program flash
ORG 0x3F00
bootloader:
;;; set up midi
bsf PIE1, RCIE
; set baudrate to 31250 baud (midi)
movlw 2 * 0x0a - 1
movwf SPBRG
; no transmit, "low speed"
clrf TXSTA
; serial port enabled, 8-bit, enable receiver
movlw (1 << SPEN) | (1 << CREN)
movwf RCSTA
; make sure that USART receive buffer is empty
bcf RCSTA, CREN
movf RCREG, W
bsf RCSTA, CREN
clrf TRISE
clrf TRISD
clrf timeout
clrf PORTE
;;; listen to midi for a while and wait for sysex
; F0 71 55 17 7F <firmware data, see below> F7
incf PORTE
bootloader_loop:
decf PORTE
movlw 0xF0
rcall bootloader_receive_expect
tstfsz timeout
bra bootloader_go
; we got 0xf0, check for our sysex id 0x715517
movlw 0x71
rcall bootloader_receive_expect
tstfsz timeout
bra bootloader_go
movlw 0x55
rcall bootloader_receive_expect
tstfsz timeout
bra bootloader_go
movlw 0x17
rcall bootloader_receive_expect
tstfsz timeout
bra bootloader_go
; expect 0x7f == firmware
movlw 0x7F
rcall bootloader_receive_expect
tstfsz timeout
bra bootloader_go
;;; okay, it seems we've got incoming firmware data chunk, receive and flash
; program data:
;
; AH AL <64 bytes of midi encoded data (data>>7 data&0x7f ...)>, cc = 0 .. 63
;
; set 20ms between sysex messages when dumping so flash writes get written
; correctly!
;
; AH = address >> 7 & 0x7f
; AL = address & 0x7f
; so address = AH<<7 | AL
;
; Note: supports addresses 14-bit addresses 0x0000 - 0x3FFF (18f442)
clrf TBLPTRU
clrf TBLPTRL
rcall bootloader_receive ; AH
tstfsz timeout
bra bootloader_go
bcf STATUS, C
rrcf WREG
movwf TBLPTRH
btfsc STATUS, C
bsf TBLPTRL, 7
rcall bootloader_receive ; AL
tstfsz timeout
bra bootloader_go
iorwf TBLPTRL
movlw 64
movwf lcounter
; receive count (max 64) bytes to buffer
lfsr FSR0, buffer - 1
bootloader_loop_64:
rcall bootloader_receive ; receive high bit
tstfsz timeout
bra bootloader_go
rrncf WREG
movwf PREINC0 ; store to buffer, FSR0 points to stored byte
rcall bootloader_receive ; receive bits 6:0
tstfsz timeout
bra bootloader_go
iorwf INDF0
decfsz lcounter
bra bootloader_loop_64
; LEDS
incf PORTE
; erase 64 bytes
movlw b'10010100'
rcall bootloader_flash
lfsr FSR0, buffer
movlw 8 ; 8 ...
movwf hcounter
bootloader_flashloop:
movlw 8 ; ... x 8 bytes == 64 byte buffer
movwf lcounter
bootloader_prepareloop: ; write 8 bytes to holding registers
movf POSTINC0, W
movwf TABLAT ; buffer to latch
tblwt*+
; LEDS
movwf PORTD
decfsz lcounter
bra bootloader_prepareloop
tblrd*- ; addr-1
movlw b'10000100'
rcall bootloader_flash ; flash 8 bytes
tblrd*+ ; addr+1
decfsz hcounter
bra bootloader_flashloop
bcf EECON1, WREN
bra bootloader_loop ; and reloop
; starts the actual program
bootloader_go:
; kill uart and start the program
movlw b'00000011'
movwf PORTE ; shut leds
clrf RCSTA
goto BOOTSTRAP
; receives a byte from a midi and timeouts in a while,
; WREG = byte expected or if 0 anything is accepted
;
; received byte is returned in WREG
bootloader_receive:
clrf WREG
bootloader_receive_expect:
movwf expected
movlw 25 ; ca 1.5s
movwf bl_wait3
bootloader_receive_wait3:
clrf bl_wait2
bootloader_receive_wait2:
clrf bl_wait1
bootloader_receive_wait1:
btfsc PIR1, RCIF
bra bootloader_received
; nothing received, wait for timeout
bootloader_receive_continue:
decfsz bl_wait1
bra bootloader_receive_wait1
decfsz bl_wait2
bra bootloader_receive_wait2
decfsz bl_wait3
bra bootloader_receive_wait3
; got timeout, just start
decf timeout
return
bootloader_received:
movf RCREG, W
bcf PIR1, RCIF ; clear irq
tstfsz expected
bra bootloader_received_chk_exp
; something received, return
return
bootloader_received_chk_exp:
; we got something, check if matches with expected
cpfseq expected
; doesn't match what we expected, continue receiving
bra bootloader_receive_continue
return
; writes data to flash
bootloader_flash:
movwf EECON1
movlw 0x55
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1, WR
nop
bootloader_waitflash:
btfsc EECON1, WR
bra bootloader_waitflash
return
External Labels :
BOOTSTRAP