1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-11-24 00:20:38 +02:00

lpc111x-isp/lpc111x.c: if file argument is given, flash that file

This commit is contained in:
Werner Almesberger 2012-12-30 23:29:24 -03:00
parent 5246f5fbc6
commit 66d091317a

View File

@ -18,6 +18,8 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <alloca.h> #include <alloca.h>
#include <assert.h>
#include <sys/types.h>
#include <ubb/ubb.h> #include <ubb/ubb.h>
#include <ubb/swuart.h> #include <ubb/swuart.h>
@ -31,11 +33,26 @@
#define HOST_RX TGT_TX #define HOST_RX TGT_TX
#define HOST_TX TGT_RX #define HOST_TX TGT_RX
#define BPS 115200
#define MAX_BUF 10000 /* receive buffer */ #define MAX_BUF 10000 /* receive buffer */
#define MAX_RECORD 45 /* data bytes per uuencoded record */
#define AUTOBAUD_TRIES 10 #define AUTOBAUD_TRIES 10
#define SYNC "Synchronized" #define SYNC "Synchronized"
#define MAX_RECORD 45 /* data bytes per uuencoded record */
/*
* UM 26.4.8 pg 416 says 0x1000017C to 0x1000025B and the last 256+32 bytes
* of the RAM are taken.
*
* UM 26.5.4 pg 418 hints 0x10000300 is a good place.
*/
#define RAM_BUFFER 0x10000300
#define SECTOR 4096
#define PAGE 256
static int verbose = 0; static int verbose = 0;
static int quiet = 0; static int quiet = 0;
@ -170,7 +187,9 @@ static const char *dialog_rc(int idle, const char *cmd, ...)
va_end(ap); va_end(ap);
p = strchr(res, '\n'); p = strchr(res, '\n');
if (!p || sscanf(res, "%u", &rc) != 1) { if (!p)
p = strchr(res, 0);
if (sscanf(res, "%u", &rc) != 1) {
fprintf(stderr, "invalid status\n"); fprintf(stderr, "invalid status\n");
exit(1); exit(1);
} }
@ -257,10 +276,151 @@ static void identify(void)
} }
/* ----- Flash programming ------------------------------------------------- */
static int ms_to_bits(int ms)
{
return (BPS*ms+999)/1000;
}
static char uuechar(uint8_t b)
{
b &= 0x3f;
return b ? b+32 : 0x60;
}
static const char *uuencode(const uint8_t *p, int len)
{
static char buf[80];
char *t = buf;
const uint8_t *end = p+len;
unsigned tmp = 0; /* initialize to prevent compiler complaints */
int i;
*t++ = len+32;
while (p != end) {
for (i = 0; i != 3; i++)
if (p == end)
tmp <<= 8;
else
tmp = tmp << 8 | *p++;
*t++ = uuechar(tmp >> 18);
*t++ = uuechar(tmp >> 12);
*t++ = uuechar(tmp >> 6);
*t++ = uuechar(tmp);
}
*t = 0;
return buf;
}
static void flash_erase_sectors(unsigned addr, unsigned len)
{
unsigned from = addr/SECTOR;
unsigned to = (addr+len-1)/SECTOR;
assert(!(addr & (SECTOR-1)));
assert(!(len & (SECTOR-1)));
dialog_rc(100, "P %d %d", from, to);
/* DS 10.2 pg 77: t_er(max) = 105 ms */
dialog_rc(ms_to_bits(200), "E %d %d", from, to);
}
static void flash_write_page(unsigned addr, const uint8_t *buf)
{
unsigned sector = addr/SECTOR;
unsigned sum;
int chunk, i;
const char *res;
assert(!(addr & (PAGE-1)));
dialog_rc(100, "W %u %u", RAM_BUFFER, PAGE);
for (i = 0; i != PAGE; i += chunk) {
chunk = PAGE-i > MAX_RECORD ? MAX_RECORD : PAGE-i;
dialog(100, "%s", uuencode(buf+i, chunk));
}
sum = 0;
for (i = 0; i != PAGE; i++)
sum += buf[i];
res = dialog(100, "%u", sum);
if (strcmp(res, "OK")) {
fprintf(stderr, "non-OK response: \"%s\"\n", res);
exit(1);
}
dialog_rc(100, "P %d %d", sector, sector);
/* DS 10.2 pg 77: t_prog(max) = 1.05 ms */
dialog_rc(ms_to_bits(2), "C %d %u %d", addr, RAM_BUFFER, PAGE);
}
static void flash_write(unsigned addr, const uint8_t *p, int len,
int erase_all)
{
uint8_t page[PAGE];
assert(!(addr & (PAGE-1)));
dialog_rc(100, "U 23130");
if (erase_all)
flash_erase_sectors(0, device->flash_kb << 10);
else
flash_erase_sectors(addr & ~(SECTOR-1),
(addr+len+SECTOR-1) & ~(SECTOR-1));
while (len > 0) {
if (len < PAGE) {
memcpy(page, p, len);
memset(page+len, 0xff, PAGE-len);
} else {
memcpy(page, p, PAGE);
p += PAGE;
}
flash_write_page(addr, page);
addr += PAGE;
len -= PAGE;
}
}
static void flash_file(FILE *file)
{
uint8_t buf[(device->flash_kb << 10)+1];
size_t got;
got = fread(buf, 1, sizeof(buf), file);
if (!got) {
if (ferror(file))
perror("fread");
else
fprintf(stderr, "file is empty\n");
exit(1);
}
if (got > device->flash_kb << 10) {
fprintf(stderr, "file is larger than flash (%d kB)\n",
device->flash_kb);
exit(1);
}
flash_write(0, buf, got, 1);
}
/* ----- Flash dump -------------------------------------------------------- */ /* ----- Flash dump -------------------------------------------------------- */
/* AN11229 */ /*
* The uuencoding algorithm is described in AN11229.
* It's the same as used by uuencode.
*/
static uint8_t uudchar(char c) static uint8_t uudchar(char c)
@ -388,7 +548,7 @@ static void start_isp(int power)
CLR(TGT_nISP); CLR(TGT_nISP);
OUT(TGT_nISP); OUT(TGT_nISP);
swuart_open(HOST_TX, HOST_RX, 115200); swuart_open(HOST_TX, HOST_RX, BPS);
if (!autobaud()) { if (!autobaud()) {
fprintf(stderr, "target is not responding\n"); fprintf(stderr, "target is not responding\n");
@ -409,7 +569,7 @@ static void start_isp(int power)
static void usage(const char *name) static void usage(const char *name)
{ {
fprintf(stderr, fprintf(stderr,
"usage: %s [-n] [-q] [-v ...]\n\n" "usage: %s [-n] [-q] [-v ...] [file.bin]\n\n"
" -n don't power the device\n" " -n don't power the device\n"
" -q suppress basic progress messages\n" " -q suppress basic progress messages\n"
" -v increase verbosity level\n" " -v increase verbosity level\n"
@ -420,6 +580,7 @@ static void usage(const char *name)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
FILE *file = NULL;
int power = 1; int power = 1;
int c; int c;
@ -441,6 +602,17 @@ int main(int argc, char **argv)
switch (argc-optind) { switch (argc-optind) {
case 0: case 0:
break; break;
case 1:
if (!strcmp(argv[optind], "-"))
file = stdin;
else {
file = fopen(argv[optind], "r");
if (!file) {
perror(argv[optind]);
exit(1);
}
}
break;
default: default:
usage(*argv); usage(*argv);
} }
@ -449,7 +621,10 @@ int main(int argc, char **argv)
identify(); identify();
dump(); if (file)
flash_file(file);
else
dump();
return 0; return 0;
} }