From 297ac49867b750bfeeeca3a354619c527468cc41 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 10 Jul 2013 03:57:48 +0000 Subject: added bootloader for IHU git-svn-id: https://svn.spreadspace.org/mur.sat@807 7de4ea59-55d0-425e-a1af-a3118ea81d4c --- software/ihu/Makefile | 11 + software/ihu/ihu.asm | 23 +- software/ihu/tables.inc | 8 + software/pic.bootloader/Makefile | 31 ++ software/pic.bootloader/Makefile-IHU | 26 ++ software/pic.bootloader/bootloader-IHU.asm | 96 +++++++ software/pic.bootloader/cmds-16f887.inc | 117 ++++++++ software/pic.bootloader/com-16f887-uart.inc | 75 +++++ software/pic.bootloader/downloader.py | 339 ++++++++++++++++++++++ software/pic.bootloader/generic-defines.inc | 50 ++++ software/pic.bootloader/generic-init.inc | 61 ++++ software/pic.bootloader/generic-mainloop.inc | 174 ++++++++++++ software/pic.bootloader/ihexpic.py | 405 +++++++++++++++++++++++++++ software/pic.bootloader/proto.txt | 200 +++++++++++++ 14 files changed, 1609 insertions(+), 7 deletions(-) create mode 100644 software/pic.bootloader/Makefile create mode 100644 software/pic.bootloader/Makefile-IHU create mode 100644 software/pic.bootloader/bootloader-IHU.asm create mode 100644 software/pic.bootloader/cmds-16f887.inc create mode 100644 software/pic.bootloader/com-16f887-uart.inc create mode 100755 software/pic.bootloader/downloader.py create mode 100644 software/pic.bootloader/generic-defines.inc create mode 100644 software/pic.bootloader/generic-init.inc create mode 100644 software/pic.bootloader/generic-mainloop.inc create mode 100644 software/pic.bootloader/ihexpic.py create mode 100644 software/pic.bootloader/proto.txt (limited to 'software') diff --git a/software/ihu/Makefile b/software/ihu/Makefile index a5184a8..3b4bb1e 100644 --- a/software/ihu/Makefile +++ b/software/ihu/Makefile @@ -32,3 +32,14 @@ PROJECT := ihu PROC_TYPE := 16F887 include ../pic.include.mk + +DOWNLOADER := ../pic.bootloader/downloader.py +BOOT_NAME := IHU +BOOT_BAUD := 57600 + +download: $(HEXFILE) + @$(DOWNLOADER) --name=$(BOOT_NAME) --cmd write $< + @$(DOWNLOADER) --name=$(BOOT_NAME) --cmd verify $< + +boot: + @$(DOWNLOADER) --name=$(BOOT_NAME) --cmd boot dummy diff --git a/software/ihu/ihu.asm b/software/ihu/ihu.asm index a4c53a4..e84eb9a 100644 --- a/software/ihu/ihu.asm +++ b/software/ihu/ihu.asm @@ -32,8 +32,13 @@ LIST p=16F887 include "p16f887.inc" - __config _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_NSLEEP & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC - __config _CONFIG2, _BOR21V & _WRT_OFF + ;; This is specified via bootloader-IHU.asm + ;; __config _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_NSLEEP & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC + ;; __config _CONFIG2, _BOR21V & _WRT_OFF + +BOOTLOADER EQU H'003' +USERVECT EQU H'100' +ISRVECT EQU H'104' ;; ------------------------------------- ;; DEFINES @@ -114,12 +119,12 @@ STATUS_TEMP EQU H'007F' ;; ------------------------------------- ;; Reset Vector - org 0 + org USERVECT ; end of bootloader goto init ;; ------------------------------------- ;; Interrupt Vector - org 4 + org ISRVECT ; replocated ISR vector ;; save context movwf W_TEMP swapf STATUS,W @@ -199,7 +204,8 @@ init clrf PSTRCON ; disable pulse steering movlw b'00010000' ; preselct 125 kHz, clock source as configured by configuration word movwf OSCCON - movlw b'11001111' ; input: RA0-RA3(analog),RA6-RA7(OSC); output: RA4-RA5(1wire) + ;; movlw b'11001111' ; input: RA0-RA3(analog),RA6-RA7(OSC); output: RA4-RA5(1wire) + movlw b'11011111' ; input: RA0-RA3(analog),RA6-RA7(OSC), RA4(BOOTPIN); output: RA5(1wire) movwf TRISA movlw b'11111111' ; input: all (interrupts and stats) movwf TRISB @@ -235,14 +241,17 @@ init call i2c_init clrf TMR0 - bsf INTCON,GIE clrf TMP + bsf INTCON,GIE + + btfsc RTC_RST ; if RTC is already finished, initialize it! + call rtc_init ; this maybe happend already via interrupt but better save than sorry goto main ;; ------------------------------------- ;; TABLES - include "tables.inc" + include "tables.inc" ; this needs to stay inside 0x100 and 0x200 ;; ------------------------------------- ;; SUBROUTINES diff --git a/software/ihu/tables.inc b/software/ihu/tables.inc index 3e42a41..99d104f 100644 --- a/software/ihu/tables.inc +++ b/software/ihu/tables.inc @@ -31,6 +31,8 @@ ;; ------------------------------------- ;; digit digit + clrf PCLATH ; this table is betwenn 0x100 and 0x200 + incf PCLATH,f ; load PCLATH without changing W andlw b'00001111' addwf PCL,f retlw '0' @@ -51,6 +53,8 @@ digit retlw 'F' mul10 + clrf PCLATH ; this table is betwenn 0x100 and 0x200 + incf PCLATH,f ; load PCLATH without changing W addwf PCL,f retlw .0 retlw .10 @@ -71,6 +75,8 @@ mul10 retlw .160 daysL + clrf PCLATH ; this table is betwenn 0x100 and 0x200 + incf PCLATH,f ; load PCLATH without changing W addwf PCL,f retlw .0 retlw .0 @@ -87,6 +93,8 @@ daysL retlw .79 daysH + clrf PCLATH ; this table is betwenn 0x100 and 0x200 + incf PCLATH,f ; load PCLATH without changing W addwf PCL,f retlw .0 retlw .0 diff --git a/software/pic.bootloader/Makefile b/software/pic.bootloader/Makefile new file mode 100644 index 0000000..fb91150 --- /dev/null +++ b/software/pic.bootloader/Makefile @@ -0,0 +1,31 @@ +## +## spreadspace pic utils +## +## +## Copyright (C) 2011 Christian Pointner +## +## This file is part of spreadspace pic utils. +## +## spreadspace pic utils 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 3 of the License, or +## any later version. +## +## spreadspace pic utils 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 spreadspace pic utils. If not, see . +## + +ifndef TARGET +$(error You need to specify a target, call make with TARGET=xyz) +endif + +all: + $(MAKE) -f Makefile-$(TARGET) $@ + +%: + $(MAKE) -f Makefile-$(TARGET) $@ diff --git a/software/pic.bootloader/Makefile-IHU b/software/pic.bootloader/Makefile-IHU new file mode 100644 index 0000000..4689f83 --- /dev/null +++ b/software/pic.bootloader/Makefile-IHU @@ -0,0 +1,26 @@ +## +## spreadspace pic utils +## +## +## Copyright (C) 2011 Christian Pointner +## +## This file is part of spreadspace pic utils. +## +## spreadspace pic utils 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 3 of the License, or +## any later version. +## +## spreadspace pic utils 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 spreadspace pic utils. If not, see . +## + +PROJECT := bootloader-IHU +PROC_TYPE := 16F887 + +include ../pic.include.mk diff --git a/software/pic.bootloader/bootloader-IHU.asm b/software/pic.bootloader/bootloader-IHU.asm new file mode 100644 index 0000000..bdf56f8 --- /dev/null +++ b/software/pic.bootloader/bootloader-IHU.asm @@ -0,0 +1,96 @@ + ;; + ;; spreadspace pic utils + ;; + ;; + ;; Copyright (C) 2011 Christian Pointner + ;; + ;; This file is part of spreadspace pic utils. + ;; + ;; spreadspace pic utils 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 3 of the License, or + ;; any later version. + ;; + ;; spreadspace pic utils 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 spreadspace pic utils. If not, see . + ;; + ;; ------------------------------------- + ;; PREAMBLE + + LIST p=16F887 + include "p16f887.inc" + __config _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_NSLEEP & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC + __config _CONFIG2, _BOR21V & _WRT_256 + + ;; ------------------------------------- + ;; DEFINES (chip/com specific) +#define BOOTPIN PORTA,4 +USERVECT EQU H'100' +ISRVECT EQU USERVECT + H'4' +FLASH_BOUNDARY EQU b'00001111' ; flash write boundary is at 16 bytes boundaries + +VERSION_MAJ EQU .0 +VERSION_MIN EQU .1 +NAME_0 EQU 'I' +NAME_1 EQU 'H' +NAME_2 EQU 'U' +DEVID_L EQU H'82' +DEVID_H EQU H'20' +FLASH_SIZE_L EQU H'00' +FLASH_SIZE_H EQU H'20' ; 0x2000 -> 8192 Words of Flash +FSS EQU .16 ; writing is done 8 words at a time but 16 words get erased +EEPROM_SIZE_L EQU H'00' +EEPROM_SIZE_H EQU H'01' ; 0x0100 -> 256 Bytes of EEPROM +MESS EQU .64 ; this limit is because of to combuff size and single byte len field for messages +SUPPORTED_H EQU .0 +SUPPORTED_L EQU b'00000110' ; only read/write flash is supported by now + +#define HOOK_CMD_RESET cmd_not_impl +#define HOOK_CMD_R_FLASH cmd_r_flash +#define HOOK_CMD_W_FLASH cmd_w_flash +#define HOOK_CMD_R_EEPROM cmd_not_impl +#define HOOK_CMD_W_EEPROM cmd_not_impl +#define HOOK_CMD_R_CONFIG cmd_not_impl +#define HOOK_CMD_W_CONFIG cmd_not_impl + + ;; Variables +combuff EQU H'0020' +current_cmdlen EQU H'0070' +csum EQU H'0071' +flags EQU H'007D' +cnt EQU H'007F' + + ;; ------------------------------------- + ;; DEFINES (defines) +#include "generic-defines.inc" + + ;; ------------------------------------- + ;; Bootloader init +#include "generic-init.inc" + + ;; ------------------------------------- + ;; Bootloader (com specific subroutines and init) +#include "com-16f887-uart.inc" + + ;; ------------------------------------- + ;; Bootloader (generic init/body) +#include "generic-mainloop.inc" + + ;; ------------------------------------- + ;; chip specific commands +#include "cmds-16f887.inc" + + ;; ------------------------------------- + ;; ------------------------------------- + ;; dummy user code + org USERVECT + goto USERVECT + + ;; ------------------------------------- + ;; END + end diff --git a/software/pic.bootloader/cmds-16f887.inc b/software/pic.bootloader/cmds-16f887.inc new file mode 100644 index 0000000..144150e --- /dev/null +++ b/software/pic.bootloader/cmds-16f887.inc @@ -0,0 +1,117 @@ + ;; + ;; spreadspace pic utils + ;; + ;; + ;; Copyright (C) 2011 Christian Pointner + ;; + ;; This file is part of spreadspace pic utils. + ;; + ;; spreadspace pic utils 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 3 of the License, or + ;; any later version. + ;; + ;; spreadspace pic utils 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 spreadspace pic utils. If not, see . + ;; + + ;; flash read -------- +cmd_r_flash + movlw FSS ; initialize EEADR:EEADRH and FSR + movwf cnt + movlw b'01011000' + movwf STATUS + movlw combuff + .2 + movwf FSR + movf INDF,w + movwf EEADR + incf FSR,f + movf INDF,w + movwf EEADRH +read_flash_segment_loop + bsf STATUS,RP0 ; perform the actual read + bsf EECON1,EEPGD + bsf EECON1,RD + nop + nop + bcf STATUS,RP0 + movf EEDAT,w ; load code word from EEDAT:EEDATH to combuff + movwf INDF + incf FSR,f + movf EEDATH,w + movwf INDF + incf FSR,f + incfsz EEADR,f ; increment flash address + goto read_flash_segment_next + incf EEADRH,f +read_flash_segment_next + decfsz cnt,f + goto read_flash_segment_loop + bcf STATUS,RP1 + clrf combuff + .2 ; = E_OK + movlw .1 + .2*FSS ; bytes to send + call send_answer + goto wait_new_cmd + + ;; flash write -------- +cmd_w_flash + movf combuff + .3,f ; if addr[15:8] == 0 -> boot loader section + btfsc STATUS,Z + goto address_prohibited + movlw FLASH_BOUNDARY ; addr on boundary? + andwf combuff + .2,w + btfss STATUS,Z + goto address_invalid + movlw FSS ; initialize EEADR:EEADRH and FSR + movwf cnt + movlw b'01011000' + movwf STATUS + movlw combuff + .2 + movwf FSR + movf INDF,w + movwf EEADR + incf FSR,f + movf INDF,w + movwf EEADRH + +write_flash_segment_loop + incf FSR,f ; load code word into EEDAT:EEDATH + movf INDF,w + movwf EEDAT + incf FSR,f + movf INDF,w + movwf EEDATH + + bsf STATUS,RP0 ; now start the acutal write sequence + bsf EECON1,EEPGD + bsf EECON1,WREN + movlw H'55' + movwf EECON2 + movlw H'AA' + movwf EECON2 + bsf EECON1,WR + nop + nop + bcf EECON1,WREN + bcf STATUS,RP0 + incfsz EEADR,f ; increment flash address + goto write_flash_segment_next + incf EEADRH,f +write_flash_segment_next + decfsz cnt,f + goto write_flash_segment_loop + bsf STATUS,RP0 + clrw ; check if a write error occured + btfsc EECON1,WRERR + movlw E_FLASH_WERR + bcf STATUS,RP1 + bcf STATUS,RP0 + movwf combuff + .2 ; = E_OK + movlw .1 ; bytes to send + call send_answer + goto wait_new_cmd diff --git a/software/pic.bootloader/com-16f887-uart.inc b/software/pic.bootloader/com-16f887-uart.inc new file mode 100644 index 0000000..b2b6812 --- /dev/null +++ b/software/pic.bootloader/com-16f887-uart.inc @@ -0,0 +1,75 @@ + ;; + ;; spreadspace pic utils + ;; + ;; + ;; Copyright (C) 2011 Christian Pointner + ;; + ;; This file is part of spreadspace pic utils. + ;; + ;; spreadspace pic utils 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 3 of the License, or + ;; any later version. + ;; + ;; spreadspace pic utils 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 spreadspace pic utils. If not, see . + ;; + + ;; --- transmit byte and add it to csum +com_tx_byte + btfss PIR1,TXIF + goto com_tx_byte + movwf TXREG + xorwf csum,f + return + + ;; ---- wait for byte to be received +com_rx_byte + btfsc RCSTA,OERR + goto uart_rx_oe + btfss PIR1,RCIF + goto com_rx_byte + btfsc RCSTA,FERR + goto uart_rx_fe + movf RCREG,w + return + +uart_rx_oe ; recover from overflow + bcf RCSTA,CREN + bsf RCSTA,CREN + goto com_rx_byte + +uart_rx_fe ; recover from framing error + movf RCREG,w + goto com_rx_byte + + ;; ----- initialize com (not a subroutine, com_init is called by generic_init +com_init + ;; bank 3 + bsf STATUS,RP0 + bsf STATUS,RP1 + ;;movlw b'00001000' ; TX non-inverted, 16bit Baudrate, no auto baud detect + movlw b'00011000' ; TX inverted, 16bit Baudrate, no auto baud detect + movwf BAUDCTL + + ;; bank 1 + bcf STATUS,RP1 + movlw b'01110000' ; set internal OSC to 8MHz + movwf OSCCON + movlw b'00100100' ; Baudrate = High Speed, async mode, transmit enabled, 8bit + movwf TXSTA + movlw .34 ; Baudrate = 57600 (@ 8MHz) -> -0,79 % Error + ;; movlw .51 ; Baudrate = 38400 (@ 8MHz) -> -0,002 % Error + ;; movlw .103 ; Baudrate = 19200 (@ 8MHz) -> 0,16 % Error + movwf SPBRG + clrf SPBRGH + + ;; bank 0 + bcf STATUS,RP0 + movlw b'10010000' ; enable Serial Port, 8bit, enable continues receive, disable address detection + movwf RCSTA diff --git a/software/pic.bootloader/downloader.py b/software/pic.bootloader/downloader.py new file mode 100755 index 0000000..27b15c3 --- /dev/null +++ b/software/pic.bootloader/downloader.py @@ -0,0 +1,339 @@ +#!/usr/bin/python +# +# spreadspace pic utils +# +# +# Copyright (C) 2011 Christian Pointner +# +# This file is part of spreadspace pic utils. +# +# spreadspace pic utils 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 3 of the License, or +# any later version. +# +# spreadspace pic utils 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 spreadspace pic utils. If not, see . +# + +'''spreadspace simple pic downloader.''' + +VERSION_MAJ = 0 +VERSION_MIN = 1 + +### HEX File Magic + +def load_hex(file): + from ihexpic import IHexPic + + fin = file + if fin == '-': + fin = sys.stdin + elif not os.path.isfile(fin): + print >> sys.stderr, "ERROR: File not found: %s" % fin + sys.exit(1) + + hexdata = IHexPic() + hexdata.load_from_file(fin) + return hexdata + +def write_hex(file, codedata): + from ihexpic import IHexPic + + fout = file + if fout == '-': + fout = sys.stdout + + hexdata = IHexPic() + hexdata.load_from_dict(codedata) + hexdata.write_to_file(fout) + +def get_lowest_flash_addr(hexdata, fss): + lowest_code_addr = hexdata.get_lowest_addr() + return lowest_code_addr - (lowest_code_addr%fss) + +def get_highest_flash_addr(hexdata, fss): + highest_code_addr = hexdata.get_highest_addr() + return highest_code_addr + (fss - highest_code_addr%fss) + +def create_flash_image(hexdata, fss, sa, ea): + img = ( sa, [0xFFFF]*(ea-sa) ) + for a,d in hexdata.items(): + if a < ea: + img[1][a-sa] = d + return img + +def create_flash_segments(hexdata, fs, fss): + sa = get_lowest_flash_addr(hexdata, fss) + ea = get_highest_flash_addr(hexdata, fss) + if ea >= fs: + print >> sys.stderr, "WARNING: the hex file contains data after end of flash, these words will be ignored" + ea = fs + + img = create_flash_image(hexdata, fss, sa, ea) + for i in xrange(0, ea, fss): + slice = tuple(img[1][i:i+fss]) + if not all( (elem == 0xFFFF) for elem in slice): + yield (i + img[0], slice) + + +### Interface to Bootloader + +def open_serial(device, baud): + import os + import tty + import termios + import serial + + print >> sys.stderr, "opening %s (%s Baud)" % (device, baud) + + try: + dev = serial.Serial(port=device, baudrate=baud, timeout=3) + dev.flushInput() + dev.flushOutput() + return dev + + except (ValueError, serial.SerialException), msg: + print >> sys.stderr, "ERROR: opening serial device: %s" % msg + sys.exit(3) + +def calc_csum(str): + cs = 0 + for c in str: + cs ^= c + return cs + +def exec_command(dev, cmd, param, answer): + import struct + + return_codes = { 0: "OK", 1: "invalid command", 2: "bad checksum", + 3: "not implemented", 4: "flash write error", + 5: "address invalid", 6: "address prohibited", + 7: "value out of bounds" } + + dev.flushInput() + dev.flushOutput() + + cstr = bytearray(struct.pack('> sys.stderr, "ERROR: timeout while reading response header (expected %d bytes, got %d)" % (4, len(astr)) + sys.exit(4) + + if astr[0] != cstr[0]: + print >> sys.stderr, "ERROR: bootloader returned wrong command code" + sys.exit(4) + + ret = astr[2] + if ret != 0: + rstr = "invalid return code" + try: + rstr = return_codes[ret] + except KeyError: + pass + print >> sys.stderr, "ERROR: bootloader returned %d: %s" % (ret, rstr) + sys.exit(4) + + answer_len = astr[1] - 4 + if answer_len < struct.calcsize(answer): + print >> sys.stderr, "ERROR: short answer %d bytes received: expected %s bytes" % (answer_len, struct.calcsize(answer)) + sys.exit(4) + + if answer_len > 0: + tmp = bytearray() + tmp += dev.read(answer_len) + if len(tmp) < answer_len: + print >> sys.stderr, "ERROR: timeout while reading response (expected %d bytes, got %d)" % (answer_len, len(tmp)) + sys.exit(4) + + astr += tmp + + if 0 != calc_csum(astr): + print >> sys.stderr, "ERROR: checksum error" + sys.exit(4) + + return struct.unpack_from(answer, astr, 3) + +### low level commands + +def cmd_identify(dev, name): + data = exec_command(dev, 1, '', '> sys.stderr, "incompatible protocol version, expected: %d, got: %d" % (VERSION_MAJ, id['ver_maj']) + sys.exit(4) + if name and id['name'] != name: + print >> sys.stderr, "ERROR: the bootloaders name '%s' differs from the one supplied via" % id['name'] + print >> sys.stderr, " command line option '%s'. Are sure you are connected to the" % name + print >> sys.stderr, " right device?" + sys.exit(4) + + print >> sys.stderr, "connected with Bootloader '%s' Version %d.%d, (ID=%04X, %d words Flash, FSS=%d, %d bytes EEPROM, MESS=%d)" % \ + (id['name'], id['ver_maj'], id['ver_min'], id['devid'], id['fs'], id['fss'], id['es'], id['mess']) + return id + +def cmd_boot(dev): + exec_command(dev, 2, '', '<') + +def cmd_reset(dev, id): + exec_command(dev, 3, '', '<') + +def cmd_read_flash_segment(dev, id, addr): + param = struct.pack('> sys.stderr, "%05X: %s" % (segment[0], ''.join('%04X '%i for i in segment[1])) + cmd_write_flash_segment(dev, id, segment[0], segment[1]) + +def read_flash(dev, id, file): + codedata = {} + for addr in xrange(0, id['fs'], id['fss']): + data = cmd_read_flash_segment(dev, id, addr) +# print >> sys.stderr, "%05X: %s" % (addr, ''.join('%04X '%i for i in data)) + a = addr + for d in data: + if d != 0x3FFF: + codedata[a] = d + a += 1 + write_hex(file, codedata) + +def verify_flash(dev, id, file): + hexdata = load_hex(file) + err = 0 + for segment in create_flash_segments(hexdata, id['fs'], id['fss']): + flashdata = cmd_read_flash_segment(dev, id, segment[0]) + for file,flash in zip(segment[1] , flashdata): + if flash == 0x3FFF: + flash = 0xFFFF + if flash != file: + err = 1 + break + + if err !=0: + break + + if err != 0: + print >> sys.stderr, "ERROR: verify failed!" + sys.exit(-1) + else: + print >> sys.stderr, "verify ok!" + sys.exit(0) + +commands = { + 'boot': boot, + 'write': write_flash, + 'read': read_flash, + 'verify': verify_flash +} + +### Main + +if __name__ == '__main__': + import getopt + import sys + import os + import struct + + usage = '''spreadspace simple pic downloader. +Usage: + python downloader.py [options] INFILE + +Arguments: + INFILE name of hex file for downloading. + Use '-' for reading from stdin. + +Options: + -h, --help this help message. + -v, --version version info. + --cmd=N the command to execute, one out of: "boot,read,write,verify" + --device=N the serial port to use (default: /dev/ttyUSB0). + --baud=N baudrate to use (default: 57600). + --name=N the expected name of the bootloader. +''' + + device = "/dev/ttyUSB0" + baudrate = 57600 + name = None + cmd = None + + try: + opts, args = getopt.getopt(sys.argv[1:], "hv", + ["help", "version", "cmd=", "device=", "baud=", "name="]) + + for o, a in opts: + if o in ("-h", "--help"): + print >> sys.stderr, usage + sys.exit(0) + elif o in ("-v", "--version"): + print >> sys.stderr, "Version %d.%d" % (VERSION_MAJ, VERSION_MIN) + sys.exit(0) + elif o in ("--cmd"): + cmd = a + elif o in ("--device"): + device = a + elif o in ("--baud"): + baudrate = a + elif o in ("--name"): + name = a + + if not args: + raise getopt.GetoptError('Hex file is not specified') + + if len(args) > 1: + raise getopt.GetoptError('Too many arguments') + + if not cmd: + raise getopt.GetoptError('You have to supply a command (boot,read,write,verify)') + + except getopt.GetoptError, msg: + print >> sys.stderr, "ERROR: %s" % msg + print >> sys.stderr, usage + sys.exit(2) + + dev = open_serial(device, baudrate) + id = cmd_identify(dev, name) + + try: + commands[cmd](dev, id, args[0]) + except KeyError: + print >> sys.stderr, "ERROR: unkown command '%s'" % cmd diff --git a/software/pic.bootloader/generic-defines.inc b/software/pic.bootloader/generic-defines.inc new file mode 100644 index 0000000..54ca01b --- /dev/null +++ b/software/pic.bootloader/generic-defines.inc @@ -0,0 +1,50 @@ + ;; + ;; spreadspace pic utils + ;; + ;; + ;; Copyright (C) 2011 Christian Pointner + ;; + ;; This file is part of spreadspace pic utils. + ;; + ;; spreadspace pic utils 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 3 of the License, or + ;; any later version. + ;; + ;; spreadspace pic utils 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 spreadspace pic utils. If not, see . + ;; + + ;; ERROR codes +E_OK EQU .0 +E_INV_CMD EQU .1 +E_BAD_CSUM EQU .2 +E_NOT_IMPL EQU .3 +E_FLASH_WERR EQU .4 +E_ADDR_INVALID EQU .5 +E_ADDR_PROHIB EQU .6 +E_VALUE_OOB EQU .7 + + ;; CMD codes +CMD_INVALID EQU .0 + +CMD_IDENTIFY EQU .1 +CMD_BOOT EQU .2 +CMD_RESET EQU .3 +CMD_R_FLASH EQU .4 +CMD_W_FLASH EQU .5 +CMD_R_EEPROM EQU .6 +CMD_W_EEPROM EQU .7 +CMD_R_CONFIG EQU .8 +CMD_W_CONFIG EQU .9 + +CMD_MAX EQU .9 +CMD_MIN_LEN EQU .3 + + ;; Flags +#define F_CMD_STARTED flags,0 diff --git a/software/pic.bootloader/generic-init.inc b/software/pic.bootloader/generic-init.inc new file mode 100644 index 0000000..4c51fa9 --- /dev/null +++ b/software/pic.bootloader/generic-init.inc @@ -0,0 +1,61 @@ + ;; + ;; spreadspace pic utils + ;; + ;; + ;; Copyright (C) 2011 Christian Pointner + ;; + ;; This file is part of spreadspace pic utils. + ;; + ;; spreadspace pic utils 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 3 of the License, or + ;; any later version. + ;; + ;; spreadspace pic utils 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 spreadspace pic utils. If not, see . + ;; + + org .0 + btfsc BOOTPIN + goto USERVECT + goto com_init + + ;; ------------------------------------- + ;; goto user ISR + org .4 +isr + goto ISRVECT + + ;; ------------------------------------- + ;; Bootloader (Generic Subroutines) +send_answer ; generic answer message, leave len of data in W + addlw .3 + movwf combuff + .1 + decf combuff + .1,w + movwf cnt + movlw combuff + movwf FSR + clrf csum +send_answer_next + movf INDF,w + call com_tx_byte + incf FSR,f + decfsz cnt,f + goto send_answer_next + + movf csum,w + call com_tx_byte + return + + ;; ------------------ +ack_cmd ; short answers which only contain return code + movwf combuff + .2 + movlw .1 + call send_answer + return + diff --git a/software/pic.bootloader/generic-mainloop.inc b/software/pic.bootloader/generic-mainloop.inc new file mode 100644 index 0000000..1e93648 --- /dev/null +++ b/software/pic.bootloader/generic-mainloop.inc @@ -0,0 +1,174 @@ + ;; + ;; spreadspace pic utils + ;; + ;; + ;; Copyright (C) 2011 Christian Pointner + ;; + ;; This file is part of spreadspace pic utils. + ;; + ;; spreadspace pic utils 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 3 of the License, or + ;; any later version. + ;; + ;; spreadspace pic utils 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 spreadspace pic utils. If not, see . + ;; + +wait_new_cmd + movlw combuff + movwf FSR + clrf combuff + clrf current_cmdlen + clrf flags + +wait_cmd + call com_rx_byte + movwf INDF ; process received byte + incf FSR,f + btfss F_CMD_STARTED + goto wait_cmd_len + movf current_cmdlen,f + btfsc STATUS,Z + goto new_cmd + decfsz current_cmdlen,f + goto wait_cmd + goto exec_cmd + +wait_cmd_len ; command code received, now wait for length + bsf F_CMD_STARTED + goto wait_cmd + +new_cmd ; got new command code and length -> check it + movf combuff,w + sublw CMD_MAX + btfss STATUS,C + goto invalid_cmd + movlw CMD_MIN_LEN ; check for minimum command len + subwf combuff + .1,w + btfss STATUS,C + goto invalid_cmd + movlw .2 ; 2 bytes already received + subwf combuff + .1,w + movwf current_cmdlen + goto wait_cmd + +exec_cmd ; command is complete -> check csum + movlw combuff + movwf FSR + movf combuff + .1,w + movwf cnt + clrf csum +exec_cmd_check_csum + movf INDF,w + xorwf csum,f + incf FSR,f + decfsz cnt,f + goto exec_cmd_check_csum + movf csum,f + btfss STATUS,Z + goto csum_error + + movf combuff,w ; command is correct and complete -> dispatch + addwf PCL,f + goto wait_new_cmd + goto cmd_identify ; identify + goto cmd_boot ; boot + goto HOOK_CMD_RESET ; reset + goto HOOK_CMD_R_FLASH ; read flash segment + goto HOOK_CMD_W_FLASH ; write flash segment + goto HOOK_CMD_R_EEPROM ; read eeprom + goto HOOK_CMD_W_EEPROM ; write eeprom + goto HOOK_CMD_R_CONFIG ; read config + goto HOOK_CMD_R_CONFIG ; write config + + ;; ** generic error messages ******* +invalid_cmd ; received command code is not known or len is bogus + movlw E_INV_CMD + call ack_cmd + goto wait_new_cmd + +csum_error ; received command has an invalid check sum + movlw E_BAD_CSUM + call ack_cmd + goto wait_new_cmd + +address_invalid ; received command uses invalid address (i.e. not aligned to 16bytes) + movlw E_ADDR_INVALID + call ack_cmd + goto wait_new_cmd + +address_prohibited ; received command uses prohibited address (i.e. FLASH < 0x100) + movlw E_ADDR_PROHIB + call ack_cmd + goto wait_new_cmd + + ;; ** generic command handlers ************ + ;; ** identify ******* +cmd_identify + clrf csum + movf combuff,w + call com_tx_byte + + movlw .19 + call com_tx_byte + + movlw E_OK + call com_tx_byte + + movlw VERSION_MIN + call com_tx_byte + movlw VERSION_MAJ + call com_tx_byte + + movlw NAME_0 + call com_tx_byte + movlw NAME_1 + call com_tx_byte + movlw NAME_2 + call com_tx_byte + + movlw DEVID_L + call com_tx_byte + movlw DEVID_H + call com_tx_byte + + movlw FLASH_SIZE_L + call com_tx_byte + movlw FLASH_SIZE_H + call com_tx_byte + movlw FSS + call com_tx_byte + + movlw EEPROM_SIZE_L + call com_tx_byte + movlw EEPROM_SIZE_H + call com_tx_byte + movlw MESS + call com_tx_byte + + movlw SUPPORTED_L + call com_tx_byte + movlw SUPPORTED_H + call com_tx_byte + + movf csum,w + call com_tx_byte + goto wait_new_cmd + + ;; ** boot ******* +cmd_boot + movlw E_OK + call ack_cmd + goto USERVECT + + ;; ** not implemented commands ******* +cmd_not_impl + movlw E_NOT_IMPL + call ack_cmd + goto wait_new_cmd diff --git a/software/pic.bootloader/ihexpic.py b/software/pic.bootloader/ihexpic.py new file mode 100644 index 0000000..e30204c --- /dev/null +++ b/software/pic.bootloader/ihexpic.py @@ -0,0 +1,405 @@ +# spreadspace pic utils +# +# +# Copyright (C) 2011 Christian Pointner +# +# This file is part of spreadspace pic utils. +# +# spreadspace pic utils 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 3 of the License, or +# any later version. +# +# spreadspace pic utils 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 spreadspace pic utils. If not, see . +# +#********************************************************************* +# This is based on IntelHex 1.4 +# which can be found at: http://www.bialix.com/intelhex/ +# +# +# Copyright (c) 2005-2012, Alexander Belchenko +# All rights reserved. +# +# Redistribution and use in source and binary forms, +# with or without modification, are permitted provided +# that the following conditions are met: +# +# * Redistributions of source code must retain +# the above copyright notice, this list of conditions +# and the following disclaimer. +# * Redistributions in binary form must reproduce +# the above copyright notice, this list of conditions +# and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the author nor the names +# of its contributors may be used to endorse +# or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#********************************************************************* + +'''Intel HEX file format reader and writer for PIC Microcontroller.''' + + +from array import array +from binascii import hexlify, unhexlify +from bisect import bisect_right +import sys + + +class IHexPic(object): + ''' Intel HEX file reader for PIC Microcontroller. ''' + + def __init__(self): + # private members + self._buf = {} + self._offset = 0 + + def _decode_record(self, s, line=0): + '''Decode one record of HEX file. + + @param s line with HEX record. + @param line line number (for error messages). + + @raise EndOfFile if EOF record encountered. + ''' + s = s.rstrip('\r\n') + if not s: + return # empty line + + if s[0] == ':': + try: + bin = array('B', unhexlify(str(s[1:]))) + except (TypeError, ValueError): + # this might be raised by unhexlify when odd hexascii digits + raise HexRecordError(line=line) + length = len(bin) + if length < 5: + raise HexRecordError(line=line) + else: + raise HexRecordError(line=line) + + record_length = bin[0] + if length != (5 + record_length): + raise RecordLengthError(line=line) + if record_length%2 != 0: + raise RecordLengthError(line=line) + + addr = bin[1]*256 + bin[2] + if addr%2 != 0: + raise RecordAlignmentError(line=line) + + record_type = bin[3] + if not (0 <= record_type <= 5): + raise RecordTypeError(line=line) + + crc = sum(bin) + crc &= 0x0FF + if crc != 0: + raise RecordChecksumError(line=line) + + if record_type == 0: + # data record + addr += self._offset + for i in xrange(4, 4+record_length, 2): + addr16 = addr/2 + if not self._buf.get(addr16, None) is None: + raise AddressOverlapError(address=addr16, line=line) + self._buf[addr16] = bin[i] + (bin[i+1]<<8) + addr += 2 # FIXME: addr should be wrapped + # BUT after 02 record (at 64K boundary) + # and after 04 record (at 4G boundary) + + elif record_type == 1: + # end of file record + if record_length != 0: + raise EOFRecordError(line=line) + raise _EndOfFile + + elif record_type == 2: + # Extended 8086 Segment Record + if record_length != 2 or addr != 0: + raise ExtendedSegmentAddressRecordError(line=line) + self._offset = (bin[4]*256 + bin[5]) * 16 + + elif record_type == 4: + # Extended Linear Address Record + if record_length != 2 or addr != 0: + raise ExtendedLinearAddressRecordError(line=line) + self._offset = (bin[4]*256 + bin[5]) * 65536 + + else: + raise UnsupportedRecordTypeError(type=record_type, line=line) + + + def load_from_file(self, fobj): + """Load hex file into internal buffer. + + @param fobj file name or file-like object + """ + if getattr(fobj, "read", None) is None: + fobj = open(fobj, "r") + fclose = fobj.close + else: + fclose = None + + line = 0 + + try: + decode = self._decode_record + try: + for s in fobj: + line += 1 + decode(s, line) + except _EndOfFile: + pass + finally: + if fclose: + fclose() + + def load_from_dict(self, dikt): + """Load data from dictionary. Dictionary should contain int keys + representing addresses. Values should be the data to be stored in + those addresses in unsigned char form (i.e. not strings). + + The contents of the dict will be merged with this object and will + overwrite any conflicts. + """ + s = dikt.copy() + for k in s.keys(): + if type(k) not in (int, long) or k < 0: + raise ValueError('Source dictionary should have only int keys') + self._buf.update(s) + + def write_to_file(self, f): + """Write data to file f in HEX format. + + @param f filename or file-like object for writing + """ + fwrite = getattr(f, "write", None) + if fwrite: + fobj = f + fclose = None + else: + fobj = file(f, 'w') + fwrite = fobj.write + fclose = fobj.close + + # Translation table for uppercasing hex ascii string. + # timeit shows that using hexstr.translate(table) + # is faster than hexstr.upper(): + # 0.452ms vs. 0.652ms (translate vs. upper) + if sys.version_info[0] >= 3: + table = bytes(range(256)).upper() + else: + table = ''.join(chr(i).upper() for i in range(256)) + + + # data + addresses = self._buf.keys() + addresses.sort() + addr_len = len(addresses) + if addr_len: + minaddr = addresses[0] + maxaddr = addresses[-1] + + if maxaddr > 65535/2: + need_offset_record = True + else: + need_offset_record = False + high_ofs = 0 + + cur_addr = minaddr + cur_ix = 0 + + while cur_addr <= maxaddr: + if need_offset_record: + bin = array('B', str('\0'*7)) + bin[0] = 2 # reclen + bin[1] = 0 # offset msb + bin[2] = 0 # offset lsb + bin[3] = 4 # rectype + high_ofs = int(cur_addr>>16) + b = divmod(high_ofs*2, 256) + bin[4] = b[0] # msb of high_ofs + bin[5] = b[1] # lsb of high_ofs + bin[6] = (-sum(bin)) & 0x0FF # chksum + fwrite(':' + + str(hexlify(bin.tostring()).translate(table)) + + '\n') + + while True: + # produce one record + low_addr = cur_addr & 0x0FFFF + # chain_len off by 1 + chain_len = min(7, 65535-low_addr, maxaddr-cur_addr) + + # search continuous chain + stop_addr = cur_addr + chain_len + if chain_len: + ix = bisect_right(addresses, stop_addr, + cur_ix, + min(cur_ix+chain_len+1, addr_len)) + chain_len = ix - cur_ix # real chain_len + # there could be small holes in the chain + # but we will catch them by try-except later + # so for big continuous files we will work + # at maximum possible speed + else: + chain_len = 1 # real chain_len + + bin = array('B', str('\0'*(5+(chain_len*2)))) + b = divmod(low_addr*2, 256) + bin[1] = b[0] # msb of low_addr + bin[2] = b[1] # lsb of low_addr + bin[3] = 0 # rectype + try: # if there is small holes we'll catch them + for i in range(chain_len): + bin[4+(i*2)] = self._buf[cur_addr+i] & 0x00FF + bin[4+(i*2)+1] = self._buf[cur_addr+i] >> 8 + except KeyError: + # we catch a hole so we should shrink the chain + chain_len = i + bin = bin[:5+(i*2)] + bin[0] = chain_len*2 + bin[4+(chain_len*2)] = (-sum(bin)) & 0x0FF # chksum + fwrite(':' + + str(hexlify(bin.tostring()).translate(table)) + + '\n') + + # adjust cur_addr/cur_ix + cur_ix += chain_len + if cur_ix < addr_len: + cur_addr = addresses[cur_ix] + else: + cur_addr = maxaddr + 1 + break + high_addr = int(cur_addr>>16) + if high_addr > high_ofs: + break + + # end-of-file record + fwrite(":00000001FF\n") + if fclose: + fclose() + + def get_lowest_addr(self): + return sorted(self._buf.keys())[0] + + def get_highest_addr(self): + return sorted(self._buf.keys())[-1] + + def items(self): + return self._buf.items() + + def __getitem__(self, addr): + t = type(addr) + if t in (int, long): + if addr < 0: + raise TypeError('Address should be >= 0.') + return self._buf(addr, 0xFFFF) + else: + raise TypeError('Address has unsupported type: %s' % t) + + +## +# IHexPic Errors Hierarchy: +# +# IHexPicError - basic error +# HexReaderError - general hex reader error +# AddressOverlapError - data for the same address overlap +# HexRecordError - hex record decoder base error +# RecordLengthError - record has invalid length +# RecordTypeError - record has invalid type (RECTYP) +# RecordChecksumError - record checksum mismatch +# EOFRecordError - invalid EOF record (type 01) +# ExtendedAddressRecordError - extended address record base error +# ExtendedSegmentAddressRecordError - invalid extended segment address record (type 02) +# ExtendedLinearAddressRecordError - invalid extended linear address record (type 04) +# UnsupportedRecordError - invalid/unsupported record type +# _EndOfFile - it's not real error, used internally by hex reader as signal that EOF record found + +class IHexPicError(Exception): + '''Base Exception class for IHexPic module''' + + _fmt = 'IHexPic base error' #: format string + + def __init__(self, msg=None, **kw): + """Initialize the Exception with the given message. + """ + self.msg = msg + for key, value in kw.items(): + setattr(self, key, value) + + def __str__(self): + """Return the message in this Exception.""" + if self.msg: + return self.msg + try: + return self._fmt % self.__dict__ + except (NameError, ValueError, KeyError), e: + return 'Unprintable exception %s: %s' \ + % (repr(e), str(e)) + +class _EndOfFile(IHexPicError): + """Used for internal needs only.""" + _fmt = 'EOF record reached -- signal to stop read file' + + +class HexReaderError(IHexPicError): + _fmt = 'Hex reader base error' + +class AddressOverlapError(HexReaderError): + _fmt = 'Hex file has data overlap at address 0x%(address)X on line %(line)d' + + +class HexRecordError(HexReaderError): + _fmt = 'Hex file contains invalid record at line %(line)d' + + +class RecordLengthError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid length' + +class RecordAlignmentError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid adress (not 16bit aligned)' + +class RecordTypeError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid record type' + +class RecordChecksumError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid checksum' + +class EOFRecordError(HexRecordError): + _fmt = 'File has invalid End-of-File record' + +class UnsupportedRecordError(HexRecordError): + _fmt = 'File has unsupported record type %(type)d at line %(line)d' + + +class ExtendedAddressRecordError(HexRecordError): + _fmt = 'Base class for extended address exceptions' + +class ExtendedSegmentAddressRecordError(ExtendedAddressRecordError): + _fmt = 'Invalid Extended Segment Address Record at line %(line)d' + +class ExtendedLinearAddressRecordError(ExtendedAddressRecordError): + _fmt = 'Invalid Extended Linear Address Record at line %(line)d' diff --git a/software/pic.bootloader/proto.txt b/software/pic.bootloader/proto.txt new file mode 100644 index 0000000..0e35e1e --- /dev/null +++ b/software/pic.bootloader/proto.txt @@ -0,0 +1,200 @@ +Command List: +============= + + code | command + ------+------------ + 1 | identify + 2 | boot + 3 | reset + 4 | read flash + 5 | write flash + 6 | read eeprom + 7 | write eeprom + 8 | read config + 9 | write config + + +Description: +------------ + +Every command consits of one byte command code, one byte length which counts all +bytes of the command including the command code and checksum. The length is followed +by zero or more data and a XOR checksum over all bytes sent. All data is +transferred LSB first (aka little endian). All addresses and words are 2bytes long. +Every answer to a command starts with the command code a length field which counts all +bytes of the answer, one byte return value optionally some data and a checksum +(XOR over all bytes received). +The return codes have the following meaning: + + code | Error + ------+------------- + 0 | OK + 1 | invalid command + 2 | bad checksum + 3 | not implemented + 4 | flash write error + 5 | address invalid + 6 | address prohibited + 5 | value out of bounds + +identify: +~~~~~~~~~ + command: + 1 | len=3 | + + answer: + 1 | len=19 | | version | name | devid | fs | fss | es | mess | supported | + + version: + 2bytes, protocol version + It is an error if the major version (MSB) is different (hence any + protocol update must change the major version of the bootloader). + + name: + 3bytes, a descriptive name of the device. + The downloader has to compare this name with the device name supplied + via commandline and stop in case they don't match + + devid: + 2bytes, device id of the PIC + The downlaoder may use this id to check if it talks to the right bootloader + + fs: + 2bytes, flash size + The size of the flash in code words. + + fss: + 1byte, flash segment size + The number of words of one flash segment which has to be written at once. + If less than should be updated the downloader has to perform a read + operation first. + + es: + 2bytes, eeprom size + The size of the eeprom in bytes. + + mess: + 1byte, maximum eeprom segment size + This represents the maximum number of eeprom bytes which may be written or + read at once. Unlike value it is ok to write or read less than + bytes. + + supported: + 2bytes, a bitmap showing supported commands + The commands 'identify' and 'boot' are always supported by the bootloader, + others may not (i.e.: not all PICs allow to update the configurtion words) + + bit | command + -----+---------- + 0 | reset + 1 | read flash + 2 | write flash + 3 | read eeprom + 4 | write eeprom + 5 | read config + 6 | write config + + +boot: +~~~~~ + + command: + 2 | len=3 | + + answer: + 2 | len=4 | | + + This instucts the bootloader to boot to the user application directly (no reset) + + +reset: +~~~~~~ + + command: + 3 | len=3 | + + answer: + 3 | len=4 | | + + The device performs a reboot. If the boot condition (i.e.: port pin) is not met + this instructs the device to boot to the user application. + + +read flash: +~~~~~~~~~~~ + + command: + 4 | len=5 | addr | + + answer: + 4 | len=4+2* | | data | + + The bootloader reads words from flash address and returns it as + . + + +write flash: +~~~~~~~~~~~~ + + command: + 5 | len=5+2* | addr | data | + + answer: + 5 | len=4 | | + + The bootloader writes (which has to contain exactly words) to address + inside the flash. The start address has to be aligned to boundaries. + Before writing the memory region will be erased. If there are words which shouldn't + be altered the downloader has to read these words first and reprogram the whole segment. + + +read eeprom: +~~~~~~~~~~~~ + + command: + 6 | len=5 | addr | len | + + answer: + 6 | len=4+ | | data | + + The bootloader reads bytes from eeprom at address and returns it as + . len is 1byte long. + + +write eeprom: +~~~~~~~~~~~~~ + + command: + 7 | len=4+len(data) | addr | data | + + answer: + 7 | len=4 | | + + The bootloader writes (which has to contain exactly -4 bytes) to address + inside the eeprom. len is 1byte long and the value must not exceed bytes. + + +read config: +~~~~~~~~~~~~ + + command: + 8 | len=3 | nr | + + answer: + 8 | len=6 | | word | + + The bootloader reads and returns the configuration word number . is one + byte long. + + +write config: +~~~~~~~~~~~~~ + + command: + 9 | len=5 | nr | word | + + answer: + 9 | len=4 | | + + The bootloader writes onto configuration word number . is one + byte long. -- cgit v1.2.3