;;;=========================================================================== ;;; ;;; project: robot ;;; file: bootstrap-pic16f88.lisp ;;; author: Andrew Smith ;;; created: 2006-07-17 ;;; updated: 2006-08-14 ;;; language: Common Lisp (CLISP) ;;; licence: GPL version 2 ;;; ;;; Copyright 2006, Andrew Smith ;;; ;;; NOTES ;;; ;;; Install a bootloader into a PIC16F88 microcontroller. ;;; Based on the design published by http://www.microchip.com ;;; Bootloader automatically runs user program if RD is held low on reset. ;;; Interrupts are *not* supported by this firmware. ;;; Uses a fixed baudrate, currently 2400 baud. ;;; ;;; ;;; protocol: ;;; ;;; packet: stx stx { byte | (dle stx) | (dle etx) | (dle dle) } etx ;;; format: command count address-l address-h 0 data ... checksum ;;; ;;; ;;; commands: ;;; ;;; read-version ;;; read-program count=number-of-words address=start-address data=lsb-msb ;;; write-program count=number-of-blocks address=block-boundary data=lsb-msb ;;; erase-program count=number-of-rows address=row-boundary ;;; read-memory count=number-of-bytes address=start-address ;;; write-memory count=number-of-bytes address=start-address data=bytes ;;; read-configuration *not implemented* ;;; write-configuration *not implemented* ;;; run-program ;;; ;;; ;;;--------------------------------------------------------------------------- ;;; ;;; This program is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published ;;; by the Free Software Foundation; either version 2 of the License, or ;;; (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software Foundation, ;;; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ;;; ;;; ;;;--------------------------------------------------------------------------- (load "source/controller") (in-package controller) ;;; variables and constants -------------------------------------------------- (defconstant *major-version* 0) (defconstant *minor-version* 4) (defconstant *stx* #x0F) (defconstant *etx* #x04) (defconstant *dle* #x05) (defconstant *buffer-size* #x68) ;;; commands (dc 0 *read-version* *read-program* *write-program* *erase-program* *read-memory* *write-memory* *read-configuration* *write-configuration* *run-program* ) (defconstant *max-command* *run-program*) (dc #x10 (buffer *buffer-size*) checksum rxdata txdata counter1 counter2 ) (dc buffer command data-count address-l address-h address-u packet-data ) ;;;--------------------------------------------------------------------------- (defparameter *pic16f88* (make-instance 'pic16f88 :configuration `(#x3f70 #x0000) :variables `() :source-code `( :reset (btfss portb 2) (goto :user-program) :restart ;; ;; select memory bank 0 ;; (bcf status rp0) (bcf status rp1) (clrf intcon) ;disable interrupts (movlw #x80) ;enable asynchronous serial communications (movwf rcsta) ;; ;; select memory bank 1 ;; (bsf status rp0) (movlw #x60) ;set the internal clock to 4 MHz (iorwf osccon f) (movlw #xFF) ;set ports A and B to all inputs (movwf trisa) (movwf trisb) (movlw #x80) ;disable internal pullups on port B (movwf option-reg) (bsf status irp) (movlw #x26) ;transmit enabled, high speed, empty (movwf txsta) (movlw 103) ;2400 baud at 4 MHz clock (movwf spbrg) :start-of-packet ;; ;; select memory bank 0 ;; (bcf status rp0) (bcf status rp1) (bsf rcsta cren) (call :receive-byte) (xorlw ,*stx*) (btfss status z) (goto :start-of-packet) :restart-packet (call :receive-byte) (xorlw ,*stx*) (btfss status z) (goto :start-of-packet) (clrf ,checksum) (movlw ,buffer) (movwf fsr) :get-next-byte (call :receive-byte) ;check for redundant start of packet (xorlw ,*stx*) (btfsc status z) (goto :restart-packet) (movf ,rxdata w) ;check for end of packet (xorlw ,*etx*) (btfsc status z) (goto :verify-checksum) (movf ,rxdata w) ;check for data link escape (xorlw ,*dle*) (btfsc status z) (call :receive-byte) (movf ,rxdata w) ;save the next byte (movwf indf) (addwf ,checksum f) (incf fsr f) (goto :get-next-byte) :verify-checksum (movf ,checksum f) ;checksum should be zero (btfss status z) (goto :start-of-packet) ;; ;; select memory bank 2 ;; (bsf status rp1) ;set up common parameters (movf ,address-l w) (movwf eeadr) (movf ,address-h w) (movwf eeadrh) (movlw ,packet-data) (movwf fsr) (movf ,data-count w) (movwf ,counter1) (btfsc status z) (goto :start-of-packet) ;perform the command (movf ,command w) (sublw ,*max-command*) (btfss status c) (goto :start-of-packet) (movf ,command w) (addwf pcl f) (goto :read-version) ;read version (goto :read-program) ;read program memory (flash) (goto :write-program) ;write program memory (flash) (goto :erase-program) ;erase program memory (flash) (goto :read-memory) ;read data memory (eeprom) (goto :write-memory) ;write data memory (eeprom) (goto :start-of-packet) ;read configuration (not implemented) (goto :start-of-packet) ;write configuration (not implemented) (goto :user-program) ;run user program ;;; in: stx stx 0 2 chksum etx ;;; out: stx stx 0 verl verh chksum etx :read-version (movlw ,*minor-version*) (movwf ,address-l) (movlw ,*major-version*) (movwf ,address-h) (movlw 4) (goto :send-packet) ;;; in: stx stx 1 dlen addrl addrh addru chksum etx ;;; out: stx stx 1 dlen addrl addrh addru data ... chksum etx :read-program ;; ;; select memory bank 3 ;; (bsf status rp0) (bsf eecon1 eepgd) (bsf eecon1 rd) (nop) (nop) ;; ;; select memory bank 2 ;; (bcf status rp0) (movf eedata w) (movwf indf) (incf fsr f) (movf eedath w) (movwf indf) (incf fsr f) (incf eeadr f) (btfsc status z) (incf eeadrh f) (decfsz ,counter1 f) (goto :read-program) (rlf ,data-count w) (addlw 5) (goto :send-packet) ;;; in: stx stx 2 blocks addrl addrh addru data ... chksum etx ;;; out: stx stx 2 chksum etx :write-program (movf eeadrh f) ;protect the bootloader (btfsc status z) (goto :start-of-packet) (movlw #x03) ;enforce a 4 word boundary (andwf eeadr w) (btfss status z) (goto :start-of-packet) (movlw 4) (movwf ,counter2) :write-block (movf indf w) (movwf eedata) (incf fsr f) (movf indf w) (movwf eedath) (incf fsr f) ;; ;; select memory bank 3 ;; (bsf status rp0) (movlw #x84) ;set program memory, write enable (movwf eecon1) (movlw #x55) (movwf eecon2) (movlw #xAA) (movwf eecon2) (bsf eecon1 wr) (nop) (nop) (clrf eecon1) ;; ;; select memory bank 2 ;; (bcf status rp0) (incf eeadr f) (btfsc status z) (incf eeadrh f) (decfsz ,counter2 f) (goto :write-block) (decfsz ,counter1 f) (goto :write-program) (goto :send-acknowledge) ;;; in: stx stx 3 rows addrl addrh addru chksum etx ;;; out: stx stx 3 chksum etx :erase-program (movf eeadrh f) ;protect the bootloader (btfsc status z) (goto :start-of-packet) (movlw #x1F) ;enforce a 32 word boundary (andwf eeadr w) (btfss status z) (goto :start-of-packet) ;; ;; select memory bank 3 ;; (bsf status rp0) (movlw #x94) ;set program memory, write enable (movwf eecon1) (movlw #x55) (movwf eecon2) (movlw #xAA) (movwf eecon2) (bsf eecon1 wr) (nop) (nop) (clrf eecon1) ;; ;; select memory bank 2 ;; (bcf status rp0) (movlw #x20) (addwf eeadr f) (btfsc status z) (incf eeadrh f) (decfsz ,counter1 f) (goto :erase-program) (goto :send-acknowledge) ;;; in: stx stx 4 dlen addrl addrh addru chksum etx ;;; out: stx stx 4 dlen addrl addrh addru data ... chksum etx :read-memory ;; ;; select memory bank 3 ;; (bsf status rp0) (clrf eecon1) (bsf eecon1 rd) ;; ;; select memory bank 2 ;; (bcf status rp0) (movf eedata w) (movwf indf) (incf fsr f) (incf eeadr f) (decfsz ,counter1 f) (goto :read-memory) (movf ,data-count w) (addlw 5) (goto :send-packet) ;;; in: stx stx 5 dlen addrl addrh addru data ... chksum etx ;;; out: stx stx 5 chksum etx :write-memory (movf indf w) (movwf eedata) (incf fsr f) ;; ;; select memory bank 3 ;; (bsf status rp0) (clrf eecon1) (bsf eecon1 wren) (movlw #x55) (movwf eecon2) (movlw #xAA) (movwf eecon2) (bsf eecon1 wr) (bcf eecon1 wren) :wm (btfsc eecon1 wr) (goto :wm) ;; ;; select memory bank 2 ;; (bcf status rp0) (incf eeadr f) (decfsz ,counter1 f) (goto :write-memory) ;; (goto :send-acknowledge) :send-acknowledge (movlw 1) :send-packet (movwf ,counter1) (movlw ,*stx*) (call :transmit-byte) (call :transmit-byte) (clrf ,checksum) (movlw ,buffer) (movwf fsr) :sp (movf indf w) (addwf ,checksum f) (incf fsr f) (call :send-next-byte) (decfsz ,counter1 f) (goto :sp) (comf ,checksum w) (addlw 1) (call :send-next-byte) (movlw ,*etx*) (call :transmit-byte) (goto :start-of-packet) :send-next-byte (movwf ,txdata) (xorlw ,*stx*) (btfsc status z) (goto :send-dle) (movf ,txdata w) (xorlw ,*etx*) (btfsc status z) (goto :send-dle) (movf ,txdata w) (xorlw ,*dle*) (btfss status z) (goto :write-next) :send-dle (movlw ,*dle*) (call :transmit-byte) :write-next (movf ,txdata w) :transmit-byte (bcf status rp1) :tb (btfss pir1 txif) (goto :tb) (movwf txreg) (return) :receive-byte (btfsc rcsta oerr) (goto :restart) :rb (btfss pir1 rcif) (goto :rb) (movf rcreg w) (movwf ,rxdata) (return) #x100 :user-program (clrf porta) (clrf portb) (bsf status rp0) (bcf status rp1) (movlw #x60) (iorwf osccon f) (clrf trisa) (movlw #xFF) (movwf trisb) (bcf status rp0) (clrf ,counter1) (clrf ,counter2) :main (clrf porta) (call :delay) (movlw #xFF) (movwf porta) (call :delay) (goto :main) :delay (clrf ,counter2) (clrf ,counter1) :dl (incfsz ,counter1 f) (goto :dl) (incfsz ,counter2 f) (goto :dl) (return) ))) (initialise *pic16f88*) (configure *pic16f88*) (print (read-configuration *pic16f88*)) (erase-data-memory *pic16f88*) (print (read-data-memory *pic16f88*)) (erase-program-memory *pic16f88*) (load-program-memory *pic16f88*) (print (read-program-memory *pic16f88* 256)) ;;;--------------------------------------------------------------------------- ;;;===========================================================================