Initial import of the bootloader code
authorJustin Mitchell <justin@discordia.org.uk>
Fri, 27 Sep 2013 16:13:44 +0000 (17:13 +0100)
committerJustin Mitchell <justin@discordia.org.uk>
Fri, 27 Sep 2013 16:13:44 +0000 (17:13 +0100)
29 files changed:
cli/Makefile [new file with mode: 0644]
cli/boot.c [new file with mode: 0644]
cli/devices.c [new file with mode: 0644]
cli/devices.h [new file with mode: 0644]
cli/log.c [new file with mode: 0644]
cli/log.h [new file with mode: 0644]
cli/memory.c [new file with mode: 0644]
cli/memory.h [new file with mode: 0644]
cli/protocol.c [new file with mode: 0644]
cli/protocol.h [new file with mode: 0644]
cli/serial.c [new file with mode: 0644]
cli/serial.h [new file with mode: 0644]
cli/test.c [new file with mode: 0644]
mybootload.X/Makefile [new file with mode: 0644]
mybootload.X/main.asm [new file with mode: 0644]
mybootload.X/nbproject/Makefile-default.mk [new file with mode: 0644]
mybootload.X/nbproject/Makefile-genesis.properties [new file with mode: 0644]
mybootload.X/nbproject/Makefile-impl.mk [new file with mode: 0644]
mybootload.X/nbproject/Makefile-local-default.mk [new file with mode: 0644]
mybootload.X/nbproject/Makefile-variables.mk [new file with mode: 0644]
mybootload.X/nbproject/Package-default.bash [new file with mode: 0644]
mybootload.X/nbproject/configurations.xml [new file with mode: 0644]
mybootload.X/nbproject/private/SuppressibleMessageMemo.properties [new file with mode: 0644]
mybootload.X/nbproject/private/configurations.xml [new file with mode: 0644]
mybootload.X/nbproject/private/private.properties [new file with mode: 0644]
mybootload.X/nbproject/private/private.xml [new file with mode: 0644]
mybootload.X/nbproject/project.properties [new file with mode: 0644]
mybootload.X/nbproject/project.xml [new file with mode: 0644]
mybootload.X/spbrgselect.inc [new file with mode: 0644]

