Kaynağa Gözat

Support for writing to Flash, some improvements

Added basic support for writing to Flash memory and improved the code.
Mateusz Bugdalski 13 yıl önce
ebeveyn
işleme
2f19f600b5
8 değiştirilmiş dosya ile 247 ekleme ve 110 silme
  1. 166 72
      lpc.c
  2. 1 0
      lpc.h
  3. 15 4
      main.c
  4. 1 0
      serial.c
  5. 3 0
      serial.h
  6. 52 29
      sprog.c
  7. 6 3
      sprog.h
  8. 3 2
      uucode.c

+ 166 - 72
lpc.c

@@ -38,17 +38,20 @@ const struct sprog_family lpc_family = {
   .setup = (void*(*)(struct serial_device*)) lpc_setup,
   .init = (void(*)(void*)) lpc_init,
   .exec = (void(*)(void*, const struct sprog_data*)) lpc_exec,
+  .write = (void(*)(void*, const struct sprog_data*)) lpc_write,
   .close = (void(*)(void*)) lpc_close
 };
   
   
 
 void lpc_ispmode(struct lpc_device *dev, int state);
-void lpc_reset(struct lpc_device *dev);
-void lpc_vprintf(const char *text, va_list l);
-void lpc_printf(const char *text, ...);
-int lpc_getline(char *buf);
-int lpc_command(const char *text, ...);
+void lpc_reset(struct lpc_device *dev, int isp);
+int lpc_scanf(struct lpc_device *dev, const char *text, ...);
+void lpc_vprintf(struct lpc_device *dev, const char *text, va_list l);
+void lpc_printf(struct lpc_device *dev, const char *text, ...);
+int lpc_getline(struct lpc_device *dev, char *buf);
+int lpc_command(struct lpc_device *dev, const char *text, ...);
+int lpc_await_reply(struct lpc_device *dev, ...);
 int lpc_read_partid(struct lpc_device *dev);
 void lpc_write_ram(struct lpc_device *dev, const struct sprog_data *d, unsigned int addr);
 
