mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 16:05:20 +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 <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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user