14 #define VERSION "Swansea Hackspace PIC Bootloader v1"
16 #define BAUD_RATE 19200
19 #define PORT_NAME "COM4:"
21 #define PORT_NAME "/dev/ttyUSB0"
24 void usage(const char * name)
27 loge("Usage: %s [-b baud] [-p port] [-i] [-v] {file.hex}", name);
28 loge("-b baud Set baudrate (default: %d)", BAUD_RATE);
29 loge("-p port Set serial port (default: %s)", PORT_NAME);
30 loge("-i ID Only mode.");
31 loge("-v Verify after write");
35 #define MIN(a,b) ((a)<(b)?(a):(b))
37 int bitmask(int value)
40 if (value >= (1<<1)) out |= 1;
41 if (value >= (1<<2)) out |= 1<<1;
42 if (value >= (1<<3)) out |= 1<<2;
43 if (value >= (1<<4)) out |= 1<<3;
44 if (value >= (1<<5)) out |= 1<<4;
45 if (value >= (1<<6)) out |= 1<<5;
46 if (value >= (1<<7)) out |= 1<<6;
47 if (value >= (1<<8)) out |= 1<<7;
48 if (value >= (1<<9)) out |= 1<<8;
49 if (value >= (1<<10)) out |= 1<<9;
54 * This routine writes a memory plan out to the device
56 int update_mem(port_t * pt, const devid_t * dev, uint16_t maxmem, mem_t * ram, int verify)
59 uint8_t buff[1024]; // scratch space
61 for (block=ram; block != NULL; block=block->next) {
62 int bstart = block->start / 2;
64 /* skip config words, we cant write them anyway */
65 if (bstart >= 0x8000) {
66 logd("UpdateMem: skip config block @ %04x", bstart);
71 uint8_t * p = block->bytes;
72 int left = block->len;
73 uint16_t addr = bstart;
74 int rowlen = dev->rowsize * 2;
75 logd("UpdateMem: new block %d bytes @ %04x", block->len, bstart);
81 memset(buff, 255, sizeof(buff));
83 /* first row, align the start */
84 if (addr % dev->rowsize != 0) {
85 addr &= ~bitmask(dev->rowsize);
86 off = (bstart - addr) * 2;
88 logd("UpdateMem: realigning %04X to %04X", bstart, addr);
94 logd("UpdateMem: Preparing %d bytes @ %04X", len, addr);
96 /* partial row write, read first */
97 if (off != 0 || len < rowlen) {
98 logd("UpdateMem: Read %d words @ %04x", dev->rowsize, addr);
99 if (loader_readmem(pt, addr, buff, dev->rowsize)) {
100 loge("UpdateMem: Aborting on failed read");
103 print_memory(addr, buff, dev->rowsize);
106 /* update with new values */
107 memcpy(&buff[off], p, len);
110 logd("UpdateMem: Writing %d words @ %04x", dev->rowsize, addr);
111 print_memory(addr, buff, dev->rowsize);
112 if (loader_writemem(pt, addr, buff, dev->rowsize)) {
113 loge("UpdateMem: Aborting on failed write");
119 logd("UpdateMem: Verify %d words @ %04x", dev->rowsize, addr);
120 if (loader_readmem(pt, addr, again, dev->rowsize)) {
121 loge("UpdateMem: Aborting on failed read");
124 print_memory(addr, again, dev->rowsize);
125 for (int i=0; i<dev->rowsize; i++) {
126 if (again[i] != buff[i]) {
127 loge("UpdateMem: Verify failed on block 0x%04X", addr);
136 addr += dev->rowsize;
142 int main(int argc, char **argv)
146 int baud = BAUD_RATE;
150 while ((opt=getopt(argc, argv, "h?b:p:ivd"))!=-1) {
156 if (port) free(port);
157 port = strdup(optarg);
176 if (port == NULL) port = PORT_NAME;
178 if (!idonly && optind >= argc) {
179 loge("Error: missing hexfile");
189 if ((fd = fopen(argv[optind], "r"))==NULL) {
190 loge("Error opening %s: %s", argv[optind], strerror(errno));
196 logd("Memory Summary :-");
200 logd("open serial port %s at %d baud", port, baud);
201 port_t * pt = serial_open(port, baud);
208 if (loader_connect(pt, &maxmem, &devid)) {
212 const devid_t * dev = devid_to_info(devid);
215 logi("Device ID: %04X", devid);
216 logi(" Free Mem: %d words available", maxmem);
218 logi(" Dev Name: %s", dev->name );
219 logi(" Max Mem: %d", dev->memsize );
224 if (dev) logd("Device Name: %s", dev->name);
226 /* check that the selected program will fit on this device */
227 if (makesafe_mem(&ram, maxmem)) {
231 logd("After re-organisation");
234 /* now write the updated memory plan to the device */
235 if (!update_mem(pt, dev, maxmem, ram, verify)) {
237 logi("Device Write (and Verify) Complete");
239 logi("Device Write Complete");