; ; 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
BOOTSTRAP