diff --git a/cli/Makefile b/cli/Makefile
new file mode 100644 (file)
index 0000000..08de8b6
--- /dev/null
@@ -0,0 +1,19 @@
+CFLAGS= -g -fstack-protector-all -Wall -pedantic -std=gnu99 -fPIC -D_GNU_SOURCE
+LDFLAGS= $(CFLAGS)
+
+SRC=serial.c log.c boot.c protocol.c devices.c memory.c
+
+OBJS=$(SRC:%.c=%.o)
+
+all: boot test
+
+test: test.o
+
+boot: $(OBJS)
+
+%.o: %.c
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+clean:
+       rm -f $(OBJS) boot test
+
diff --git a/cli/boot.c b/cli/boot.c
new file mode 100644 (file)
index 0000000..564bfbf
--- /dev/null
@@ -0,0 +1,237 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "log.h"
+#include "serial.h"
+#include "protocol.h"
+#include "devices.h"
+#include "memory.h"
+
+#define BAUD_RATE 19200
+#define PORT_NAME "/dev/ttyUSB0"
+
+
+void usage(const char * name)
+{
+       loge("Usage: %s [-b baud] [-p port] [-i] [-v] {file.hex}\n", name);
+       loge("-b baud   Set baudrate (default: %d)\n", BAUD_RATE);
+       loge("-p port   Set serial port (default: %s)\n", PORT_NAME);
+       loge("-i        ID Only mode.\n");
+       loge("-v        Verify after write\n");
+}
+
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+int bitmask(int value)
+{
+       int out = 0;
+       if (value >= (1<<1)) out |= 1;
+       if (value >= (1<<2)) out |= 1<<1;
+       if (value >= (1<<3)) out |= 1<<2;
+       if (value >= (1<<4)) out |= 1<<3;
+       if (value >= (1<<5)) out |= 1<<4;
+       if (value >= (1<<6)) out |= 1<<5;
+       if (value >= (1<<7)) out |= 1<<6;
+       if (value >= (1<<8)) out |= 1<<7;
+       if (value >= (1<<9)) out |= 1<<8;
+       if (value >= (1<<10)) out |= 1<<9;
+
+       return out;
+}
+/*
+ * This routine writes a memory plan out to the device
+ */
+int update_mem(port_t * pt, const devid_t * dev, uint16_t maxmem, mem_t * ram, int verify)
+{
+       mem_t * block = ram;
+       uint8_t buff[1024];  // scratch space
+
+       for (block=ram; block != NULL; block=block->next) {
+               int bstart = block->start / 2;
+
+               /* skip config words, we cant write them anyway */
+               if (bstart >= 0x8000) {
+                       logd("UpdateMem: skip config block @ %04x", bstart);
+                       continue;
+               }
+                       
+
+               uint8_t * p = block->bytes;
+               int left = block->len;
+               uint16_t addr = bstart;
+               int rowlen = dev->rowsize * 2;
+               logd("UpdateMem: new block %d bytes @ %04x", block->len, bstart);
+
+               while (left > 0) {
+                       int off = 0;
+                       int len = rowlen;
+
+                       memset(buff, 255, sizeof(buff));
+                       if (addr == bstart) {
+                               /* first row, align the start */
+                               if (addr % dev->rowsize != 0) {
+                                       addr &= ~bitmask(dev->rowsize);
+                                       off = (bstart - addr) * 2;
+                                       len -= off;
+                                       logd("UpdateMem: realigning %04X to %04X", bstart, addr);
+                               }
+                       }
+
+                       len = MIN(len, left);
+
+                       logd("UpdateMem: Preparing %d bytes @ %04X", len, addr);
+
+                       /* partial row write, read first */
+                       if (off != 0 || len < rowlen) {
+                               logd("UpdateMem: Read %d words @ %04x", dev->rowsize, addr);
+                               if (loader_readmem(pt, addr, buff, dev->rowsize)) {
+                                       loge("UpdateMem: Aborting on failed read");
+                                       return 1;
+                               }
+                               print_memory(addr, buff, dev->rowsize);
+                       }
+
+                       /* update with new values */
+                       memcpy(&buff[off], p, len);
+
+                       /* write the row */
+                       logd("UpdateMem: Writing %d words @ %04x", dev->rowsize, addr);
+                       print_memory(addr, buff, dev->rowsize);
+                       if (loader_writemem(pt, addr, buff, dev->rowsize)) {
+                               loge("UpdateMem: Aborting on failed write");
+                               return 1;
+                       }
+
+                       if (verify) {
+                               uint8_t again[1024];
+                               sleep(1);
+                               logd("UpdateMem: Verify %d words @ %04x", dev->rowsize, addr);
+                               if (loader_readmem(pt, addr, again, dev->rowsize)) {
+                                       loge("UpdateMem: Aborting on failed read");
+                                       return 1;
+                               }
+                               print_memory(addr, again, dev->rowsize);
+                               for (int i=0; i<rowlen; i++) {
+                                       if (again[i] != buff[i]) {
+                                               loge("UpdateMem: Verify failed on block 0x%04X", addr);
+                                               return 1;
+                                       }
+                               }
+                       }
+
+                       /* shuffle along */
+                       left -= len;
+                       p += len;
+                       addr += dev->rowsize;
+               }
+       }
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int opt;
+       char * port = NULL;
+       int baud = BAUD_RATE;
+       int verify = 0;
+       int idonly = 0;
+
+       while ((opt=getopt(argc, argv, "h?b:p:ivd"))!=-1) {
+               switch (opt) {
+                       case 'b':
+                               baud = atoi(optarg);
+                               break;
+                       case 'p':
+                               if (port) free(port);
+                               port = strdup(optarg);
+                               break;
+                       case 'v':
+                               verify=1;
+                               break;
+                       case 'i':
+                               idonly=1;
+                               break;
+                       case 'd':
+                               debug++;
+                               break;
+                       case 'h':
+                       case '?':
+                       default:
+                               usage(argv[0]);
+                               return 1;
+               }
+       }
+
+       if (port == NULL) port = PORT_NAME;
+
+       if (!idonly && optind >= argc) {
+               loge("Error: missing hexfile");
+               return 1;
+       }
+
+       mem_t * ram = NULL;
+
+       if (!idonly) {
+               FILE * fd = NULL;
+               if ((fd = fopen(argv[optind], "r"))==NULL) {
+                       loge("Error opening %s: %s", argv[optind], strerror(errno));
+                       return 1;
+               }
+               ram = load_ihex(fd);
+               fclose(fd);
+
+               logd("Memory Summary :-");
+               list_mem(ram);
+       }
+
+       logd("open serial port %s at %d baud", port, baud);
+       port_t * pt = serial_open(port, baud);
+       if (pt == NULL) return 1;
+
+       uint16_t maxmem;
+       uint16_t devid;
+       if (loader_connect(pt, &maxmem, &devid)) {
+               return 1;
+       }
+
+       const devid_t * dev = devid_to_info(devid);
+
+       if (idonly) {
+               logi("Device ID: %04X", devid);
+               logi(" Free Mem: %d words available", maxmem);
+               if (dev != NULL) {
+                       logi(" Dev Name: %s", dev->name );
+                       logi("  Max Mem: %d", dev->memsize );
+               }
+
+               return 0;
+       }
+       if (dev) logd("Device Name: %s", dev->name);
+
+       /* check that the selected program will fit on this device */
+       if (makesafe_mem(&ram, maxmem)) {
+               serial_close(pt);
+               return 1;
+       }
+       logd("After re-organisation");
+       list_mem(ram);
+
+       /* now write the updated memory plan to the device */
+       if (!update_mem(pt, dev, maxmem, ram, verify)) {
+               if (verify)
+                       logi("Device Write (and Verify) Complete");
+               else
+                       logi("Device Write Complete");
+       }
+
+       /* finished */
+       serial_close(pt);
+       logd("done.");
+       return 0;
+
+}
diff --git a/cli/devices.c b/cli/devices.c
new file mode 100644 (file)
index 0000000..d3e949d
--- /dev/null
@@ -0,0 +1,41 @@
+#include <string.h>
+#include <stdint.h>
+#include "devices.h"
+
+/* list of devices we know the ID of */
+static const devid_t device_list[] = {
+     /* { devid, devmask, name, memwords, rowsize } */
+       { 0x3020, 0x3FFF, "PIC16F1454",  0x2000, 32 },
+       { 0x3024, 0x3FFF, "PIC16LF1454", 0x2000, 32 },
+       { 0x3021, 0x3FFF, "PIC16F1455",  0x2000, 32 },
+       { 0x3025, 0x3FFF, "PIC16LF1455", 0x2000, 32 },
+       { 0x3023, 0x3FFF, "PIC16F1459",  0x2000, 32 },
+       { 0x3027, 0x3FFF, "PIC16LF1459", 0x2000, 32 },
+       { 0x1480, 0x3FE0, "PIC16F1847",  0x2000, 32 },
+       { 0x14A0, 0x3FE0, "PIC16LF1847", 0x2000, 32 },
+       { 0x1B80, 0x3FE0, "PIC12F1840",  0x1000, 32 },
+       { 0x1BC0, 0x3FE0, "PIC12LF1840", 0x1000, 32 },
+       { 0, 0, NULL, 0, 0}
+};
+
+const char *devidtoname(uint16_t devid)
+{
+       const devid_t *d = device_list;
+       while (d->name != NULL) {
+               if ((devid & d->mask) == d->id) 
+                       return d->name;
+               d++;
+       }
+       return "Unknown";
+}
+
+const devid_t * devid_to_info(uint16_t devid)
+{
+       const devid_t *d = device_list;
+       while (d->name != NULL) {
+               if ((devid & d->mask) == d->id) 
+                       return d;
+               d++;
+       }
+       return NULL;
+}
diff --git a/cli/devices.h b/cli/devices.h
new file mode 100644 (file)
index 0000000..03b7272
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef DEVICE_INFO_H
+#define DEVICE_INFO_H
+
+typedef struct device_info {
+       uint16_t id;
+       uint16_t mask;
+       const char *name;
+       uint16_t memsize;
+       uint8_t rowsize;
+} devid_t;
+
+const char *devidtoname(uint16_t devid);
+const devid_t * devid_to_info(uint16_t devid);
+
+#endif
diff --git a/cli/log.c b/cli/log.c
new file mode 100644 (file)
index 0000000..ff27062
--- /dev/null
+++ b/cli/log.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "log.h"
+
+int debug = 0;
+
+void logit(int type, const char * format, ...)
+{
+       va_list va;
+       va_start(va, format);
+
+       struct timeval now;
+       gettimeofday(&now, NULL);
+
+       struct tm * now_tm = localtime(&(now.tv_sec));
+
+       if (type == LOG_INFO) {
+               vfprintf(stdout, format, va);
+               fprintf(stdout, "\n");
+       } else 
+       if (type == LOG_DEBUG) {
+               if (debug > 0) {
+                       fprintf(stderr, "%02d:%02d:%02d.%03d ", now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, (int)(now.tv_usec / 1000));
+                       vfprintf(stderr, format, va);
+                       fprintf(stderr, "\n");
+               }
+       } else {
+               vfprintf(stderr, format, va);
+               fprintf(stderr, "\n");
+       }
+
+       va_end(va);
+}
diff --git a/cli/log.h b/cli/log.h
new file mode 100644 (file)
index 0000000..c5d9f31
--- /dev/null
+++ b/cli/log.h
@@ -0,0 +1,13 @@
+/* log.c */
+
+enum log_types {
+       LOG_DEBUG, LOG_ERROR, LOG_INFO
+};
+
+#define logd(...) logit(LOG_DEBUG, __VA_ARGS__)
+#define loge(...) logit(LOG_ERROR, __VA_ARGS__)
+#define logi(...) logit(LOG_INFO, __VA_ARGS__)
+
+extern int debug;
+
+void logit(int type, const char *format, ...);
diff --git a/cli/memory.c b/cli/memory.c
new file mode 100644 (file)
index 0000000..acc16e7
--- /dev/null
@@ -0,0 +1,266 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "log.h"
+#include "memory.h"
+#include "serial.h"
+#include "devices.h"
+#include "protocol.h"
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+/* return 0 for end of file. -1 for error */
+int parse_ihex16(const char *line, uint8_t *bytes, int *addr, int *code)
+{
+       unsigned int sum, len, cksum;
+       unsigned int laddr, lcode;
+       int i;
+       const char *p;
+
+       if (line[0] != ':') return -1;
+       if (strlen(line) < 11) return -1;
+       p = &line[1];
+       if (!sscanf(p, "%02x", &len)) return -1;
+       p+=2;
+       if (strlen(line) < (11 + (len * 2))) return -1;
+       if (!sscanf(p, "%04x", &laddr)) return -1;
+       p += 4;
+       *addr = laddr; // little endian address record
+       if (!sscanf(p, "%02x", &lcode)) return -1;
+       p+=2;
+       *code = lcode & 0xFF;
+
+       /* end of file record */
+       if (*code == 1) return 0;
+
+       sum = (len & 0xFF) + ((*addr >> 8) & 0xFF) + (*addr & 0xFF) + (*code & 0xFF);
+
+       i = 0;
+       while (i < len) {
+               unsigned int byte;
+               /* files are little-endian */
+               if (!sscanf(p, "%02x", &byte)) return -1;
+               bytes[i+1] = byte & 0xFF;
+               sum += byte & 0xFF;
+               p += 2;
+
+               if (!sscanf(p, "%02x", &byte)) return -1;
+               bytes[i] = byte & 0xFF;
+               sum += byte & 0xFF;
+               i += 2;
+               p += 2;
+       }
+       if (!sscanf(p, "%02x", &cksum)) return -1;
+       if (  ((sum & 0xFF) + (cksum & 0xFF)) & 0xFF ) return -1;
+       return len;
+}
+
+static void mem_add(mem_t **head, uint32_t start, uint8_t * bytes, int len)
+{
+       /* look for an existing block this overlaps/adjoins */
+       mem_t * block = *head;
+       uint32_t end = start + len;
+
+       for(block = *head; block!=NULL; block=block->next) {
+               int bend = block->start + block->len;
+               /* before and not touching */
+               if (start < block->start && end+1 < block->start) continue;
+               /* after and not touching */
+               if (start > bend+1) continue;
+
+               /* therefore it at least touches */
+
+               /* starts before or on old block */
+               if (start <= block->start) {
+                       int pre=0, lap=0, post=0;
+                       pre = block->start - start; // bytes before the old block
+                       lap = len - pre;        // bytes overlapping, from start
+                       if (lap > block->len) {
+                               post = lap - block->len;
+                               lap = block->len;
+                       }
+                       int newsize = block->len + pre + post;
+                       uint8_t * newbytes = malloc(newsize);
+                       memcpy(&newbytes[pre], block->bytes, block->len);
+                       memcpy(newbytes, bytes, len);
+                       free(block->bytes);
+                       block->bytes = newbytes;
+                       block->len = newsize;
+                       block->start -= pre;
+               } else {
+                       /* starts part way down / at end */
+                       int pre=0, /*lap=0, */ post=0;
+                       pre = start - block->start; // gap from start
+                       //lap = MIN(block->len - pre, len);
+                       if (end > bend) post = end - bend;
+                       int newsize = block->len + post;
+                       uint8_t * newbytes = malloc(newsize);
+                       memcpy(newbytes, block->bytes, block->len);
+                       memcpy(&newbytes[pre], bytes, len);
+                       block->bytes = newbytes;
+                       block->len = newsize;
+               }
+               return;
+       }
+
+       block = calloc(1, sizeof(mem_t));
+       block->start = start;
+       block->len = len;
+       block->bytes = malloc(len);
+       memcpy(block->bytes, bytes, len);
+       block->next = *head;
+       *head = block;
+}
+
+mem_t * load_ihex(FILE *in)
+{
+       uint32_t addrh = 0;
+
+       char buff[1024];
+
+       mem_t * ram = NULL;
+
+       while (!feof(in) && fgets(buff, sizeof(buff), in)!=NULL) {
+               if (buff[0] == '#') continue;
+
+               unsigned char bytes[80];
+               int len, addr, code;
+               
+               if ((len=parse_ihex16(buff, bytes, &addr, &code)) <= 0) {
+                       if (len < 0) loge("LoadIHEX: Bad line: %s\n", buff);
+                       continue;
+               }
+
+               if (code == 4) {
+                       addrh = ((bytes[0] << 8) | bytes[1]) << 16;
+                       logd("LoadIHEX: Setting high addr 0x%02X%02X", bytes[0], bytes[1]);
+               } else
+               if (code == 1) {
+                       /* end of file marker */
+                       break;
+               } else
+               if (code == 0) {
+                       /* normal code block */
+                       uint32_t fulladdr = addrh | addr;
+                       mem_add(&ram, fulladdr, bytes, len);
+               }
+       }
+       return ram;
+}
+
+/* summary of the memory blocks in this list */
+void list_mem(const mem_t * head)
+{
+       const mem_t *p = head;
+       while (p!=NULL) {
+               logd("%6X : %d bytes", p->start, p->len);
+               p = p->next;
+       }
+}
+
+/* check that the program will fit */
+int validate_mem(mem_t * head, uint16_t maxmem)
+{
+       if (head == NULL) {
+               loge("MemValidate: No program!");
+               return 1;
+       }
+
+       mem_t * p;
+       int used = 0;
+
+       /* test that all the memory blocks will fit */
+       for (p=head; p!=NULL; p=p->next) {
+               /* just ignore config bytes, we cant write them anyway */
+               if (p->start / 2 >= 0x8000) continue;
+
+               used += p->len / 2;
+
+               if (p->start / 2 >= maxmem || (p->start+p->len)/2 >= maxmem) {
+                       loge("MemValidate: Program too large, overlaps bootloader.");
+                       return 1;
+               }
+       }
+
+       logd("MemValidate: Used %d of %d leaving %d free.", used, maxmem, maxmem-used);
+
+       return 0;
+}
+
+/* reorganise bytes to work with the boot loader */
+int makesafe_mem(mem_t **head, uint16_t maxmem)
+{
+       /* it must fit safely first */
+       if (validate_mem(*head, maxmem)) return 1;
+
+       mem_t * new = malloc(sizeof(mem_t));
+       new->start = maxmem * 2;
+       new->len = 8;
+       new->bytes = malloc(8);
+       memset(new->bytes, 255, 8);
+
+       int found = 0;
+       /* find the code that goes in words 0-3 and move it */
+       mem_t * p = NULL;
+       for (p = *head; p!=NULL; p=p->next) {
+               if (p->start >= 0 && p->start <= 7) {
+                       int pre = p->start;
+                       int lap = MIN(8-pre, p->len);
+                       memcpy(&new->bytes[pre], p->bytes, lap);
+                       p->start += lap;
+                       p->len -= lap;
+                       memmove(p->bytes, &p->bytes[lap], p->len);
+                       found++;
+               }
+       }
+
+       if (!found) {
+               loge("MakeSafeMem: Could not find start vector");
+               free(new);
+               return 1;
+       }
+
+       /* check that there is something sane in here 
+        * Warning: this is very enhanced-midrange dependant */
+       found = 0;
+       uint8_t * m = new->bytes;
+       uint16_t lath = 0;
+       for (int i=0; i<4; i++) {
+               uint16_t in = (m[0] << 8) | m[1];
+               if ((in & 0x3F80) == 0x3180) { // MOVLP
+                       lath = in & 0x007F;
+                       logd("MakeSafeMem: 0x%04X MOVLP 0x%02X", i, lath);
+               }else
+               if ((in & 0x3800) == 0x2800) { // GOTO
+                       uint16_t addr = in & 0x07FF;
+                       addr |= lath << 8;
+                       logd("MakeSafeMem: 0x%04X GOTO 0x%02X", i, addr);
+
+                       if ( addr < 4) {
+                               // an absolute goto within the reset vector
+                               // this is silly and wrong, replace with NOP
+                               logd("MakeSafeMem: Rewriting bad 'GOTO 0x%02X' to NOP", addr);
+                               m[0] = 0;
+                               m[1] = 0;
+                       } else {
+                               // there is a sane GOTO, hurrah
+                               found = 1;
+                       }
+               }
+               m += 2;
+       }
+
+       if (!found) {
+               loge("Start Vector did not contain a GOTO");
+               free(new);
+               return 1;
+       }
+
+       new->next = *head;
+       *head = new;
+
+       return 0;
+}
diff --git a/cli/memory.h b/cli/memory.h
new file mode 100644 (file)
index 0000000..444f238
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef MEMORY_BLOCK_H
+#define MEMORY_BLOCK_H
+
+typedef struct memory {
+       uint32_t        start;
+       uint16_t        len;
+       uint8_t *       bytes;
+       struct memory * next;
+} mem_t;
+
+mem_t *load_ihex(FILE *in);
+void list_mem(const mem_t * head);
+int validate_mem(mem_t * head, uint16_t maxmem);
+int makesafe_mem(mem_t **head, uint16_t maxmem);
+
+
+
+
+
+
+#endif
diff --git a/cli/protocol.c b/cli/protocol.c
new file mode 100644 (file)
index 0000000..5d6e028
--- /dev/null
@@ -0,0 +1,267 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "log.h"
+#include "serial.h"
+#include "protocol.h"
+
+static uint8_t checksum(uint8_t * buff, int len)
+{
+       int sum = 0;
+       int i;
+
+       for (i=0;i<len;i++) sum += buff[i];
+       return sum & 0xFF;
+}
+
+void print_memory(uint16_t addr, const unsigned char * buff, int words)
+{
+       int len = (words * 5) + 16;
+       char * line = malloc(len);
+       char * out = line;
+       out += snprintf(out, len-strlen(line), "Mem %04X: ", addr);
+
+       const unsigned char *p = &buff[0];
+       for (int i=0; i<words; i++) {
+               out += snprintf(out, len-strlen(line), "%02X%02X ", p[0], p[1] );
+               p+=2;
+       }
+       logd(line);
+       free(line);
+}
+
+void dumpbuff(const unsigned char * buff, int charlen)
+{
+       int len = (charlen * 3) + 16;
+        char * line = malloc(len);
+       char * out = line;
+        out += snprintf(out, len-strlen(line), "Dump: ");
+
+        const unsigned char *p = &buff[0];
+        for (int i=0; i<charlen; i++) {
+                out += snprintf(out, len-strlen(line), "%02X ", p[0] );
+                p++;
+        }
+        logd(line);
+        free(line);
+}
+
+int loader_readmem(port_t * pt, uint16_t addr, uint8_t * memory, int words)
+{
+       int len = (words * 2) + 4;
+       unsigned char * buff = malloc(len);
+
+       /* request to read memory block */
+       buff[0] = 'R';
+       buff[1] = addr >> 8;
+       buff[2] = addr & 0xFF;
+       buff[3] = checksum(buff, 3);
+
+       int ret = serial_write(pt, buff, 4);
+       if (ret <= 0) return 1;
+
+       bzero(buff, len);
+
+       /* read the response */
+       if (serial_read(pt, buff, 1)<=0) return 1;
+
+       if (buff[0] == 'E') {
+               loge("ReadMem %04X: Loader gave error", addr);
+               return 2;
+       }
+
+       if (buff[0] != 'R') {
+               loge("ReadMem %04X: Unknown response to read 0x%02X '%c'", addr, buff[0], buff[0]);
+               return 3;
+       }
+
+       /* now read the address, and check it matches */
+       ret = serial_read(pt, &buff[1], len-1);
+       if (ret < 1) {
+               loge("ReadMem %04X: Error read response", addr);
+               return 4;
+       }
+       if (ret < len-1) {
+               loge("ReadMem %04X: Short read %d of %d", addr, ret, len-1);
+               return 5;
+       }
+
+       int sum = checksum(buff, len-1);
+       if ((sum & 0xFF) != buff[len-1]) {
+               loge("ReadMem %04X: Bad checksum. %02X != %02X", addr, sum & 0xFF, buff[len-1]);
+               return 6;
+       }
+
+       uint16_t realaddr = (buff[1]<<8) | buff[2];
+       if (realaddr != addr) {
+               loge("ReadMem %04X: Actual Address %04X", addr, realaddr);
+               return 7;
+       }
+       logd("ReadMem %04X: Read Successful", realaddr);
+
+       memcpy(memory, &buff[3], (words * 2));
+       free(buff);
+
+       return 0;
+}
+
+
+int loader_writemem(port_t * pt, uint16_t addr, uint8_t * memory, int words)
+{
+       int len = (words * 2) + 4;
+       uint8_t * buff = malloc((words * 2) + 4);
+
+       /* request to read memory block */
+       buff[0] = 'W';
+       buff[1] = addr >> 8;
+       buff[2] = addr & 0xFF;
+
+       unsigned char * p = memory;
+       unsigned char * q = &buff[3];
+       for (int i=0; i<words; i++) {
+               *q++ = *p++;
+               *q++ = *p++;
+       }
+       *q = checksum(buff, len-1) & 0xFF;
+
+       logd("WriteMem %04X: Sending Write request", addr);
+       int ret = serial_write(pt, buff, len);
+       if (ret <= 0) { free(buff); return 1; }
+
+       logd("WriteMem %04X: Awaiting Write confirmation", addr);
+       /* read the response */
+       if (serial_read(pt, buff, 1)<=0) { free(buff); return 1; }
+
+       if (buff[0] == 'E') {
+               loge("WriteMem %04X: Bootloader gave an error", addr);
+               free(buff);
+               return 2;
+       }
+
+       if (buff[0] != 'W') {
+               loge("WriteMem %04X: unknown reponse '%c'", addr, buff[0]);
+               free(buff);
+               return 3;
+       }
+
+       /* now read the address, and check it matches */
+       ret = serial_read(pt, &buff[1], 3);
+       if (ret < 3) {
+               loge("WriteMem %04X: Error reading rest of response %d of %d", addr, ret, 3);
+               free(buff);
+               return 4;
+       }
+
+       uint16_t realaddr = (buff[1]<<8) | buff[2];
+       if (realaddr != addr) {
+               loge("WriteMem %04X: Actual location %04X", addr, realaddr);
+               free(buff);
+               return 5;
+       }
+       int sum = checksum(buff, 3);
+
+       if ((sum & 0xFF) != buff[3]) {
+               loge("WriteMem %04X: Bad checksum on confirmation. %02X != %02X", addr, sum & 0xFF, buff[3]);
+               dumpbuff(buff, 4);
+               free(buff);
+               return 8;
+       }
+
+       logd("WriteMem %04X: Write confirmed.", realaddr);
+       free(buff);
+
+       return 0;
+}
+
+/*
+ * Connect to the bootloader
+ * read the start of bootloader address
+ */
+int loader_connect(port_t * pt, uint16_t *maxmem, uint16_t *devid)
+{
+       if (pt == NULL) return 1;
+
+       logd("Connect: Assert break and wait for acknowledgement");
+       serial_break(pt, 1);
+
+       unsigned char buff[10];
+       int bootload = 0;
+       int ret;
+
+       logi("Please reset the device to enter bootloader mode");
+
+       while ((ret=serial_read(pt, buff, 1))> 0) {
+               if (buff[0] == 06) {
+                       break;
+               } else {
+                       logd("Connect: Want ESC (0x06) got 0x%02X ret=%d", buff[0], ret);
+                       usleep(100000);
+               }
+       }
+
+       if (ret <= 0) {
+               if (ret == 0)
+                       loge("Connect: Serial port closed");
+               else
+                       loge("Connect: read error: %s", strerror(errno));
+               return 1;
+       }
+
+       /* Next we should see 'B' 'L' */
+       while ((ret=serial_read(pt, &buff[1], 2))> 0) {
+               if (buff[1] == 'B' && buff[2] == 'L') {
+                       bootload = 1;
+                       break;
+               } else {
+                       logd("Connect: Want 'BL' got '%c%c' ret=%d", buff[1], buff[2], ret);
+               }
+               bzero(buff,3);
+       }
+
+       if (ret <= 0) {
+               if (ret == 0)
+                       loge("Connect: Serial port closed");
+               else
+                       loge("Connect: read error: %s", strerror(errno));
+               return 1;
+       }
+
+       /* turn break off now we are in bootloader mode */
+       serial_break(pt, 0);
+
+       if (!bootload) {
+               serial_close(pt);
+               loge("Connect: Could not find bootloader");
+               return 1;
+       }
+
+       logd("Connect: Release break. Read memory size.");
+
+       /* now read the bootloaders location, and thus mem size */
+       ret=serial_read(pt, &buff[3], 5);
+
+       if (ret < 3) {
+               if (ret == 0)
+                       loge("Connect: Serial port closed");
+               else
+                       loge("Connect: read error: %s", strerror(errno));
+               return 1;
+       }
+
+       if (buff[7] != (checksum(buff,7) & 0xFF)) {
+               loge("Connect: Bad checksum");
+               return 1;
+       }
+
+       *devid = (buff[3] << 8) | buff[4];
+       logd("Connect: Device ID: 0x%04X", *devid);
+
+       *maxmem = (buff[5] << 8) | buff[6];
+       logd("Connect: Memory Size: 0x%04X", *maxmem);
+
+       return 0;
+}
diff --git a/cli/protocol.h b/cli/protocol.h
new file mode 100644 (file)
index 0000000..4674ce0
--- /dev/null
@@ -0,0 +1,6 @@
+/* proto.c */
+void print_memory(uint16_t addr, const unsigned char *buff, int words);
+void dumpbuff(const unsigned char *buff, int charlen);
+int loader_readmem(port_t *pt, uint16_t addr, uint8_t *memory, int words);
+int loader_writemem(port_t *pt, uint16_t addr, uint8_t *memory, int words);
+int loader_connect(port_t *pt, uint16_t *maxmem, uint16_t *devid);
diff --git a/cli/serial.c b/cli/serial.c
new file mode 100644 (file)
index 0000000..6fb682a
--- /dev/null
@@ -0,0 +1,117 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "log.h"
+#include "serial.h"
+
+struct serial_port {
+       int fd;
+};
+
+static speed_t baud(int speed)
+{
+       if (speed == 230400) return B230400; else
+       if (speed == 115200) return B115200; else
+       if (speed == 57600) return B57600; else
+       if (speed == 38400) return B38400; else
+       if (speed == 19200) return B19200; else
+       if (speed == 9600) return B9600; else
+       if (speed == 4800) return B4800; else
+       if (speed == 2400) return B2400; else
+       if (speed == 1200) return B1200; else {
+               loge("Error setting baud rate: %d not recognised.", speed);
+               return B0;
+       }
+
+}
+
+port_t * serial_open(const char *name, int speed)
+{
+       port_t *pt = NULL;
+       int fd;
+
+       if ((fd = open(name, O_RDWR | O_NOCTTY))<0) {
+               loge("Error: opening %s: %s", name, strerror(errno));
+               return NULL;
+       }
+
+       struct termios adtio;
+       bzero(&adtio, sizeof(adtio));
+
+       tcgetattr(fd, &adtio);
+       adtio.c_cflag = CS8 | CLOCAL | CREAD;
+       adtio.c_iflag = IGNPAR | IGNBRK;
+       adtio.c_oflag = 0;
+       adtio.c_lflag = 0; // non-canon, no echo
+
+       cfmakeraw(&adtio);
+
+       adtio.c_cc[VTIME] = 0;
+       adtio.c_cc[VMIN] = 1;
+
+       cfsetispeed(&adtio, baud(speed));
+       cfsetospeed(&adtio, baud(speed));
+
+       tcsetattr(fd, TCSANOW, &adtio);
+
+       pt = malloc(sizeof(port_t));
+       pt->fd = fd;
+
+       return pt;
+
+}
+
+void serial_close(port_t * pt)
+{
+       if (pt == NULL) return;
+       if (pt->fd < 0) return;
+
+       close(pt->fd);
+       pt->fd = -1;
+
+       return;
+}
+
+int serial_read(port_t * pt, unsigned char * buff, size_t len)
+{
+       if (pt == NULL || pt->fd < 0) return -1;
+
+       int ret = 0;
+       int count = 0;
+       unsigned char * p = buff;
+       while (count < len) {
+               ret = read(pt->fd, p, len-count);
+               if (ret <= 0) return ret;
+               p += ret;
+               count += ret;
+       }
+       return count;
+}
+
+int serial_write(port_t * pt, unsigned char * buff, size_t len)
+{
+       if (pt == NULL || pt->fd < 0) return -1;
+
+       return write(pt->fd, buff, len);
+}
+
+int serial_break(port_t * pt, int set)
+{
+       if (pt == NULL || pt->fd < 0) return -1;
+
+       if (set)
+               ioctl(pt->fd, TIOCSBRK, 0);
+       else
+               ioctl(pt->fd, TIOCCBRK, 0);
+
+       return 0;
+}
+
diff --git a/cli/serial.h b/cli/serial.h
new file mode 100644 (file)
index 0000000..1baf110
--- /dev/null
@@ -0,0 +1,14 @@
+/* Serial port controls */
+
+struct serial_port;
+typedef struct serial_port port_t;
+
+#define ACK 0x06
+#define NACK 0x15
+
+/* serial.c */
+port_t *serial_open(const char *name, int speed);
+void serial_close(port_t *pt);
+int serial_read(port_t *pt, unsigned char *buff, size_t len);
+int serial_write(port_t *pt, unsigned char *buff, size_t len);
+int serial_break(port_t *pt, int set);
diff --git a/cli/test.c b/cli/test.c
new file mode 100644 (file)
index 0000000..d7d72ea
--- /dev/null
@@ -0,0 +1,75 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+/* return 0 for end of file. -1 for error */
+int parse_ihex16(const char *line, uint8_t *bytes, int *addr, int *code)
+{
+       unsigned int sum, len, cksum;
+       unsigned int laddr, lcode;
+       int i;
+       const char *p;
+
+       if (line[0] != ':') return -1;
+       if (strlen(line) < 11) return -1;
+       p = &line[1];
+       if (!sscanf(p, "%02x", &len)) return -1;
+       p+=2;
+       if (strlen(line) < (11 + (len * 2))) return -1;
+       if (!sscanf(p, "%04x", &laddr)) return -1;
+       p += 4;
+       *addr = laddr; // little endian address record
+       if (!sscanf(p, "%02x", &lcode)) return -1;
+       p+=2;
+       *code = lcode & 0xFF;
+
+       /* end of file record */
+       if (*code == 1) return 0;
+
+       sum = (len & 0xFF) + ((*addr >> 8) & 0xFF) + (*addr & 0xFF) + (*code & 0xFF);
+
+       i = 0;
+       while (i < len) {
+               unsigned int byte;
+               if (!sscanf(p, "%02x", &byte)) return -1;
+               bytes[i++] = byte & 0xFF;
+               sum += byte & 0xFF;
+               p += 2;
+       }
+       if (!sscanf(p, "%02x", &cksum)) return -1;
+       if (  ((sum & 0xFF) + (cksum & 0xFF)) & 0xFF ) return -1;
+       return len;
+}      
+
+int main(int argc, char **argv)
+{
+       FILE *in;
+
+       if (argc < 2) return 1;
+
+       if ((in=fopen(argv[1], "r"))==NULL) {
+               fprintf(stderr, "Failed opening %s: %s\n", argv[1], strerror(errno));
+               return 1;
+       }
+
+       char buff[1024];
+
+       while (!feof(in) && fgets(buff, sizeof(buff), in)!=NULL) {
+               if (buff[0] == '#') continue;
+
+               unsigned char bytes[80];
+               int len, addr, code;
+               
+               if ((len=parse_ihex16(buff, bytes, &addr, &code)) <= 0) {
+                       if (len < 0) fprintf(stderr, "Bad line: %s\n", buff);
+                       continue;
+               }
+
+               printf("Addr: %04X +%2d code=%d :", addr, len, code);
+               for (int i=0; i<len; i++) printf(" %02X", bytes[i]);
+               printf("\n");
+       }
+
+       fclose(in);
+}
diff --git a/mybootload.X/Makefile b/mybootload.X/Makefile
new file mode 100644 (file)
index 0000000..05a3fb1
--- /dev/null
@@ -0,0 +1,108 @@
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:               called before 'help' target
+#     .help-post:              called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+#  Available make variables:
+#
+#     CND_BASEDIR                base directory for relative paths
+#     CND_DISTDIR                default top distribution directory (build artifacts)
+#     CND_BUILDDIR               default top build directory (object files, ...)
+#     CONF                       name of current configuration
+#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
+#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
+#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
+#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
+#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
+#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
+#
+# NOCDDL
+
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post: .build-impl
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post: .clean-impl
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post: .clobber-impl
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post: .all-impl
+# Add your post 'all' code here...
+
+
+# help
+help: .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post: .help-impl
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
+
+# include project make variables
+include nbproject/Makefile-variables.mk
diff --git a/mybootload.X/main.asm b/mybootload.X/main.asm
new file mode 100644 (file)
index 0000000..6bfe74e
--- /dev/null
@@ -0,0 +1,382 @@
+    radix dec
+
+    errorlevel -302
+
+#include "p16f1455.inc"
+
+; CONFIG1
+ __config _CONFIG1, 0xFCC
+;; __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_SWDTEN & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
+; CONFIG2
+ __config _CONFIG2, 0x16CF
+; __CONFIG _CONFIG2, _WRT_OFF & _CPUDIV_NOCLKDIV & _USBLSCLK_48MHz & _PLLMULT_3x & _PLLEN_DISABLED & _STVREN_ON & _BORV_LO & _LPBOR_ON & _LVP_OFF
+
+
+#define max_flash 0x2000
+#define row_size  32
+
+; 16F1455 errata says self-program only works <= 4MHz clock
+xtal    EQU 4000000
+baud    EQU 19200
+
+#include "spbrgselect.inc"
+
+; This is the smallest multiple of 32 that the bootloader
+; code fits into (minus the 4 for the remapped section)
+loader_size     set 224
+
+; fit remap section in end of previous page
+; so we dont need to rewrite the bootloader page
+remap_addr      set max_flash - loader_size - 4
+
+; Variables
+    cblock 0x20
+        buffer:80
+    endc
+
+    ; common ram section
+    cblock 0x70
+        cmd
+        crc
+        i
+        tmp
+    endc
+
+; ############ RESET ############
+; This is the normal reset vector
+; when a program is loaded, its version of these 4 will be moved
+; and replaced with our code to jump to the bootloader
+
+Start CODE 0x0000
+    MOVLP   high(StartBoot)
+    GOTO    StartBoot
+    NOP
+    NOP
+; after this is the normal reset vector and rest of the loaded program
+
+
+; simple test program
+Main
+    banksel ANSELA
+    CLRF    ANSELA
+    banksel TRISA
+    CLRF    TRISA
+    CLRF    TRISC
+    banksel PORTA
+    BSF     PORTA,5     ; green on
+    BCF     PORTA,4     ; red off
+    SLEEP
+
+
+; At the far end of memory...
+; this is the relocated boot sector
+    ORG remap_addr
+AppVector
+;    NOP
+    MOVLP   high(Main)
+    GOTO    Main    ; pretend program loaded
+    NOP
+    NOP
+
+; immediately followed by out bootloader
+    ORG     remap_addr+4
+StartBoot
+
+    ; First configure the pin
+    ; 16f1455  RX=RC5 TX=RC4
+;    banksel TRISC
+;    BSF     TRISC,5   ; RC5 as input
+;    BCF     TRISC,4   ; RC4 as output
+    banksel PORTC
+    CLRF    PORTC
+
+    BTFSC   PORTC,5   ; RC5 is Clear (break state) carry on
+    BRA     AppVector   ; Was not clear, launch app instead
+
+    ; Lets start the bootloader properly
+    banksel OSCCON
+    MOVLW   b'00110100'
+    MOVWF   OSCCON      ; 4Mhz clock mode
+    BTFSS   OSCSTAT,HFIOFR
+    BRA     $-1         ; wait until oscillator is ready
+    MOVLW   b'00011001' ; Activate watchdog, 4 seconds
+    MOVWF   WDTCON
+
+SetBaud
+    ; Set the baud rate and enable uart
+    banksel TXSTA
+    MOVLW   b'00100100' ; TXEN=1 SYNC=0 BRGH=1
+    MOVWF   TXSTA
+    banksel SPBRGL
+    MOVLW   spbrg_value
+    MOVWF   SPBRGL
+    CLRF    SPBRGH
+    banksel RCSTA
+    MOVLW   b'10010000' ; SPEN CREN
+    MOVWF   RCSTA
+
+; debug lights
+; debug RA5 green, RA4 red
+    banksel ANSELA
+    CLRF    ANSELA
+    banksel TRISA
+    CLRF    TRISA
+    banksel PORTA
+    BCF     PORTA,5     ; green off
+    BSF     PORTA,4     ; red on
+    
+    ; Send the 'we heard you' ACK symbol
+    CLRF    crc
+    MOVLW   0x06
+    CALL    SendByte
+    MOVLW   'B'
+    CALL    SendByte
+    MOVLW   'L'
+    CALL    SendByte
+    
+    ; Wait for PC to drop the break condition
+    banksel PORTC
+    BTFSS   PORTC,5
+    BRA     $-1
+
+    ; Transmit device ID
+    banksel PMADRL
+    MOVLW   0x06  ; 0x8006 Device ID
+    MOVWF   PMADRL
+    CLRF    PMADRH
+    BSF     PMCON1,CFGS
+    BSF     PMCON1,RD
+    NOP
+    NOP
+    MOVF    PMDATH,W
+    CALL    SendByte
+    banksel PMDATL
+    MOVF    PMDATL,W
+    CALL    SendByte
+
+    ; Transmit location of bootloader, and thus top of flash
+    MOVLW   high(remap_addr)
+    CALL    SendByte
+
+    MOVLW   low(remap_addr)
+    CALL    SendByte
+
+    ; transmit csum to complete the welcome message
+    CALL    SendCRC
+
+    ; Wait here for instructions
+CmdLoop
+    CLRWDT
+    CLRF    crc
+    CALL    ReadByte
+    MOVWF   cmd         ; keep it to re-examine
+
+    ; command 'R' read a row (32 words)
+    SUBLW   'R'
+    SKPNZ
+    BRA     ReadLine
+
+    ; command 'W' write a row (32 words)
+    MOVFW   cmd
+    SUBLW   'W'
+    SKPNZ
+    BRA     WriteLine
+
+    ; command 'B' reboot
+    MOVFW   cmd
+    SUBLW   'B'
+    SKPNZ
+    BRA     DoBoot
+
+    BRA     CmdLoop
+
+ReadByte ; put it in W
+    banksel PIR1
+    BTFSS   PIR1, RCIF
+    BRA     $-1
+    banksel RCREG
+    MOVF    RCREG,W
+    ADDWF   crc,F
+    RETURN
+
+ReadCRC
+    banksel PIR1
+    BTFSS   PIR1, RCIF
+    BRA     $-1
+    banksel RCREG
+    MOVF    RCREG,W
+    RETURN
+
+
+SendCRC  ; copy the crc in as the thing to send
+    MOVF    crc,W
+SendByte ; that is in W
+    ADDWF   crc,F
+    banksel PIR1
+    BTFSS   PIR1, TXIF
+    BRA     $-1
+    banksel TXREG
+    MOVWF   TXREG
+    RETURN
+
+SendError ; Say there was an error (must be an in subr)
+    MOVLW   'E'
+    CALL    SendByte
+    BRA     CmdLoop
+
+ReadLine ; read a row
+    CALL    ReadByte
+    banksel PMADRH
+    MOVWF   PMADRH  ; store the high byte
+    CALL    ReadByte
+    banksel PMADRL
+    ANDLW   0xE0    ; align to 32 word
+    MOVWF   PMADRL  ; store the low byte
+    CALL    ReadCRC ; read the checksum
+    SUBWF   crc,W
+    SKPZ             ; if crc-checksum !=0 goto Error
+    BRA     SendError
+; now lets send a record back to the host
+    MOVLW   row_size    ; 32 words
+    MOVWF   i
+    CLRF    crc         ; reset crc for outgoing message
+    MOVLW   'R'         ; warn that we are writing
+    CALL    SendByte
+    banksel PMADRH
+    MOVF    PMADRH,W    ; say what the start address is
+    ANDLW   0x7F        ; top bit is always set, duh
+    CALL    SendByte
+    banksel PMADRL
+    MOVF    PMADRL,W
+    CALL    SendByte
+
+ReadLoop
+    banksel PMCON1
+    BCF     PMCON1,CFGS ; read program not config
+    BSF     PMCON1,RD
+    NOP
+    NOP
+    MOVF    PMDATH,W    ; send high byte
+    CALL    SendByte
+    banksel PMDATL
+    MOVF    PMDATL,W    ; send low byte
+    CALL    SendByte
+    banksel PMADRL
+    ; Assumption: this is 32 word aligned, will never cross boundary
+    INCF    PMADRL,F    ; increment address
+    DECFSZ  i,F         ; i--
+    BRA     ReadLoop    ; go around again
+    ; finished sending program words
+    CALL    SendCRC    ; send the crc
+    ; done, go back for next command
+    BRA     CmdLoop
+
+WriteLine ; write a row
+    CALL    ReadByte
+    banksel PMADRH
+    MOVWF   PMADRH  ; store the high byte
+    CALL    ReadByte
+    banksel PMADRL
+    ANDLW   0xE0    ; align to 32 word
+    MOVWF   PMADRL  ; store the low byte
+    ; lets just store the bytes in buff until we are sure the checksum is good
+    banksel FSR0L
+    MOVLW   high(buffer)
+    MOVWF   FSR0H
+    MOVLW   low(buffer)
+    MOVWF   FSR0L
+    ; read row_size * 2 bytes
+    MOVLW   row_size * 2
+    MOVWF   i
+WriteLineRead
+    CALL    ReadByte
+    MOVWI   FSR0++
+    DECFSZ  i,F
+    BRA     WriteLineRead
+    ; now read the crc and test
+    CALL    ReadCRC ; read the checksum
+    SUBWF   crc,W
+    SKPZ             ; if crc-checksum !=0 goto Error
+    BRA     SendError
+    ; everything is fine, commit to memory
+    ; first we have to erase the row
+    banksel PMCON1
+    BCF     PMCON1,CFGS ; program
+    BSF     PMCON1,FREE ; erase
+    BSF     PMCON1,WREN ; enable writes
+    MOVLW   0x55
+    MOVWF   PMCON2
+    MOVLW   0xAA
+    MOVWF   PMCON2
+    BSF     PMCON1,WR   ; commit
+    NOP
+    NOP     ; CPU goes to sleep for 2mS
+    BCF     PMCON1,WREN ; disable writes
+    ; now move the FSR back to the start
+    banksel FSR0L
+    MOVLW   high(buffer)
+    MOVWF   FSR0H
+    MOVLW   low(buffer)
+    MOVWF   FSR0L
+    MOVLW   row_size    ; need to do this once per word
+    MOVWF   i
+
+    ; setup for writing to latches
+    banksel PMCON1
+    BSF     PMCON1,WREN ; enable writes
+    BCF     PMCON1,CFGS ; program
+    BCF     PMCON1,FREE ; write not erase this time
+    BSF     PMCON1,LWLO ; into the latches
+
+LatchWord
+    MOVIW   FSR0++
+    MOVWF   PMDATH
+    MOVIW   FSR0++
+    MOVWF   PMDATL
+    DECFSZ  i,F
+    BRA     LatchWrite
+    BRA     CommitWrite
+    ; just a latching write
+LatchWrite
+    MOVLW   0x55
+    MOVWF   PMCON2
+    MOVLW   0xAA
+    MOVWF   PMCON2
+    BSF     PMCON1,WR   ; commit
+    NOP
+    NOP
+    INCF    PMADRL,F    ; move along
+    BRA     LatchWord
+CommitWrite
+    BCF     PMCON1,LWLO ; real thing this time
+    MOVLW   0x55
+    MOVWF   PMCON2
+    MOVLW   0xAA
+    MOVWF   PMCON2
+    BSF     PMCON1,WR   ; commit
+    NOP
+    NOP             ; cpu stalls for 2mS
+    ; and we are finished
+    BCF     PMCON1,WREN ; disable writes
+    ; tell the other end we finished
+    CLRF    crc         ; reset crc for outgoing message
+    MOVLW   'W'         ; confirm the write command
+    CALL    SendByte
+    banksel PMADRH
+    MOVF    PMADRH,W    ; say what the start address is
+    ANDLW   0x7F        ; top bit is always set, duh
+    CALL    SendByte
+    banksel PMADRL
+    MOVF    PMADRL,W
+    ANDLW   0xE0        ; align to 32 word
+    CALL    SendByte
+    CALL    SendCRC
+    ; finished writing
+    BRA     CmdLoop
+
+DoBoot
+    RESET
+
+EndBoot
+    END
+
diff --git a/mybootload.X/nbproject/Makefile-default.mk b/mybootload.X/nbproject/Makefile-default.mk
new file mode 100644 (file)
index 0000000..75523f8
--- /dev/null
@@ -0,0 +1,132 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a -pre and a -post target defined where you can add customized code.
+#
+# This makefile implements configuration specific macros and targets.
+
+
+# Include project Makefile
+ifeq "${IGNORE_LOCAL}" "TRUE"
+# do not include local makefile. User is passing all local related variables already
+else
+include Makefile
+# Include makefile containing local settings
+ifeq "$(wildcard nbproject/Makefile-local-default.mk)" "nbproject/Makefile-local-default.mk"
+include nbproject/Makefile-local-default.mk
+endif
+endif
+
+# Environment
+MKDIR=mkdir -p
+RM=rm -f 
+MV=mv 
+CP=cp 
+
+# Macros
+CND_CONF=default
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+IMAGE_TYPE=debug
+OUTPUT_SUFFIX=cof
+DEBUGGABLE_SUFFIX=cof
+FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+else
+IMAGE_TYPE=production
+OUTPUT_SUFFIX=hex
+DEBUGGABLE_SUFFIX=cof
+FINAL_IMAGE=dist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+endif
+
+# Object Directory
+OBJECTDIR=build/${CND_CONF}/${IMAGE_TYPE}
+
+# Distribution Directory
+DISTDIR=dist/${CND_CONF}/${IMAGE_TYPE}
+
+# Source Files Quoted if spaced
+SOURCEFILES_QUOTED_IF_SPACED=main.asm
+
+# Object Files Quoted if spaced
+OBJECTFILES_QUOTED_IF_SPACED=${OBJECTDIR}/main.o
+POSSIBLE_DEPFILES=${OBJECTDIR}/main.o.d
+
+# Object Files
+OBJECTFILES=${OBJECTDIR}/main.o
+
+# Source Files
+SOURCEFILES=main.asm
+
+
+CFLAGS=
+ASFLAGS=
+LDLIBSOPTIONS=
+
+############# Tool locations ##########################################
+# If you copy a project from one host to another, the path where the  #
+# compiler is installed may be different.                             #
+# If you open this project with MPLAB X in the new host, this         #
+# makefile will be regenerated and the paths will be corrected.       #
+#######################################################################
+# fixDeps replaces a bunch of sed/cat/printf statements that slow down the build
+FIXDEPS=fixDeps
+
+.build-conf:  ${BUILD_SUBPROJECTS}
+       ${MAKE}  -f nbproject/Makefile-default.mk dist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+
+MP_PROCESSOR_OPTION=16f1455
+MP_LINKER_DEBUG_OPTION=
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: assemble
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+${OBJECTDIR}/main.o: main.asm  nbproject/Makefile-${CND_CONF}.mk
+       @${MKDIR} ${OBJECTDIR} 
+       @${RM} ${OBJECTDIR}/main.o.d 
+       @${RM} ${OBJECTDIR}/main.o 
+       @${FIXDEPS} dummy.d -e "${OBJECTDIR}/main.err" $(SILENT) -c ${MP_AS} $(MP_EXTRA_AS_PRE) -d__DEBUG -d__MPLAB_DEBUGGER_ICD3=1 -q -p$(MP_PROCESSOR_OPTION) -u  -l\\\"${OBJECTDIR}/main.lst\\\" -e\\\"${OBJECTDIR}/main.err\\\" $(ASM_OPTIONS)   -o\\\"${OBJECTDIR}/main.o\\\" \\\"main.asm\\\" 
+       @${DEP_GEN} -d "${OBJECTDIR}/main.o"
+       @${FIXDEPS} "${OBJECTDIR}/main.o.d" $(SILENT) -rsi ${MP_AS_DIR} -c18 
+       
+else
+${OBJECTDIR}/main.o: main.asm  nbproject/Makefile-${CND_CONF}.mk
+       @${MKDIR} ${OBJECTDIR} 
+       @${RM} ${OBJECTDIR}/main.o.d 
+       @${RM} ${OBJECTDIR}/main.o 
+       @${FIXDEPS} dummy.d -e "${OBJECTDIR}/main.err" $(SILENT) -c ${MP_AS} $(MP_EXTRA_AS_PRE) -q -p$(MP_PROCESSOR_OPTION) -u  -l\\\"${OBJECTDIR}/main.lst\\\" -e\\\"${OBJECTDIR}/main.err\\\" $(ASM_OPTIONS)   -o\\\"${OBJECTDIR}/main.o\\\" \\\"main.asm\\\" 
+       @${DEP_GEN} -d "${OBJECTDIR}/main.o"
+       @${FIXDEPS} "${OBJECTDIR}/main.o.d" $(SILENT) -rsi ${MP_AS_DIR} -c18 
+       
+endif
+
+# ------------------------------------------------------------------------------------
+# Rules for buildStep: link
+ifeq ($(TYPE_IMAGE), DEBUG_RUN)
+dist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk    
+       @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
+       ${MP_LD} $(MP_EXTRA_LD_PRE)   -p$(MP_PROCESSOR_OPTION)  -w -x -u_DEBUG -z__ICD2RAM=1 -m"${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map"   -z__MPLAB_BUILD=1  -z__MPLAB_DEBUG=1 -z__MPLAB_DEBUGGER_ICD3=1 $(MP_LINKER_DEBUG_OPTION) -odist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}     
+else
+dist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}: ${OBJECTFILES}  nbproject/Makefile-${CND_CONF}.mk   
+       @${MKDIR} dist/${CND_CONF}/${IMAGE_TYPE} 
+       ${MP_LD} $(MP_EXTRA_LD_PRE)   -p$(MP_PROCESSOR_OPTION)  -w  -m"${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map"   -z__MPLAB_BUILD=1  -odist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${DEBUGGABLE_SUFFIX}  ${OBJECTFILES_QUOTED_IF_SPACED}     
+endif
+
+
+# Subprojects
+.build-subprojects:
+
+
+# Subprojects
+.clean-subprojects:
+
+# Clean Targets
+.clean-conf: ${CLEAN_SUBPROJECTS}
+       ${RM} -r build/default
+       ${RM} -r dist/default
+
+# Enable dependency checking
+.dep.inc: .depcheck-impl
+
+DEPFILES=$(shell "${PATH_TO_IDE_BIN}"mplabwildcard ${POSSIBLE_DEPFILES})
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff --git a/mybootload.X/nbproject/Makefile-genesis.properties b/mybootload.X/nbproject/Makefile-genesis.properties
new file mode 100644 (file)
index 0000000..705c4cd
--- /dev/null
@@ -0,0 +1,8 @@
+#
+#Fri Sep 27 11:45:23 BST 2013
+default.languagetoolchain.dir=/opt/microchip/mplabx/mpasmx
+com-microchip-mplab-nbide-embedded-makeproject-MakeProject.md5=0d2b1469ad71adb787c711a416386331
+default.languagetoolchain.version=5.52
+host.platform=linux
+conf.ids=default
+default.com-microchip-mplab-nbide-toolchainMPASMWIN-MPASMWINLanguageToolchain.md5=dc1e238caba4e98e3e2f2da7006384df
diff --git a/mybootload.X/nbproject/Makefile-impl.mk b/mybootload.X/nbproject/Makefile-impl.mk
new file mode 100644 (file)
index 0000000..7482b42
--- /dev/null
@@ -0,0 +1,69 @@
+#
+# Generated Makefile - do not edit!
+#
+# Edit the Makefile in the project folder instead (../Makefile). Each target
+# has a pre- and a post- target defined where you can add customization code.
+#
+# This makefile implements macros and targets common to all configurations.
+#
+# NOCDDL
+
+
+# Building and Cleaning subprojects are done by default, but can be controlled with the SUB
+# macro. If SUB=no, subprojects will not be built or cleaned. The following macro
+# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf
+# and .clean-reqprojects-conf unless SUB has the value 'no'
+SUB_no=NO
+SUBPROJECTS=${SUB_${SUB}}
+BUILD_SUBPROJECTS_=.build-subprojects
+BUILD_SUBPROJECTS_NO=
+BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}}
+CLEAN_SUBPROJECTS_=.clean-subprojects
+CLEAN_SUBPROJECTS_NO=
+CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}}
+
+
+# Project Name
+PROJECTNAME=mybootload.X
+
+# Active Configuration
+DEFAULTCONF=default
+CONF=${DEFAULTCONF}
+
+# All Configurations
+ALLCONFS=default 
+
+
+# build
+.build-impl: .build-pre
+       ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-conf
+
+
+# clean
+.clean-impl: .clean-pre
+       ${MAKE} -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .clean-conf
+
+# clobber
+.clobber-impl: .clobber-pre .depcheck-impl
+           ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default clean
+
+
+
+# all
+.all-impl: .all-pre .depcheck-impl
+           ${MAKE} SUBPROJECTS=${SUBPROJECTS} CONF=default build
+
+
+
+# dependency checking support
+.depcheck-impl:
+#      @echo "# This code depends on make tool being used" >.dep.inc
+#      @if [ -n "${MAKE_VERSION}" ]; then \
+#          echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
+#          echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
+#          echo "include \$${DEPFILES}" >>.dep.inc; \
+#          echo "endif" >>.dep.inc; \
+#      else \
+#          echo ".KEEP_STATE:" >>.dep.inc; \
+#          echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
+#      fi
diff --git a/mybootload.X/nbproject/Makefile-local-default.mk b/mybootload.X/nbproject/Makefile-local-default.mk
new file mode 100644 (file)
index 0000000..ee6b645
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# Generated Makefile - do not edit!
+#
+#
+# This file contains information about the location of compilers and other tools.
+# If you commmit this file into your revision control server, you will be able to 
+# to checkout the project and build it from the command line with make. However,
+# if more than one person works on the same project, then this file might show
+# conflicts since different users are bound to have compilers in different places.
+# In that case you might choose to not commit this file and let MPLAB X recreate this file
+# for each user. The disadvantage of not commiting this file is that you must run MPLAB X at
+# least once so the file gets created and the project can be built. Finally, you can also
+# avoid using this file at all if you are only building from the command line with make.
+# You can invoke make with the values of the macros:
+# $ makeMP_CC="/opt/microchip/mplabc30/v3.30c/bin/pic30-gcc" ...  
+#
+PATH_TO_IDE_BIN=/opt/microchip/mplabx/mplab_ide/mplab_ide/modules/../../bin/
+# Adding MPLAB X bin directory to path.
+PATH:=/opt/microchip/mplabx/mplab_ide/mplab_ide/modules/../../bin/:$(PATH)
+# Path to java used to run MPLAB X when this makefile was created
+MP_JAVA_PATH="/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.25.x86_64/jre/bin/"
+OS_CURRENT="$(shell uname -s)"
+# MP_CC is not defined
+# MP_CPPC is not defined
+# MP_BC is not defined
+MP_AS="/opt/microchip/mplabx/mpasmx/mpasmx"
+MP_LD="/opt/microchip/mplabx/mpasmx/mplink"
+MP_AR="/opt/microchip/mplabx/mpasmx/mplib"
+DEP_GEN=${MP_JAVA_PATH}java -jar "/opt/microchip/mplabx/mplab_ide/mplab_ide/modules/../../bin/extractobjectdependencies.jar" 
+# MP_CC_DIR is not defined
+# MP_CPPC_DIR is not defined
+# MP_BC_DIR is not defined
+MP_AS_DIR="/opt/microchip/mplabx/mpasmx"
+MP_LD_DIR="/opt/microchip/mplabx/mpasmx"
+MP_AR_DIR="/opt/microchip/mplabx/mpasmx"
+# MP_BC_DIR is not defined
diff --git a/mybootload.X/nbproject/Makefile-variables.mk b/mybootload.X/nbproject/Makefile-variables.mk
new file mode 100644 (file)
index 0000000..9db2045
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Generated - do not edit!
+#
+# NOCDDL
+#
+CND_BASEDIR=`pwd`
+# default configuration
+CND_ARTIFACT_DIR_default=dist/default/production
+CND_ARTIFACT_NAME_default=mybootload.X.production.hex
+CND_ARTIFACT_PATH_default=dist/default/production/mybootload.X.production.hex
+CND_PACKAGE_DIR_default=${CND_DISTDIR}/default/package
+CND_PACKAGE_NAME_default=mybootload.x.tar
+CND_PACKAGE_PATH_default=${CND_DISTDIR}/default/package/mybootload.x.tar
diff --git a/mybootload.X/nbproject/Package-default.bash b/mybootload.X/nbproject/Package-default.bash
new file mode 100644 (file)
index 0000000..c01315f
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash -x
+
+#
+# Generated - do not edit!
+#
+
+# Macros
+TOP=`pwd`
+CND_CONF=default
+CND_DISTDIR=dist
+TMPDIR=build/${CND_CONF}/${IMAGE_TYPE}/tmp-packaging
+TMPDIRNAME=tmp-packaging
+OUTPUT_PATH=dist/${CND_CONF}/${IMAGE_TYPE}/mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+OUTPUT_BASENAME=mybootload.X.${IMAGE_TYPE}.${OUTPUT_SUFFIX}
+PACKAGE_TOP_DIR=mybootload.x/
+
+# Functions
+function checkReturnCode
+{
+    rc=$?
+    if [ $rc != 0 ]
+    then
+        exit $rc
+    fi
+}
+function makeDirectory
+# $1 directory path
+# $2 permission (optional)
+{
+    mkdir -p "$1"
+    checkReturnCode
+    if [ "$2" != "" ]
+    then
+      chmod $2 "$1"
+      checkReturnCode
+    fi
+}
+function copyFileToTmpDir
+# $1 from-file path
+# $2 to-file path
+# $3 permission
+{
+    cp "$1" "$2"
+    checkReturnCode
+    if [ "$3" != "" ]
+    then
+        chmod $3 "$2"
+        checkReturnCode
+    fi
+}
+
+# Setup
+cd "${TOP}"
+mkdir -p ${CND_DISTDIR}/${CND_CONF}/package
+rm -rf ${TMPDIR}
+mkdir -p ${TMPDIR}
+
+# Copy files and create directories and links
+cd "${TOP}"
+makeDirectory ${TMPDIR}/mybootload.x/bin
+copyFileToTmpDir "${OUTPUT_PATH}" "${TMPDIR}/${PACKAGE_TOP_DIR}bin/${OUTPUT_BASENAME}" 0755
+
+
+# Generate tar file
+cd "${TOP}"
+rm -f ${CND_DISTDIR}/${CND_CONF}/package/mybootload.x.tar
+cd ${TMPDIR}
+tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/package/mybootload.x.tar *
+checkReturnCode
+
+# Cleanup
+cd "${TOP}"
+rm -rf ${TMPDIR}
diff --git a/mybootload.X/nbproject/configurations.xml b/mybootload.X/nbproject/configurations.xml
new file mode 100644 (file)
index 0000000..ef190a3
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configurationDescriptor version="62">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>spbrgselect.inc</itemPath>
+    </logicalFolder>
+    <logicalFolder name="LinkerScript"
+                   displayName="Linker Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>main.asm</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="default" type="2">
+      <toolsSet>
+        <developmentServer>localhost</developmentServer>
+        <targetDevice>PIC16F1455</targetDevice>
+        <targetHeader></targetHeader>
+        <targetPluginBoard></targetPluginBoard>
+        <platformTool>ICD3PlatformTool</platformTool>
+        <languageToolchain>MPASMWIN</languageToolchain>
+        <languageToolchainVersion>5.52</languageToolchainVersion>
+        <platform>2</platform>
+      </toolsSet>
+      <compileType>
+        <linkerTool>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+        <loading>
+          <useAlternateLoadableFile>false</useAlternateLoadableFile>
+          <alternateLoadableFile></alternateLoadableFile>
+        </loading>
+      </compileType>
+      <makeCustomizationType>
+        <makeCustomizationPreStepEnabled>false</makeCustomizationPreStepEnabled>
+        <makeCustomizationPreStep></makeCustomizationPreStep>
+        <makeCustomizationPostStepEnabled>false</makeCustomizationPostStepEnabled>
+        <makeCustomizationPostStep></makeCustomizationPostStep>
+        <makeCustomizationPutChecksumInUserID>false</makeCustomizationPutChecksumInUserID>
+        <makeCustomizationEnableLongLines>false</makeCustomizationEnableLongLines>
+        <makeCustomizationNormalizeHexFile>false</makeCustomizationNormalizeHexFile>
+      </makeCustomizationType>
+      <ICD3PlatformTool>
+        <property key="AutoSelectMemRanges" value="auto"/>
+        <property key="Freeze Peripherals" value="true"/>
+        <property key="SecureSegment.SegmentProgramming" value="FullChipProgramming"/>
+        <property key="ToolFirmwareFilePath"
+                  value="Press to browse for a specific firmware version"/>
+        <property key="ToolFirmwareOption.UseLatestFirmware" value="true"/>
+        <property key="debugoptions.useswbreakpoints" value="false"/>
+        <property key="hwtoolclock.frcindebug" value="false"/>
+        <property key="memories.aux" value="false"/>
+        <property key="memories.bootflash" value="false"/>
+        <property key="memories.configurationmemory" value="false"/>
+        <property key="memories.eeprom" value="true"/>
+        <property key="memories.flashdata" value="true"/>
+        <property key="memories.id" value="true"/>
+        <property key="memories.programmemory" value="true"/>
+        <property key="memories.programmemory.end" value="0x1fff"/>
+        <property key="memories.programmemory.start" value="0x0"/>
+        <property key="poweroptions.powerenable" value="false"/>
+        <property key="programoptions.eraseb4program" value="true"/>
+        <property key="programoptions.preserveeeprom" value="false"/>
+        <property key="programoptions.preserveprogramrange" value="false"/>
+        <property key="programoptions.preserveprogramrange.end" value="0x1fff"/>
+        <property key="programoptions.preserveprogramrange.start" value="0x0"/>
+        <property key="programoptions.preserveuserid" value="false"/>
+        <property key="programoptions.testmodeentrymethod" value="VPPFirst"/>
+        <property key="programoptions.usehighvoltageonmclr" value="false"/>
+        <property key="programoptions.uselvpprogramming" value="false"/>
+        <property key="voltagevalue" value="5.0"/>
+      </ICD3PlatformTool>
+      <MPASMWIN-AS>
+        <property key="cross.reference.file" value=""/>
+        <property key="default.radix" value="HEX"/>
+        <property key="enable.case.sensitivity" value="true"/>
+        <property key="hex.output.format" value="INHX32"/>
+        <property key="preprocessor.macros" value=""/>
+        <property key="warning.level" value="0"/>
+      </MPASMWIN-AS>
+      <MPASMWIN-LD>
+        <property key="cod-file" value="false"/>
+        <property key="extra-lib-directories" value=""/>
+        <property key="hex-output-format" value="INHX32"/>
+        <property key="map-file" value="${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.map"/>
+      </MPASMWIN-LD>
+      <PICkit2PlatformTool>
+        <property key="pk2settings.3state" value="false"/>
+        <property key="pk2settings.preserveee" value="false"/>
+        <property key="pk2settings.setvddvoltage" value=""/>
+        <property key="pk2settings.userpgmexec" value="true"/>
+        <property key="pk2settings.usetargetpower" value="true"/>
+      </PICkit2PlatformTool>
+      <mpasmsuite>
+        <property key="absolute-mode" value="false"/>
+        <property key="eeprom-width" value="8"/>
+        <property key="extended-mode" value="false"/>
+        <property key="extended-mode-mpasm" value="false"/>
+        <property key="extended-mode-mplink" value="false"/>
+      </mpasmsuite>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/mybootload.X/nbproject/private/SuppressibleMessageMemo.properties b/mybootload.X/nbproject/private/SuppressibleMessageMemo.properties
new file mode 100644 (file)
index 0000000..832d3ca
--- /dev/null
@@ -0,0 +1,22 @@
+#
+#Fri Sep 27 11:32:28 BST 2013
+mdbDebugger/MEMORY_VIEW_LAST_HW_BP_RESOURCE_WARN=false
+pkobskde/CHECK_4_HIGH_VOLTAGE_VPP=false
+pk3/DEVID_MISMATCH=false
+mdbDebugger/NO_HW_COMBINER_RESOURCES_WARNING=false
+mdbDebugger/NO_HW_BP_RESOURCES_WARN=false
+mdbDebugger/MEMORY_VIEW_NO_HW_BP_RESOURCES_WARN=false
+pk3/CHECK_CLOCK=false
+mdbDebugger/LAST_HW_BP_RESOURCE_WARN=false
+pk3/CHECK_4_HIGH_VOLTAGE_VPP=false
+icd3/DEVID_MISMATCH=false
+realice/DEVID_MISMATCH=false
+realice/CHECK_CLOCK=false
+pkoblicdbgr/DEVID_MISMATCH=false
+pkoblicdbgr/CHECK_CLOCK=false
+pkobskde/DEVID_MISMATCH=false
+icd3/CHECK_CLOCK=false
+realice/CHECK_4_HIGH_VOLTAGE_VPP=false
+pkoblicdbgr/CHECK_4_HIGH_VOLTAGE_VPP=false
+pkobskde/CHECK_CLOCK=false
+icd3/CHECK_4_HIGH_VOLTAGE_VPP=true
diff --git a/mybootload.X/nbproject/private/configurations.xml b/mybootload.X/nbproject/private/configurations.xml
new file mode 100644 (file)
index 0000000..56374ed
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configurationDescriptor version="62">
+  <projectmakefile>Makefile</projectmakefile>
+  <defaultConf>0</defaultConf>
+  <confs>
+    <conf name="default" type="2">
+      <platformToolSN>:=MPLABCommUSB:=04D8:=9009:=0100:=Microchip Technology, Inc. (www.microchip.com):=MPLAB ICD3 tm (www.microchip.com):=JIT123410560:=x:=en</platformToolSN>
+      <languageToolchainDir>/opt/microchip/mplabx/mpasmx</languageToolchainDir>
+      <mdbdebugger version="1">
+        <placeholder1>place holder 1</placeholder1>
+        <placeholder2>place holder 2</placeholder2>
+      </mdbdebugger>
+      <runprofile version="6">
+        <args></args>
+        <rundir></rundir>
+        <buildfirst>true</buildfirst>
+        <console-type>0</console-type>
+        <terminal-type>0</terminal-type>
+        <remove-instrumentation>0</remove-instrumentation>
+        <environment>
+        </environment>
+      </runprofile>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/mybootload.X/nbproject/private/private.properties b/mybootload.X/nbproject/private/private.properties
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mybootload.X/nbproject/private/private.xml b/mybootload.X/nbproject/private/private.xml
new file mode 100644 (file)
index 0000000..e396670
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?><project-private xmlns="http://www.netbeans.org/ns/project-private/1">
+    <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
+</project-private>
diff --git a/mybootload.X/nbproject/project.properties b/mybootload.X/nbproject/project.properties
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mybootload.X/nbproject/project.xml b/mybootload.X/nbproject/project.xml
new file mode 100644 (file)
index 0000000..f437b8e
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>com.microchip.mplab.nbide.embedded.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>mybootload</name>
+            <creation-uuid>dc4e0df1-dbee-4df1-977e-9dfb5bf3e19a</creation-uuid>
+            <make-project-type>0</make-project-type>
+            <c-extensions/>
+            <cpp-extensions/>
+            <header-extensions/>
+            <sourceEncoding>UTF-8</sourceEncoding>
+            <make-dep-projects/>
+        </data>
+    </configuration>
+</project>
diff --git a/mybootload.X/spbrgselect.inc b/mybootload.X/spbrgselect.inc
new file mode 100644 (file)
index 0000000..69c2a7e
--- /dev/null
@@ -0,0 +1,33 @@
+RoundResult SET 0                              ; Rounding function.  RoundResult = Round(aa/bb)\r
+Round  macro aa,bb\r
+       LOCAL rr = aa/bb\r
+       LOCAL d1 = aa - rr*bb\r
+       LOCAL d2 = (rr+1)*bb - aa\r
+RoundResult = rr\r
+       if d1 >= d2\r
+RoundResult++\r
+       endif\r
+       endm\r
+\r
+AbsResult SET 0\r
+Abs            macro nr\r
+       if nr>=0\r
+AbsResult = nr\r
+       else\r
+AbsResult = -nr\r
+       endif\r
+       endm\r
+               \r
+       Round xtal,(16*baud)\r
+spbrg_value EQU RoundResult-1\r
+\r
+       Round xtal,(16*(spbrg_value+1))\r
+baud_real EQU RoundResult\r
+       Abs(baud_real-baud)\r
+errpercent EQU AbsResult*100/baud\r
+       if errpercent > 4\r
+               ERROR big error in baudrate: #v(errpercent)%\r
+       endif\r
+       if errpercent >= 2\r
+               messg baudrate not exact: #v(errpercent)%\r
+       endif
\ No newline at end of file