@@ -58,51 +61,109 @@ struct lpc_device *lpc_setup(struct serial_device *port) {
   dev = malloc(sizeof(struct lpc_device));
   dev->port = port;
   dev->part = NULL;
-  lpc_ispmode(dev, 1);
-  lpc_reset(dev);
+  lpc_reset(dev, 1);
   return dev;
 }
 
 void lpc_init(struct lpc_device *dev) {
   char buf[4096];
-  printf("?");
-  fflush(stdout);
-  if(lpc_getline(buf)) {
-    if(strcmp(buf, "Synchronized\r\n")==0)
-      sprog_error("Synchronization successful\n");
-    lpc_printf("Synchronized\r\n");
-    lpc_getline(buf);
-    if(strcmp(buf, "OK\r\n")!=0)
+  
+  lpc_printf(dev, "?");
+  fflush(dev->port->f);
+  
+  if(lpc_await_reply(dev, "Synchronized", NULL)==1) {
+      sprog_info("Synchronization successful\n");
+    lpc_printf(dev, "Synchronized\r\n");
+    if(lpc_await_reply(dev, "OK", NULL)!=1)
       sprog_error("Expected OK, received '%s'\n", buf);
-    sprog_error("Sending clock frequency\n");
-    lpc_printf("12000\r\n");
-    lpc_getline(buf);
-    if(strcmp(buf, "OK\r\n")!=0)
+    lpc_printf(dev, "12000\r\n");
+    if(lpc_await_reply(dev, "OK", NULL)!=1)
       sprog_error("Expected OK, received '%s'\n", buf);
   } else {
-    printf("\r\n");
-    if(lpc_getline(buf))
-      if(strcmp(buf, "?\r\n")==0)
-	sprog_error("The device appears to be already synchronized\n");
-    lpc_getline(buf); /* deny invalid command reply */
+    lpc_printf(dev, "\r\n");
+    if(lpc_await_reply(dev, "OK", NULL)==1)
+      sprog_info("The device appears to be already synchronized\n");
+    else
+      sprog_error("Invalid device response\n");
+    lpc_getline(dev, buf); /* receive invalid command reply */
   }
-  sprog_error("Reading part ID\n");
   if(lpc_read_partid(dev)==0)
-    sprog_error("Found device: %s, %dkB Flash, %dkB RAM\n", dev->part->name, dev->part->flash, dev->part->ram);
+    sprog_info("Found device: %s, %dkB Flash, %dkB RAM\n", dev->part->name, dev->part->flash, dev->part->ram);
+}
+
+void lpc_write(struct lpc_device *dev, const struct sprog_data *d) {
+  static const int chunk_sizes[] = {256, 512, 1024, 4096, 0};
+  struct sprog_data chunk;
+  int i;
+  int offset;
+  int chunk_size;
+  int data_size;
+  offset = 0;
+  
+  chunk.data = NULL;
+  
+  i = 7; /* dev->part->flash/4; /* number of sectors = Flash size / 4kB */
+  lpc_command(dev, "P 0 %d\r\n", i);
+  
+  sprog_info("Erasing Flash memory... ");
+  if(lpc_command(dev, "E 0 %d\r\n", i))
+    sprog_info("Error\n");
+  else
+    sprog_info("OK\n");
+  
+  i = d->size/4096;
+  lpc_command(dev, "P 0 %d\r\n", i); /* prepare sectors for write */
+  
+  while(d->size-offset>0) {
+    chunk_size = d->size - offset;
+    for(i=0; chunk_sizes[i]; i++) {
+      if(chunk_sizes[i]>=chunk_size)
+	break;
+      /*if(chunk_sizes[i]+1024 > dev->part->ram) {
+	i--;
+	break;
+      }*/
+    }
+    
+    chunk_size = chunk_sizes[i];
+    if(chunk_size==0) chunk_size = chunk_sizes[i-1];
+    sprog_alloc_data(&chunk, chunk_size);
+    
+    data_size = chunk_size;
+    if(data_size > d->size-offset)
+      data_size = d->size - offset;
+    
+    for(i=0; i<data_size; i++)
+      chunk.data[i] = d->data[offset+i];
+    
+    for(i=data_size; i<chunk_size; i++)
+      chunk.data[i] = 0;
+    
+    chunk.size = chunk_size;
+    
+    lpc_write_ram(dev, &chunk, 0x10000400);
+    
+    sprog_info("Copying to Flash...\n");
+    if(lpc_command(dev, "C %d %u %d\r\n", offset, 0x10000400, chunk_size))
+      sprog_error("Error while copying to flash\n");
+    else
+      sprog_info("Done!\n");
+    
+    offset += data_size;
+  }
 }
 
 void lpc_exec(struct lpc_device *dev, const struct sprog_data *d) {
   lpc_write_ram(dev, d, 0x10000400);
-  lpc_command("U 23130\r\n");
-  sprog_error("Executing code... ");
-  if(lpc_command("G %u T\r\n", 0x10000400))
-    sprog_error("Error\n");
+  lpc_command(dev, "U 23130\r\n");
+  sprog_info("Executing code... ");
+  if(lpc_command(dev, "G %u T\r\n", 0x10000400))
+    sprog_info("Error\n");
   else
-    sprog_error("OK\n");
+    sprog_info("OK\n");
 }
 
 void lpc_write_ram(struct lpc_device *dev, const struct sprog_data *d, unsigned int addr) {
-  char reply_buf[4096];
   int last_offset;
   int last_i;
   int offset;
@@ -114,88 +175,116 @@ void lpc_write_ram(struct lpc_device *dev, const struct sprog_data *d, unsigned
   if(d->size & 3)
     sprog_error("Invalid data size - should be aligned to 4\n");
   
-  lpc_command("W %u %u\r\n", addr, d->size);
-  sprog_error("Writing %d bytes\n", d->size);
+  lpc_command(dev, "W %u %u\r\n", addr, d->size);
+  sprog_info("Writing %d bytes\n", d->size);
   
   last_i = 0;
   last_offset = 0;
   offset = 0;
-  sprog_progress((offset*100)/d->size);
+  sprog_progress(offset, d->size);
   checksum = 0;
   
   for(i=0; (j = uuencode_line(d, buf, &offset, &checksum)); i++) {
-    if(j==1) lpc_printf("%s\r\n", buf);
+    lpc_printf(dev, "%s\r\n", buf);
     if(j==2 || (i % 20)==19) {
-      lpc_printf("%u\r\n", checksum);
+      lpc_printf(dev, "%u\r\n", checksum);
       checksum = 0;
       
-      if(lpc_getline(reply_buf)) {
-	if(strcmp(reply_buf, "OK\r\n")==0) {
+      switch(lpc_await_reply(dev, "OK", "RESEND", NULL)) {
+	case 1:
 	  last_offset = offset;
 	  last_i = i;
-	  if(j==2)
-	    offset = -1;
-	} else {
+	  break;
+	case 2:
+	default:
 	  offset = last_offset;
 	  i = last_i;
-	}
-      } else
-	break;
+      }
+    }
+    sprog_progress(offset, d->size);
+  }
+  sprog_info("\n");
+}
+
+int lpc_await_reply(struct lpc_device *dev, ...) {
+  char buf[4096];
+  int i;
+  const char *t;
+  va_list l;
+  va_start(l, dev);
+  if(!lpc_getline(dev, buf))
+    return 0;
+  for(i=0; buf[i]; i++) {
+    if(buf[i]=='\n') {
+      buf[i] = 0;
+      if(i>0) {
+	if(buf[i-1]=='\r')
+	  buf[i-1] = 0;
+      }
+      break;
     }
-    if(offset!=-1)
-      sprog_progress((offset*100)/d->size);
-    else
-      sprog_progress(100);
   }
   
-  if(offset!=-1)
-    sprog_error("Error while writing to RAM\n");
+  for(i=0; (t = va_arg(l, const char*)); i++) {
+    if(strcmp(buf, t)==0)
+      return i+1;
+  }
+  return -1;
 }
   
 
-int lpc_getline(char *buf) {
-  if(sprog_waitdata(500)==0)
+int lpc_getline(struct lpc_device *dev, char *buf) {
+  if(sprog_waitdata(dev->port, 500)==0)
     return 0;
-  fgets(buf, 4096, stdin);
+  fgets(buf, 4096, dev->port->f);
   return 1;
 }
 
-void lpc_vprintf(const char *text, va_list l) {
+int lpc_scanf(struct lpc_device *dev, const char *text, ...) {
+  int r;
   char buf[4096];
-  vprintf(text, l);
-  lpc_getline(buf);
+  va_list l;
+  va_start(l, text);
+  if(!lpc_getline(dev, buf))
+    return 0;
+  r = vsscanf(buf, text, l);
+  va_end(l);
+  return r;
+}
+
+void lpc_vprintf(struct lpc_device *dev, const char *text, va_list l) {
+  char buf[4096];
+  vsprintf(buf, text, l);
+  serial_write(dev->port, buf);
+  lpc_getline(dev, buf);
 }
 
-void lpc_printf(const char *text, ...) {
+void lpc_printf(struct lpc_device *dev, const char *text, ...) {
   va_list l;
   va_start(l, text);
-  lpc_vprintf(text, l);
+  lpc_vprintf(dev, text, l);
   va_end(l);
 }
 
-int lpc_command(const char *text, ...) {
-  char buf[4096];
+int lpc_command(struct lpc_device *dev, const char *text, ...) {
   int res;
   va_list l;
   va_start(l, text);
-  lpc_vprintf(text, l);
+  lpc_vprintf(dev, text, l);
   va_end(l);
-  lpc_getline(buf);
-  if(sscanf(buf, "%d", &res)<1)
+  if(lpc_scanf(dev, "%d", &res)<1)
     return -1;
   return res;
 }
 
 int lpc_read_partid(struct lpc_device *dev) {
-  char buf[4096];
   int i;
   int res;
   unsigned int partid;
-  res = lpc_command("J\r\n");
+  res = lpc_command(dev, "J\r\n");
   if(res!=0)
     return res;
-  lpc_getline(buf);
-  sscanf(buf, "%u", &partid);
+  lpc_scanf(dev, "%u", &partid);
   for(i=0; lpc_parts[i].name; i++)
     if(lpc_parts[i].part_id==partid)
       break;
@@ -210,12 +299,17 @@ void lpc_ispmode(struct lpc_device *dev, int state) {
   serial_setline(dev->port, SERIAL_DTR, state);
 }
 
-void lpc_reset(struct lpc_device *dev) {
+void lpc_reset(struct lpc_device *dev, int isp) {
   /* TODO: configure the control lines */
-  serial_setline(dev->port, SERIAL_RTS, 1);
+  serial_setline(dev->port, SERIAL_DTR, 1);
+  if(isp)
+    lpc_ispmode(dev, 1);
   sprog_sleep(50);
-  serial_setline(dev->port, SERIAL_RTS, 0);
-  sprog_sleep(10);
+  serial_setline(dev->port, SERIAL_DTR, 0);
+  if(isp) {
+    sprog_sleep(50);
+    lpc_ispmode(dev, 0);
+  }
 }
 
 void lpc_close(struct lpc_device *dev) {

+ 1 - 0
lpc.h

@@ -12,6 +12,7 @@ struct lpc_device {
 struct lpc_device *lpc_setup(struct serial_device *port);
 void lpc_init(struct lpc_device *dev);
 void lpc_exec(struct lpc_device *dev, const struct sprog_data *d);
+void lpc_write(struct lpc_device *dev, const struct sprog_data *d);
 void lpc_close(struct lpc_device *dev);
 
 

+ 15 - 4
main.c

@@ -10,6 +10,7 @@ struct option sprog_options[] = {
   {"family", required_argument, NULL, 'f'},
   {"baud", required_argument, NULL, 'b'},
   {"exec", required_argument, NULL, 'e'},
+  {"write", required_argument, NULL, 'w'},
   {"version", no_argument, NULL, 'v'},
   {"help", no_argument, NULL, 'h'},
   {NULL, 0, NULL, 0}
@@ -25,18 +26,27 @@ int main(int argc, char *argv[]) {
   int opt;
   int option_index;
   int baud;
+  int mode;
   char port[128];
   char path[128];
   port[0] = 0;
   path[0] = 0;
   fam = NULL;
+  baud = 9600;
   
-  while((opt = getopt_long(argc, argv, "p:b:f:e:h", sprog_options, &option_index))!=-1) {
+  mode = 0;
+  
+  while((opt = getopt_long(argc, argv, "p:b:f:e:w:h", sprog_options, &option_index))!=-1) {
     switch(opt) {
       case 'p':
 	strncpy(port, optarg, sizeof(port));
 	break;
       case 'e':
+	mode = 1;
+	strncpy(path, optarg, sizeof(path));
+	break;
+      case 'w':
+	mode = 2;
 	strncpy(path, optarg, sizeof(path));
 	break;
       case 'f':
@@ -77,13 +87,13 @@ int main(int argc, char *argv[]) {
     return 1;
   }
   
-  if(path[0]) {
+  if(mode) {
     d.data = NULL;
     d.size = 0;
     sprog_load(&d, path);
-    sprog_communicate(fam, &d, port, baud);
+    sprog_communicate(fam, &d, mode, port, baud);
   } else
-    sprog_communicate(fam, NULL, port, baud);
+    sprog_communicate(fam, NULL, mode, port, baud);
     
   
   return 0;
@@ -97,6 +107,7 @@ void usage(const char *name) {
   printf("  -f <family>, --family <family>	specify the microcontroller family, eg. lpc\n");
   printf("  -b <baud>, --baud <baud>		specify the baud rate\n");
   printf("  -e <file>, --exec <file>		execute the given file\n");
+  printf("  -w <file>, --write <file>		write the given file to Flash\n");
   printf("  -h, --help				display this help\n");
   printf("  --version				print version and exit\n");
 }

+ 1 - 0
serial.c

@@ -56,6 +56,7 @@ int serial_open(struct serial_device *port, const char *path, int baud) {
   serial_setbaud_termios(&attr, baud);
   tcsetattr(fd, TCSANOW, &attr);
   port->fd = fd;
+  port->f = fdopen(fd, "r+");
   return fd;
 }
 

+ 3 - 0
serial.h

@@ -1,6 +1,8 @@
 #ifndef __SERIAL_H__
 #define __SERIAL_H__
 
+#include <stdio.h>
+
 #define SERIAL_DTR 0
 #define SERIAL_RTS 1
 
@@ -17,6 +19,7 @@ struct ring_buf {
 
 struct serial_device {
   int fd;
+  FILE *f;
   struct ring_buf in_buf;
   struct ring_buf out_buf;
 };

+ 52 - 29
sprog.c

@@ -9,7 +9,7 @@
 #include <sys/wait.h>
 #include <sprog.h>
 
-void sprog_process(const struct sprog_family *fam, void *arg, const struct sprog_data *d, int nstdin, int nstdout);
+void sprog_process(const struct sprog_family *fam, void *arg, const struct sprog_data *d, int mode);
 
 void sprog_error(const char *text, ...) {
   va_list l;
@@ -18,43 +18,44 @@ void sprog_error(const char *text, ...) {
   va_end(l);
 }
 
+void sprog_info(const char *text, ...) {
+  va_list l;
+  va_start(l, text);
+  vprintf(text, l);
+  va_end(l);
+}
+
 void sprog_sleep(int msec) {
   usleep(msec * 1000);
 }
 
-void sprog_communicate(const struct sprog_family *fam, const struct sprog_data *d, const char *port, int baud) {
+void sprog_communicate(const struct sprog_family *fam, const struct sprog_data *d, int mode, const char *port, int baud) {
   void *arg;
   struct serial_device dev;
   
   serial_open(&dev, port, baud);
   arg = fam->setup(&dev);
-  sprog_process(fam, arg, d, dev.fd, dev.fd);
+  sprog_process(fam, arg, d, mode);
 }
 
-int sprog_waitdata(int timeout) {
+int sprog_waitdata(struct serial_device *port, int timeout) {
   fd_set read_set;
   struct timeval tval;
   FD_ZERO(&read_set);
-  FD_SET(1, &read_set);
+  FD_SET(port->fd, &read_set);
   tval.tv_sec = timeout/1000;
   tval.tv_usec = (timeout%1000)*1000;
-  if(select(1+1, &read_set, NULL, NULL, &tval)!=1)
+  if(select(port->fd+1, &read_set, NULL, NULL, &tval)!=1)
     return 0;
   return 1;
 }
 
-void sprog_process(const struct sprog_family *fam, void *arg, const struct sprog_data *d, int nstdin, int nstdout) {
-  int oldstdin;
-  int oldstdout;
-  oldstdin = dup(0);
-  oldstdout = dup(1);
-  dup2(nstdin, 0);
-  dup2(nstdout, 1);
+void sprog_process(const struct sprog_family *fam, void *arg, const struct sprog_data *d, int mode) {
   fam->init(arg);
-  if(d)
+  if(mode==1)
     fam->exec(arg, d);
-  dup2(oldstdin, 0);
-  dup2(oldstdout, 1);
+  else if(mode==2)
+    fam->write(arg, d);
 }
 
 void sprog_load(struct sprog_data *d, const char *path) {
@@ -84,40 +85,62 @@ void sprog_load(struct sprog_data *d, const char *path) {
 
 void sprog_append_data(struct sprog_data *d, const char *data, int len) {
   int i;
+
+  if(!d->data)
+    d->size = 0;
+  
+  sprog_alloc_data(d, d->size+len);
+  
+  for(i=0; i<len; i++)
+    d->data[i+d->size] = data[i];
+
+  d->size += len;
+}
+
+void sprog_alloc_data(struct sprog_data *d, int len) {
   int alloc;
   alloc = d->alloc;
   
-  if(!d->data)
+  if(!d->data) {
     alloc = 4096;
+    d->size = 0;
+  }
   
-  while((d->size+len+128)>alloc)
+  while(len+128>alloc)
     alloc *= 2;
   
-  if(d->data)
-    d->data = realloc(d->data, alloc);
-  else
+  if(d->data) {
+    if(d->alloc!=alloc)
+      d->data = realloc(d->data, alloc);
+  } else
     d->data = malloc(alloc);
   
-  for(i=0; i<len; i++)
-    d->data[i+d->size] = data[i];
-  
   d->alloc = alloc;
-  d->size = len;
 }
 
-void sprog_progress(int progress) {
+void sprog_progress(int progress, int total) {
   char buf[80];
   int i;
   int w;
-  w = (progress*7)/10;
+  int p;
+  
+  if(progress==total) {
+    p = 100;
+    w = 70;
+  } else {
+    p = (progress*100)/total;
+    w = (progress*70)/total;
+  }
+  
   for(i=0; i<70; i++) {
-    if(i<=w)
+    if(i<w)
       buf[i] = ':';
     else
       buf[i] = ' ';
   }
   buf[i] = 0;
   
-  sprog_error("\r[%s] %3d%%", buf, progress);
+  sprog_info("\r[%s] %3d%%", buf, p);
+  fflush(stdout);
 }
  

+ 6 - 3
sprog.h

@@ -14,19 +14,22 @@ struct sprog_family {
   void *(*setup)(struct serial_device *dev);
   void (*init)(void *arg);
   void (*exec)(void *arg, const struct sprog_data *d);
+  void (*write)(void *arg, const struct sprog_data *d);
   void (*close)(void *arg);
 };
 
 
 extern const char sprog_version[];
-void sprog_communicate(const struct sprog_family *fam, const struct sprog_data *d, const char *port, int baud);
+void sprog_communicate(const struct sprog_family *fam, const struct sprog_data *d, int mode, const char *port, int baud);
 int sprog_getline(char *buf, int len, int timeout);
-int sprog_waitdata(int timeout);
+int sprog_waitdata(struct serial_device *port, int timeout);
+void sprog_info(const char *text, ...);
 void sprog_error(const char *text, ...);
 void sprog_sleep(int msec);
 void sprog_load(struct sprog_data *d, const char *path);
+void sprog_alloc_data(struct sprog_data *d, int len);
 void sprog_append_data(struct sprog_data *d, const char *data, int len);
-void sprog_progress(int progress);
+void sprog_progress(int progress, int total);
 
 
 #endif

+ 3 - 2
uucode.c

@@ -10,7 +10,7 @@ int uuencode_line(const struct sprog_data *d, char *dst, int *offset, int *check
   int n;
   int i;
   
-  if(*offset==-1)
+  if(*offset >= d->size)
     return 0;
   
   b = d->size - *offset;
@@ -48,10 +48,11 @@ int uuencode_line(const struct sprog_data *d, char *dst, int *offset, int *check
   
   dstd[0] = 0;
   
+  *offset += b;
+  
   if(*offset >= d->size)
     return 2;
   
-  *offset += b;
   return 1;
 }