mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 15:41:53 +02:00
lpc111x-isp/lpc111x.c: if file argument is given, flash that file
This commit is contained in:
parent
5246f5fbc6
commit
66d091317a
@ -18,6 +18,8 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ubb/ubb.h>
|
||||
#include <ubb/swuart.h>
|
||||
@ -31,11 +33,26 @@
|
||||
#define HOST_RX TGT_TX
|
||||
#define HOST_TX TGT_RX
|
||||
|
||||
#define BPS 115200
|
||||
|
||||
#define MAX_BUF 10000 /* receive buffer */
|
||||
#define MAX_RECORD 45 /* data bytes per uuencoded record */
|
||||
|
||||
#define AUTOBAUD_TRIES 10
|
||||
#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 quiet = 0;
|
||||
|
||||
@ -170,7 +187,9 @@ static const char *dialog_rc(int idle, const char *cmd, ...)
|
||||
va_end(ap);
|
||||
|
||||
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");
|
||||
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 -------------------------------------------------------- */
|
||||
|
||||
|
||||
/* AN11229 */
|
||||
/*
|
||||
* The uuencoding algorithm is described in AN11229.
|
||||
* It's the same as used by uuencode.
|
||||
*/
|
||||
|
||||
|
||||
static uint8_t uudchar(char c)
|
||||
@ -388,7 +548,7 @@ static void start_isp(int power)
|
||||
CLR(TGT_nISP);
|
||||
OUT(TGT_nISP);
|
||||
|
||||
swuart_open(HOST_TX, HOST_RX, 115200);
|
||||
swuart_open(HOST_TX, HOST_RX, BPS);
|
||||
|
||||
if (!autobaud()) {
|
||||
fprintf(stderr, "target is not responding\n");
|
||||
@ -409,7 +569,7 @@ static void start_isp(int power)
|
||||
static void usage(const char *name)
|
||||
{
|
||||
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"
|
||||
" -q suppress basic progress messages\n"
|
||||
" -v increase verbosity level\n"
|
||||
@ -420,6 +580,7 @@ static void usage(const char *name)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *file = NULL;
|
||||
int power = 1;
|
||||
int c;
|
||||
|
||||
@ -441,6 +602,17 @@ int main(int argc, char **argv)
|
||||
switch (argc-optind) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (!strcmp(argv[optind], "-"))
|
||||
file = stdin;
|
||||
else {
|
||||
file = fopen(argv[optind], "r");
|
||||
if (!file) {
|
||||
perror(argv[optind]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage(*argv);
|
||||
}
|
||||
@ -449,6 +621,9 @@ int main(int argc, char **argv)
|
||||
|
||||
identify();
|
||||
|
||||
if (file)
|
||||
flash_file(file);
|
||||
else
|
||||
dump();
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user