commit
229152ff8f
28
Makefile
28
Makefile
@ -7,7 +7,15 @@ CFLAGS=-Wall
|
|||||||
|
|
||||||
OBJS=\
|
OBJS=\
|
||||||
$(OBJDIR)/p1load.o \
|
$(OBJDIR)/p1load.o \
|
||||||
$(OBJDIR)/ploader.o
|
$(OBJDIR)/port.o \
|
||||||
|
$(OBJDIR)/ploader.o \
|
||||||
|
$(OBJDIR)/packet.o
|
||||||
|
|
||||||
|
EEPROM_OBJS=\
|
||||||
|
$(OBJDIR)/eeprom.o \
|
||||||
|
$(OBJDIR)/port.o \
|
||||||
|
$(OBJDIR)/ploader.o \
|
||||||
|
$(OBJDIR)/packet.o
|
||||||
|
|
||||||
OS?=macosx
|
OS?=macosx
|
||||||
|
|
||||||
@ -29,22 +37,22 @@ ifeq ($(OS),raspberrypi)
|
|||||||
OS=linux
|
OS=linux
|
||||||
CFLAGS+=-DLINUX -DRASPBERRY_PI
|
CFLAGS+=-DLINUX -DRASPBERRY_PI
|
||||||
EXT=
|
EXT=
|
||||||
OSINT=osint_linux
|
OSINT=osint_linux.o
|
||||||
LIBS=
|
LIBS=
|
||||||
OBJS+=$(OBJDIR)/gpio_sysfs.o
|
OSINT+=gpio_sysfs.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS),msys)
|
ifeq ($(OS),msys)
|
||||||
CFLAGS+=-DMINGW
|
CFLAGS+=-DMINGW
|
||||||
EXT=.exe
|
EXT=.exe
|
||||||
OSINT=osint_mingw enumcom
|
OSINT=osint_mingw.o enumcom.o
|
||||||
LIBS=-lsetupapi
|
LIBS=-lsetupapi
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OS),macosx)
|
ifeq ($(OS),macosx)
|
||||||
CFLAGS+=-DMACOSX
|
CFLAGS+=-DMACOSX
|
||||||
EXT=
|
EXT=
|
||||||
OSINT=osint_linux
|
OSINT=osint_linux.o
|
||||||
LIBS=
|
LIBS=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -58,22 +66,28 @@ BINDIR=bin/$(OS)
|
|||||||
|
|
||||||
TARGET=$(BINDIR)/p1load$(EXT)
|
TARGET=$(BINDIR)/p1load$(EXT)
|
||||||
|
|
||||||
|
EEPROM_TARGET=$(BINDIR)/eeprom$(EXT)
|
||||||
|
|
||||||
HDRS=\
|
HDRS=\
|
||||||
ploader.h
|
ploader.h
|
||||||
|
|
||||||
OBJS+=$(foreach x, $(OSINT), $(OBJDIR)/$(x).o)
|
OBJS+=$(foreach x, $(OSINT), $(OBJDIR)/$(x))
|
||||||
|
EEPROM_OBJS+=$(foreach x, $(OSINT), $(OBJDIR)/$(x))
|
||||||
|
|
||||||
CFLAGS+=-Wall
|
CFLAGS+=-Wall
|
||||||
LDFLAGS=$(CFLAGS)
|
LDFLAGS=$(CFLAGS)
|
||||||
|
|
||||||
.PHONY: default
|
.PHONY: default
|
||||||
default: $(TARGET)
|
default: $(TARGET) $(EEPROM_TARGET)
|
||||||
|
|
||||||
DIRS=$(OBJDIR) $(BINDIR)
|
DIRS=$(OBJDIR) $(BINDIR)
|
||||||
|
|
||||||
$(TARGET): $(BINDIR) $(OBJDIR) $(OBJS)
|
$(TARGET): $(BINDIR) $(OBJDIR) $(OBJS)
|
||||||
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
||||||
|
|
||||||
|
$(EEPROM_TARGET): $(BINDIR) $(OBJDIR) $(EEPROM_OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $(EEPROM_OBJS) $(LIBS)
|
||||||
|
|
||||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HDRS) $(OBJDIR)
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HDRS) $(OBJDIR)
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
285
eeprom.c
Normal file
285
eeprom.c
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "port.h"
|
||||||
|
#include "ploader.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "osint.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* port prefix */
|
||||||
|
#if defined(CYGWIN) || defined(WIN32) || defined(MINGW)
|
||||||
|
#define PORT_PREFIX ""
|
||||||
|
#elif defined(LINUX)
|
||||||
|
#ifdef RASPBERRY_PI
|
||||||
|
#define PORT_PREFIX "ttyAMA"
|
||||||
|
#else
|
||||||
|
#define PORT_PREFIX "ttyUSB"
|
||||||
|
#endif
|
||||||
|
#elif defined(MACOSX)
|
||||||
|
#define PORT_PREFIX "cu.usbserial-"
|
||||||
|
#else
|
||||||
|
#define PORT_PREFIX ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* defaults */
|
||||||
|
#define BAUD_RATE 115200
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
#define HUB_MEMORY_SIZE 32768
|
||||||
|
|
||||||
|
static PL_state state;
|
||||||
|
|
||||||
|
static void Usage(void);
|
||||||
|
static uint8_t *ReadEntireFile(char *name, long *pSize);
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char actualPort[PATH_MAX], *var, *val, *port, *p;
|
||||||
|
int baudRate, baudRate2, verbose, i;
|
||||||
|
char *file = NULL;
|
||||||
|
long imageSize;
|
||||||
|
uint8_t *image;
|
||||||
|
|
||||||
|
/* initialize */
|
||||||
|
baudRate = baudRate2 = BAUD_RATE;
|
||||||
|
verbose = FALSE;
|
||||||
|
port = NULL;
|
||||||
|
|
||||||
|
/* initialize the loader port */
|
||||||
|
InitPortState(&state);
|
||||||
|
|
||||||
|
/* process the position-independent arguments */
|
||||||
|
for (i = 1; i < argc; ++i) {
|
||||||
|
|
||||||
|
/* handle switches */
|
||||||
|
if (argv[i][0] == '-') {
|
||||||
|
switch (argv[i][1]) {
|
||||||
|
case 'b':
|
||||||
|
if (argv[i][2])
|
||||||
|
p = &argv[i][2];
|
||||||
|
else if (++i < argc)
|
||||||
|
p = argv[i];
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
if (*p != ':')
|
||||||
|
baudRate = baudRate2 = atoi(p);
|
||||||
|
if ((p = strchr(p, ':')) != NULL) {
|
||||||
|
if (*++p != ':' && *p != '\0')
|
||||||
|
baudRate2 = atoi(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
if (argv[i][2])
|
||||||
|
p = &argv[i][2];
|
||||||
|
else if (++i < argc)
|
||||||
|
p = argv[i];
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
if ((var = strtok(p, "=")) != NULL) {
|
||||||
|
if ((val = strtok(NULL, "")) != NULL) {
|
||||||
|
if (strcmp(var, "reset") == 0)
|
||||||
|
use_reset_method(val);
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
if (argv[i][2])
|
||||||
|
port = &argv[i][2];
|
||||||
|
else if (++i < argc)
|
||||||
|
port = argv[i];
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
#if defined(CYGWIN) || defined(WIN32) || defined(LINUX)
|
||||||
|
if (isdigit((int)port[0])) {
|
||||||
|
#if defined(CYGWIN) || defined(WIN32)
|
||||||
|
static char buf[10];
|
||||||
|
sprintf(buf, "COM%d", atoi(port));
|
||||||
|
port = buf;
|
||||||
|
#endif
|
||||||
|
#if defined(LINUX)
|
||||||
|
static char buf[64];
|
||||||
|
sprintf(buf, "/dev/%s%d", PORT_PREFIX, atoi(port));
|
||||||
|
port = buf;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(MACOSX)
|
||||||
|
if (port[0] != '/') {
|
||||||
|
static char buf[64];
|
||||||
|
sprintf(buf, "/dev/%s-%s", PORT_PREFIX, port);
|
||||||
|
port = buf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
ShowPorts(&state, PORT_PREFIX);
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose = TRUE;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
Usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle the input filename */
|
||||||
|
else {
|
||||||
|
if (file)
|
||||||
|
Usage();
|
||||||
|
file = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (InitPort(&state, PORT_PREFIX, port, baudRate, verbose, actualPort)) {
|
||||||
|
case CHECK_PORT_OK:
|
||||||
|
printf("Found propeller version %d on %s\n", state.version, actualPort);
|
||||||
|
break;
|
||||||
|
case CHECK_PORT_OPEN_FAILED:
|
||||||
|
printf("error: opening serial port '%s'\n", port);
|
||||||
|
perror("Error is ");
|
||||||
|
return 1;
|
||||||
|
case CHECK_PORT_NO_PROPELLER:
|
||||||
|
if (port)
|
||||||
|
printf("error: no propeller chip on port '%s'\n", port);
|
||||||
|
else
|
||||||
|
printf("error: can't find a port with a propeller chip\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HELPER "pkt_test.binary"
|
||||||
|
|
||||||
|
/* read the entire file into a buffer */
|
||||||
|
if (!(image = ReadEntireFile(HELPER, &imageSize))) {
|
||||||
|
printf("error: reading '%s'\n", HELPER);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure the file isn't too big for hub memory */
|
||||||
|
if (imageSize > HUB_MEMORY_SIZE) {
|
||||||
|
printf("error: image too big for hub memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load the file from the memory buffer */
|
||||||
|
printf("Loading '%s' (%ld bytes)\n", HELPER, imageSize);
|
||||||
|
switch (PL_LoadSpinBinary(&state, LOAD_TYPE_RUN, image, imageSize)) {
|
||||||
|
case LOAD_STS_OK:
|
||||||
|
printf("OK\n");
|
||||||
|
break;
|
||||||
|
case LOAD_STS_ERROR:
|
||||||
|
printf("Error\n");
|
||||||
|
return 1;
|
||||||
|
case LOAD_STS_TIMEOUT:
|
||||||
|
printf("Timeout\n");
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
printf("Internal error\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
OP_RESULT,
|
||||||
|
OP_ADD,
|
||||||
|
OP_SUB
|
||||||
|
};
|
||||||
|
int32_t type, sts;
|
||||||
|
int32_t buf[2];
|
||||||
|
while (1) {
|
||||||
|
printf("type and two arguments: ");
|
||||||
|
scanf("%d %d %d", &type, &buf[0], &buf[1]);
|
||||||
|
printf("%d %d %d\n", type, buf[0], buf[1]);
|
||||||
|
printf("sizeof(buf) = %lu\n", sizeof(buf));
|
||||||
|
sts = SendPacket(type, (void *)buf, sizeof(buf));
|
||||||
|
printf("SendPacket returned %d\n", sts);
|
||||||
|
if (sts == 0) {
|
||||||
|
sts = ReceivePacket(&type, (void *)buf, sizeof(buf));
|
||||||
|
printf("ReceivePacket returned %d\n", sts);
|
||||||
|
if (sts >= 0)
|
||||||
|
printf("%d %d\n", type, buf[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Usage - display a usage message and exit */
|
||||||
|
static void Usage(void)
|
||||||
|
{
|
||||||
|
printf("\
|
||||||
|
p1load - a simple loader for the propeller - %s, %s\n\
|
||||||
|
usage: p1load\n\
|
||||||
|
[ -b baud ] baud rate (default is %d)\n\
|
||||||
|
[ -D var=val ] set variable value\n\
|
||||||
|
[ -p port ] serial port (default is to auto-detect the port)\n\
|
||||||
|
[ -P ] list available serial ports\n\
|
||||||
|
[ -r addr:len ] read from eeprom\n\
|
||||||
|
[ -v ] verbose output\n\
|
||||||
|
[ -w addr write to eeprom\n\
|
||||||
|
[ -? ] display a usage message and exit\n\
|
||||||
|
file file to load\n", VERSION, __DATE__, BAUD_RATE);
|
||||||
|
#ifdef RASPBERRY_PI
|
||||||
|
printf("\
|
||||||
|
\n\
|
||||||
|
Supports resetting the Propeller with a GPIO pin with option: -Dreset=gpio,pin,level\n\
|
||||||
|
where \"pin\" is the GPIO number to use and \"level\" is the logic level, 0 or 1. This\n\
|
||||||
|
defaults to GPIO 17 and level 0.\n\
|
||||||
|
");
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ReadEntireFile - read an entire file into an allocated buffer */
|
||||||
|
static uint8_t *ReadEntireFile(char *name, long *pSize)
|
||||||
|
{
|
||||||
|
uint8_t *buf;
|
||||||
|
long size;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
/* open the file in binary mode */
|
||||||
|
if (!(fp = fopen(name, "rb")))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* get the file size */
|
||||||
|
fseek(fp, 0L, SEEK_END);
|
||||||
|
size = ftell(fp);
|
||||||
|
fseek(fp, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
/* allocate a buffer for the file contents */
|
||||||
|
if (!(buf = (uint8_t *)malloc(size))) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read the contents of the file into the buffer */
|
||||||
|
if (fread(buf, 1, size, fp) != size) {
|
||||||
|
free(buf);
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close the file ad return the buffer containing the file contents */
|
||||||
|
*pSize = size;
|
||||||
|
fclose(fp);
|
||||||
|
return buf;
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2009 by John Steven Denson
|
* Copyright (c) 2009 by John Steven Denson
|
||||||
* Modified in 2011 by David Michael Betz
|
* Modified in 2011 by David Michael Betz
|
||||||
|
* GPIO reset code by Michael Rychlik
|
||||||
*
|
*
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
@ -88,7 +89,7 @@ int use_reset_method(char* method)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("Using GPIO pin %d as Propeller reset ", propellerResetGpioPin);
|
//printf ("Using GPIO pin %d as Propeller reset ", propellerResetGpioPin);
|
||||||
if (propellerResetGpioLevel)
|
if (propellerResetGpioLevel)
|
||||||
{
|
{
|
||||||
printf ("(HIGH).\n");
|
printf ("(HIGH).\n");
|
||||||
|
240
p1load.c
240
p1load.c
@ -4,6 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include "port.h"
|
||||||
#include "ploader.h"
|
#include "ploader.h"
|
||||||
#include "osint.h"
|
#include "osint.h"
|
||||||
|
|
||||||
@ -28,84 +29,23 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* defaults */
|
/* defaults */
|
||||||
#define BAUD_RATE 115200
|
#define BAUD_RATE 115200
|
||||||
|
|
||||||
/* CheckPort state structure */
|
/* constants */
|
||||||
typedef struct {
|
#define HUB_MEMORY_SIZE 32768
|
||||||
int baud;
|
|
||||||
int verbose;
|
|
||||||
char *actualport;
|
|
||||||
} CheckPortInfo;
|
|
||||||
|
|
||||||
/* CheckPort result codes */
|
|
||||||
enum {
|
|
||||||
CHECK_PORT_OK,
|
|
||||||
CHECK_PORT_OPEN_FAILED,
|
|
||||||
CHECK_PORT_NO_PROPELLER
|
|
||||||
};
|
|
||||||
|
|
||||||
static void cb_reset(void *data)
|
|
||||||
{
|
|
||||||
hwreset();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cb_tx(void *data, uint8_t* buf, int n)
|
|
||||||
{
|
|
||||||
return tx(buf, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cb_rx_timeout(void *data, uint8_t* buf, int n, int timeout)
|
|
||||||
{
|
|
||||||
return rx_timeout(buf, n, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cb_progress(void *data, int phase, int current)
|
|
||||||
{
|
|
||||||
switch (phase) {
|
|
||||||
case LOAD_PHASE_HANDSHAKE:
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_RESPONSE:
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_VERSION:
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_HANDSHAKE_DONE:
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_PROGRAM:
|
|
||||||
printf("\rLoading hub memory ... %d", current);
|
|
||||||
fflush(stdout);
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_EEPROM_WRITE:
|
|
||||||
printf(" -- OK\nWriting EEPROM ... ");
|
|
||||||
fflush(stdout);
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_EEPROM_VERIFY:
|
|
||||||
printf("OK\nVerifying EEPROM ... ");
|
|
||||||
fflush(stdout);
|
|
||||||
break;
|
|
||||||
case LOAD_PHASE_DONE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static PL_state state;
|
static PL_state state;
|
||||||
static int version;
|
|
||||||
|
|
||||||
static void Usage(void);
|
static void Usage(void);
|
||||||
static uint8_t *ReadEntireFile(char *name, long *pSize);
|
static uint8_t *ReadEntireFile(char *name, long *pSize);
|
||||||
static int ShowPort(const char* port, void* data);
|
|
||||||
static void ShowPorts(char *prefix);
|
|
||||||
static int CheckPort(const char* port, void* data);
|
|
||||||
static int InitPort(char *prefix, char *port, int baud, int verbose, char *actualport);
|
|
||||||
static int OpenPort(const char* port, int baud);
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char actualPort[PATH_MAX], *var, *val, *port, *p;
|
char actualPort[PATH_MAX], *var, *val, *port, *p;
|
||||||
int baudRate, baudRate2, verbose, terminalMode, pstMode, i;
|
int baudRate, baudRate2, verbose, terminalMode, pstMode, i;
|
||||||
|
int loadType = LOAD_TYPE_RUN;
|
||||||
|
int loadTypeOptionSeen = FALSE;
|
||||||
char *file = NULL;
|
char *file = NULL;
|
||||||
int loadType = 0;
|
|
||||||
long imageSize;
|
long imageSize;
|
||||||
uint8_t *image;
|
uint8_t *image;
|
||||||
|
|
||||||
@ -114,12 +54,8 @@ int main(int argc, char *argv[])
|
|||||||
verbose = terminalMode = pstMode = FALSE;
|
verbose = terminalMode = pstMode = FALSE;
|
||||||
port = NULL;
|
port = NULL;
|
||||||
|
|
||||||
/* initialize the loader */
|
/* initialize the loader port */
|
||||||
PL_Init(&state);
|
InitPortState(&state);
|
||||||
state.reset = cb_reset;
|
|
||||||
state.tx = cb_tx;
|
|
||||||
state.rx_timeout = cb_rx_timeout;
|
|
||||||
state.progress = cb_progress;
|
|
||||||
|
|
||||||
/* process the position-independent arguments */
|
/* process the position-independent arguments */
|
||||||
for (i = 1; i < argc; ++i) {
|
for (i = 1; i < argc; ++i) {
|
||||||
@ -162,6 +98,10 @@ int main(int argc, char *argv[])
|
|||||||
Usage();
|
Usage();
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
if (!loadTypeOptionSeen) {
|
||||||
|
loadTypeOptionSeen = TRUE;
|
||||||
|
loadType = 0;
|
||||||
|
}
|
||||||
loadType |= LOAD_TYPE_EEPROM;
|
loadType |= LOAD_TYPE_EEPROM;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
@ -194,9 +134,13 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
ShowPorts(PORT_PREFIX);
|
ShowPorts(&state, PORT_PREFIX);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
if (!loadTypeOptionSeen) {
|
||||||
|
loadTypeOptionSeen = TRUE;
|
||||||
|
loadType = 0;
|
||||||
|
}
|
||||||
loadType |= LOAD_TYPE_RUN;
|
loadType |= LOAD_TYPE_RUN;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
@ -224,39 +168,54 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (InitPort(PORT_PREFIX, port, baudRate, verbose, actualPort)) {
|
if (file || terminalMode) {
|
||||||
case CHECK_PORT_OK:
|
switch (InitPort(&state, PORT_PREFIX, port, baudRate, verbose, actualPort)) {
|
||||||
printf("Found propeller version %d on %s\n", version, actualPort);
|
case CHECK_PORT_OK:
|
||||||
break;
|
printf("Found propeller version %d on %s\n", state.version, actualPort);
|
||||||
case CHECK_PORT_OPEN_FAILED:
|
break;
|
||||||
printf("error: opening serial port '%s'\n", port);
|
case CHECK_PORT_OPEN_FAILED:
|
||||||
perror("Error is ");
|
printf("error: opening serial port '%s'\n", port);
|
||||||
return 1;
|
perror("Error is ");
|
||||||
case CHECK_PORT_NO_PROPELLER:
|
return 1;
|
||||||
if (port)
|
case CHECK_PORT_NO_PROPELLER:
|
||||||
printf("error: no propeller chip on port '%s'\n", port);
|
if (port)
|
||||||
else
|
printf("error: no propeller chip on port '%s'\n", port);
|
||||||
printf("error: can't find a port with a propeller chip\n");
|
else
|
||||||
return 1;
|
printf("error: can't find a port with a propeller chip\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for a file to load */
|
||||||
if (file) {
|
if (file) {
|
||||||
if ((image = ReadEntireFile(file, &imageSize)) != NULL) {
|
|
||||||
printf("Loading '%s' (%ld bytes)\n", file, imageSize);
|
/* read the entire file into a buffer */
|
||||||
switch (PL_LoadSpinBinary(&state, loadType, image, imageSize)) {
|
if (!(image = ReadEntireFile(file, &imageSize))) {
|
||||||
case LOAD_STS_OK:
|
printf("error: reading '%s'\n", file);
|
||||||
printf(" -- OK\n");
|
return 1;
|
||||||
break;
|
}
|
||||||
case LOAD_STS_ERROR:
|
|
||||||
printf(" -- Error\n");
|
/* make sure the file isn't too big for hub memory */
|
||||||
break;
|
if (imageSize > HUB_MEMORY_SIZE) {
|
||||||
case LOAD_STS_TIMEOUT:
|
printf("error: image too big for hub memory\n");
|
||||||
printf(" -- Timeout\n");
|
return 1;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
printf(" -- Internal error\n");
|
/* load the file from the memory buffer */
|
||||||
break;
|
printf("Loading '%s' (%ld bytes)\n", file, imageSize);
|
||||||
}
|
switch (PL_LoadSpinBinary(&state, loadType, image, imageSize)) {
|
||||||
|
case LOAD_STS_OK:
|
||||||
|
printf("OK\n");
|
||||||
|
break;
|
||||||
|
case LOAD_STS_ERROR:
|
||||||
|
printf("Error\n");
|
||||||
|
return 1;
|
||||||
|
case LOAD_STS_TIMEOUT:
|
||||||
|
printf("Timeout\n");
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
printf("Internal error\n");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,14 +235,14 @@ int main(int argc, char *argv[])
|
|||||||
static void Usage(void)
|
static void Usage(void)
|
||||||
{
|
{
|
||||||
printf("\
|
printf("\
|
||||||
p1load - a simple loader for the propeller - v%s, %s\n\
|
p1load - a simple loader for the propeller - %s, %s\n\
|
||||||
usage: p1load\n\
|
usage: p1load\n\
|
||||||
[ -b baud ] baud rate (default is %d)\n\
|
[ -b baud ] baud rate (default is %d)\n\
|
||||||
[ -D var=val ] set variable value\n\
|
[ -D var=val ] set variable value\n\
|
||||||
[ -e ] write a bootable image to EEPROM\n\
|
[ -e ] write a bootable image to EEPROM\n\
|
||||||
[ -p port ] serial port (default is to auto-detect the port)\n\
|
[ -p port ] serial port (default is to auto-detect the port)\n\
|
||||||
[ -P ] list available serial ports\n\
|
[ -P ] list available serial ports\n\
|
||||||
[ -r ] run the program after loading\n\
|
[ -r ] run the program after loading (default)\n\
|
||||||
[ -t ] enter terminal mode after running the program\n\
|
[ -t ] enter terminal mode after running the program\n\
|
||||||
[ -T ] enter PST-compatible terminal mode\n\
|
[ -T ] enter PST-compatible terminal mode\n\
|
||||||
[ -v ] verbose output\n\
|
[ -v ] verbose output\n\
|
||||||
@ -293,7 +252,8 @@ usage: p1load\n\
|
|||||||
printf("\
|
printf("\
|
||||||
\n\
|
\n\
|
||||||
This version supports resetting the Propeller with a GPIO pin with option: -Dreset=gpio,pin,level\n\
|
This version supports resetting the Propeller with a GPIO pin with option: -Dreset=gpio,pin,level\n\
|
||||||
where \"pin\" is the GPIO number to use and \"level\" is the logic level, 0 or 1. \n\
|
where \"pin\" is the GPIO number to use and \"level\" is the logic level, 0 or 1. This defaults to\n\
|
||||||
|
GPIO 17 and level 0.\n\
|
||||||
");
|
");
|
||||||
#endif
|
#endif
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -333,69 +293,3 @@ static uint8_t *ReadEntireFile(char *name, long *pSize)
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ShowPort(const char* port, void* data)
|
|
||||||
{
|
|
||||||
printf("%s\n", port);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ShowPorts(char *prefix)
|
|
||||||
{
|
|
||||||
serial_find(prefix, ShowPort, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CheckPort(const char* port, void* data)
|
|
||||||
{
|
|
||||||
CheckPortInfo* info = (CheckPortInfo*)data;
|
|
||||||
int rc;
|
|
||||||
if (info->verbose)
|
|
||||||
printf("Trying %s \n", port); fflush(stdout);
|
|
||||||
if ((rc = OpenPort(port, info->baud)) != CHECK_PORT_OK)
|
|
||||||
return rc;
|
|
||||||
if (info->actualport) {
|
|
||||||
strncpy(info->actualport, port, PATH_MAX - 1);
|
|
||||||
info->actualport[PATH_MAX - 1] = '\0';
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int InitPort(char *prefix, char *port, int baud, int verbose, char *actualport)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (port) {
|
|
||||||
if (actualport) {
|
|
||||||
strncpy(actualport, port, PATH_MAX - 1);
|
|
||||||
actualport[PATH_MAX - 1] = '\0';
|
|
||||||
}
|
|
||||||
result = OpenPort(port, baud);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
CheckPortInfo info;
|
|
||||||
info.baud = baud;
|
|
||||||
info.verbose = verbose;
|
|
||||||
info.actualport = actualport;
|
|
||||||
if (serial_find(prefix, CheckPort, &info) == 0)
|
|
||||||
result = CHECK_PORT_OK;
|
|
||||||
else
|
|
||||||
result = CHECK_PORT_NO_PROPELLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OpenPort(const char* port, int baud)
|
|
||||||
{
|
|
||||||
/* open the port */
|
|
||||||
if (serial_init(port, baud) == 0)
|
|
||||||
return CHECK_PORT_OPEN_FAILED;
|
|
||||||
|
|
||||||
/* check for a propeller on this port */
|
|
||||||
if (PL_HardwareFound(&state, &version) != LOAD_STS_OK) {
|
|
||||||
serial_done();
|
|
||||||
return CHECK_PORT_NO_PROPELLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CHECK_PORT_OK;
|
|
||||||
}
|
|
||||||
|
173
packet.c
Normal file
173
packet.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/* packet.c - an elf and spin binary loader for the Parallax Propeller microcontroller
|
||||||
|
Copyright (c) 2011 David Michael Betz
|
||||||
|
See license at the end of the file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "packet.h"
|
||||||
|
#include "osint.h"
|
||||||
|
|
||||||
|
/* packet format: SOH pkt# type length-lo length-hi hdrchk length*data crc1 crc2 */
|
||||||
|
#define HDR_SOH 0
|
||||||
|
#define HDR_TYPE 1
|
||||||
|
#define HDR_LEN_HI 2
|
||||||
|
#define HDR_LEN_LO 3
|
||||||
|
#define HDR_CHK 4
|
||||||
|
|
||||||
|
/* packet header and crc lengths */
|
||||||
|
#define PKTHDRLEN 5
|
||||||
|
#define PKTCRCLEN 2
|
||||||
|
|
||||||
|
/* maximum length of a frame */
|
||||||
|
#define FRAMELEN (PKTHDRLEN + PKTMAXLEN + PKTCRCLEN)
|
||||||
|
|
||||||
|
/* protocol characters */
|
||||||
|
#define SOH 0x01 /* start of a packet */
|
||||||
|
|
||||||
|
#define updcrc(crc, ch) (crctab[((crc) >> 8) & 0xff] ^ ((crc) << 8) ^ (ch))
|
||||||
|
|
||||||
|
static const uint16_t crctab[256] = {
|
||||||
|
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||||
|
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||||
|
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||||
|
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||||
|
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||||
|
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||||
|
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||||
|
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||||
|
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||||
|
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||||
|
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||||
|
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||||
|
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||||
|
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||||
|
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||||
|
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||||
|
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||||
|
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||||
|
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||||
|
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||||
|
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||||
|
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||||
|
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||||
|
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||||
|
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||||
|
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||||
|
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||||
|
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||||
|
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||||
|
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||||
|
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||||
|
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||||
|
};
|
||||||
|
|
||||||
|
int SendPacket(int type, uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
uint8_t hdr[PKTHDRLEN], crc[PKTCRCLEN], *p;
|
||||||
|
uint16_t crc16 = 0;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
/* setup the frame header */
|
||||||
|
hdr[HDR_SOH] = SOH; /* SOH */
|
||||||
|
hdr[HDR_TYPE] = type; /* type type */
|
||||||
|
hdr[HDR_LEN_HI] = (uint8_t)(len >> 8); /* data length - high byte */
|
||||||
|
hdr[HDR_LEN_LO] = (uint8_t)len; /* data length - low byte */
|
||||||
|
hdr[HDR_CHK] = hdr[1] + hdr[2] + hdr[3]; /* header checksum */
|
||||||
|
printf("tx length %d\n", len);
|
||||||
|
printf("%02x %02x %02x\n", hdr[1], hdr[2], hdr[3]);
|
||||||
|
|
||||||
|
/* compute the crc */
|
||||||
|
for (p = buf, cnt = len; --cnt >= 0; ++p)
|
||||||
|
crc16 = updcrc(crc16, *p);
|
||||||
|
crc16 = updcrc(crc16, '\0');
|
||||||
|
crc16 = updcrc(crc16, '\0');
|
||||||
|
|
||||||
|
/* add the crc to the frame */
|
||||||
|
crc[0] = (uint8_t)(crc16 >> 8);
|
||||||
|
crc[1] = (uint8_t)crc16;
|
||||||
|
|
||||||
|
/* send the packet */
|
||||||
|
tx(hdr, PKTHDRLEN);
|
||||||
|
if (len > 0)
|
||||||
|
tx(buf, len);
|
||||||
|
tx(crc, PKTCRCLEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReceivePacket(int *pType, uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
uint8_t hdr[PKTHDRLEN], crc[PKTCRCLEN];
|
||||||
|
int actual_len, chk;
|
||||||
|
uint16_t crc16 = 0;
|
||||||
|
int retries = 10;
|
||||||
|
printf("Looking for SOH\n");
|
||||||
|
|
||||||
|
/* look for start of packet */
|
||||||
|
do {
|
||||||
|
rx_timeout(&hdr[HDR_SOH], 1, 100);
|
||||||
|
} while (hdr[HDR_SOH] != SOH && --retries >= 0);
|
||||||
|
printf(" retries %d\n", retries);
|
||||||
|
|
||||||
|
/* check for a timeout waiting for the packet */
|
||||||
|
if (retries < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* receive the rest of the header */
|
||||||
|
rx(&hdr[HDR_TYPE], PKTHDRLEN - 1);
|
||||||
|
printf("%02x %02x %02x %02x %02x\n", hdr[0], hdr[1], hdr[2], hdr[3], hdr[4]);
|
||||||
|
|
||||||
|
/* check the header checksum */
|
||||||
|
chk = (hdr[1] + hdr[2] + hdr[3]) & 0xff;
|
||||||
|
if (hdr[HDR_CHK] != chk)
|
||||||
|
return -1;
|
||||||
|
printf("checksum okay\n");
|
||||||
|
|
||||||
|
/* make sure the buffer is big enough for the payload */
|
||||||
|
actual_len = (hdr[HDR_LEN_HI] << 8) | hdr[HDR_LEN_LO];
|
||||||
|
printf("rx length %d\n", actual_len);
|
||||||
|
if (actual_len > len)
|
||||||
|
return -1;
|
||||||
|
printf("length okay\n");
|
||||||
|
|
||||||
|
/* receive the packet payload */
|
||||||
|
rx(buf, actual_len);
|
||||||
|
|
||||||
|
/* compute the crc */
|
||||||
|
for (len = actual_len; --len >= 0; )
|
||||||
|
crc16 = updcrc(crc16, *buf++);
|
||||||
|
|
||||||
|
/* receive the crc */
|
||||||
|
rx(crc, PKTCRCLEN);
|
||||||
|
|
||||||
|
/* check the crc */
|
||||||
|
crc16 = updcrc(crc16, crc[0]);
|
||||||
|
crc16 = updcrc(crc16, crc[1]);
|
||||||
|
if (crc16 != 0)
|
||||||
|
return -1;
|
||||||
|
printf("crc okay\n");
|
||||||
|
|
||||||
|
/* return packet type and the length of the payload */
|
||||||
|
*pType = hdr[HDR_TYPE];
|
||||||
|
return actual_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||||
|
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
32
packet.h
Normal file
32
packet.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* packet.h - an elf and spin binary loader for the Parallax Propeller microcontroller
|
||||||
|
|
||||||
|
Copyright (c) 2011 David Michael Betz
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||||
|
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PACKET_H__
|
||||||
|
#define __PACKET_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PKTMAXLEN 1024
|
||||||
|
|
||||||
|
int SendPacket(int type, uint8_t *buf, int len);
|
||||||
|
int ReceivePacket(int *pType, uint8_t *buf, int len);
|
||||||
|
|
||||||
|
#endif
|
409
packet_driver.spin
Normal file
409
packet_driver.spin
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
''*********************************************
|
||||||
|
''* Bidirectional Packet Driver *
|
||||||
|
''* (C) 2011-2015 David Betz *
|
||||||
|
''* Based on: *
|
||||||
|
''* Full-Duplex Serial Driver v1.1 Extended *
|
||||||
|
''* (C) 2006 Parallax, Inc. *
|
||||||
|
''*********************************************
|
||||||
|
|
||||||
|
CON
|
||||||
|
|
||||||
|
' command codes
|
||||||
|
#0
|
||||||
|
CMD_IDLE ' must be zero
|
||||||
|
CMD_RXPACKET
|
||||||
|
CMD_TXPACKET
|
||||||
|
|
||||||
|
' status codes
|
||||||
|
#0
|
||||||
|
STATUS_OK
|
||||||
|
STATUS_ERROR
|
||||||
|
|
||||||
|
' init offsets
|
||||||
|
#0
|
||||||
|
INIT_MBOX ' zeroed by driver after init is done
|
||||||
|
INIT_RXPIN
|
||||||
|
INIT_TXPIN
|
||||||
|
INIT_BAUDRATE
|
||||||
|
_INIT_SIZE
|
||||||
|
|
||||||
|
' mailbox offsets
|
||||||
|
#0
|
||||||
|
MBOX_CMD
|
||||||
|
MBOX_TYPE ' or pointer to type on rx
|
||||||
|
MBOX_BUFFER
|
||||||
|
MBOX_LENGTH ' or pointer to length on rx
|
||||||
|
MBOX_STATUS
|
||||||
|
MBOX_COG ' not really part of the mailbox
|
||||||
|
_MBOX_SIZE
|
||||||
|
|
||||||
|
' character codes
|
||||||
|
SOH = $01 ' start of a packet
|
||||||
|
|
||||||
|
VAR
|
||||||
|
long mbox[_MBOX_SIZE]
|
||||||
|
|
||||||
|
PUB start(rxpin, txpin, baudrate) | init[_INIT_SIZE], cogn
|
||||||
|
|
||||||
|
'' Start packet driver - starts a cog
|
||||||
|
'' returns zero on success and non-zero if no cog is available
|
||||||
|
''
|
||||||
|
|
||||||
|
' stop the driver if it's already running
|
||||||
|
stop
|
||||||
|
|
||||||
|
' start the driver cog
|
||||||
|
init[INIT_MBOX] := @mbox
|
||||||
|
init[INIT_RXPIN] := rxpin
|
||||||
|
init[INIT_TXPIN] := txpin
|
||||||
|
init[INIT_BAUDRATE] := clkfreq / baudrate
|
||||||
|
cogn := mbox[MBOX_COG] := cognew(@entry, @init) + 1
|
||||||
|
|
||||||
|
' if the cog started okay wait for it to finish initializing
|
||||||
|
if cogn
|
||||||
|
repeat while init[INIT_MBOX] <> 0
|
||||||
|
|
||||||
|
return !cogn
|
||||||
|
|
||||||
|
PUB stop
|
||||||
|
if mbox[MBOX_COG]
|
||||||
|
cogstop(mbox[MBOX_COG]~ - 1)
|
||||||
|
|
||||||
|
PUB rx(ptype, buffer, plength)
|
||||||
|
|
||||||
|
mbox[MBOX_BUFFER] := buffer
|
||||||
|
mbox[MBOX_LENGTH] := long[plength]
|
||||||
|
|
||||||
|
mbox[MBOX_CMD] := CMD_RXPACKET
|
||||||
|
repeat while mbox[MBOX_CMD] <> CMD_IDLE
|
||||||
|
|
||||||
|
long[ptype] := mbox[MBOX_TYPE]
|
||||||
|
long[plength] := mbox[MBOX_LENGTH]
|
||||||
|
|
||||||
|
return mbox[MBOX_STATUS]
|
||||||
|
|
||||||
|
PUB tx(type, buffer, length)
|
||||||
|
|
||||||
|
mbox[MBOX_TYPE] := type
|
||||||
|
mbox[MBOX_BUFFER] := buffer
|
||||||
|
mbox[MBOX_LENGTH] := length
|
||||||
|
|
||||||
|
mbox[MBOX_CMD] := CMD_TXPACKET
|
||||||
|
repeat while mbox[MBOX_CMD] <> CMD_IDLE
|
||||||
|
|
||||||
|
return mbox[MBOX_STATUS]
|
||||||
|
|
||||||
|
DAT
|
||||||
|
|
||||||
|
'***********************************
|
||||||
|
'* Assembly language serial driver *
|
||||||
|
'***********************************
|
||||||
|
|
||||||
|
org
|
||||||
|
'
|
||||||
|
'
|
||||||
|
' Entry
|
||||||
|
'
|
||||||
|
entry mov t1, par 'get init structure address
|
||||||
|
|
||||||
|
rdlong t2, t1 'get the mailbox address
|
||||||
|
mov cmd_ptr, t2 'offset 0 - cmd
|
||||||
|
add t2, #4
|
||||||
|
mov pkt_type_ptr, t2 'offset 1 - type
|
||||||
|
add t2, #4
|
||||||
|
mov pkt_buffer_ptr, t2 'offset 2 - buffer
|
||||||
|
add t2, #4
|
||||||
|
mov pkt_length_ptr, t2 'offset 3 - length
|
||||||
|
add t2, #4
|
||||||
|
mov pkt_status_ptr, t2 'offset 4 - status
|
||||||
|
|
||||||
|
add t1, #4 'get rx_pin
|
||||||
|
rdlong t2, t1
|
||||||
|
mov rxmask, #1
|
||||||
|
shl rxmask, t2
|
||||||
|
|
||||||
|
add t1, #4 'get tx_pin
|
||||||
|
rdlong t2, t1
|
||||||
|
mov txmask, #1
|
||||||
|
shl txmask, t2
|
||||||
|
|
||||||
|
add t1, #4 'get bit_ticks
|
||||||
|
rdlong bitticks, t1
|
||||||
|
|
||||||
|
or outa, txmask 'initialize the tx pin
|
||||||
|
or dira, txmask
|
||||||
|
andn dira, rxmask 'initialize the rx pin
|
||||||
|
|
||||||
|
rdlong t1, #0
|
||||||
|
add t1, cnt
|
||||||
|
waitcnt t1, #0
|
||||||
|
|
||||||
|
mov t1, #CMD_IDLE 'no command in progress
|
||||||
|
wrlong t1, cmd_ptr
|
||||||
|
|
||||||
|
mov t1, #0 'signal end of initialization
|
||||||
|
wrlong t1, par
|
||||||
|
|
||||||
|
next_cmd mov t1, #CMD_IDLE 'no command in progress
|
||||||
|
wrlong t1, cmd_ptr
|
||||||
|
:wait rdlong t1, cmd_ptr wz 'wait for a command
|
||||||
|
if_z jmp #:wait
|
||||||
|
add t1, #dispatch
|
||||||
|
jmp t1
|
||||||
|
|
||||||
|
dispatch jmp #next_cmd 'should never happen
|
||||||
|
jmp #do_rxpacket
|
||||||
|
jmp #do_txpacket
|
||||||
|
|
||||||
|
' receive a packet
|
||||||
|
do_rxpacket rdlong rcv_ptr, pkt_buffer_ptr
|
||||||
|
rdlong t1, pkt_length_ptr
|
||||||
|
rdlong rcv_max, t1
|
||||||
|
call #rxpacket
|
||||||
|
if_c wrlong ok_status, pkt_status_ptr
|
||||||
|
if_c wrlong rcv_type, pkt_type_ptr
|
||||||
|
if_c wrlong rcv_length, pkt_length_ptr
|
||||||
|
if_nc wrlong error_status, pkt_status_ptr
|
||||||
|
jmp #next_cmd
|
||||||
|
|
||||||
|
' send a packet
|
||||||
|
do_txpacket rdlong xmt_type, pkt_type_ptr
|
||||||
|
rdlong xmt_ptr, pkt_buffer_ptr
|
||||||
|
rdlong xmt_length, pkt_length_ptr
|
||||||
|
call #txpacket
|
||||||
|
if_c wrlong ok_status, pkt_status_ptr
|
||||||
|
if_nc wrlong error_status, pkt_status_ptr
|
||||||
|
jmp #next_cmd
|
||||||
|
|
||||||
|
ok_status long STATUS_OK
|
||||||
|
error_status long STATUS_ERROR
|
||||||
|
|
||||||
|
' receive a packet
|
||||||
|
' input:
|
||||||
|
' rcv_ptr points to the receive buffer
|
||||||
|
' rcv_max is the maximum number of bytes to receive
|
||||||
|
' output:
|
||||||
|
' rcv_type is the packet type
|
||||||
|
' rcv_length is the length of the packet received
|
||||||
|
' C is set on return if the packet was received successfully
|
||||||
|
' C is clear on return if there was an error
|
||||||
|
rxpacket call #rxbyte
|
||||||
|
cmp rxdata, #SOH wz
|
||||||
|
if_nz jmp #rxpacket
|
||||||
|
call #rxbyte ' receive packet type
|
||||||
|
mov rcv_type, rxdata
|
||||||
|
mov rcv_chk, rxdata
|
||||||
|
call #rxbyte ' receive hi byte of packet length
|
||||||
|
mov rcv_length, rxdata
|
||||||
|
shl rcv_length, #8
|
||||||
|
add rcv_chk, rxdata
|
||||||
|
call #rxbyte ' receive lo byte of packet length
|
||||||
|
or rcv_length, rxdata
|
||||||
|
add rcv_chk, rxdata
|
||||||
|
call #rxbyte ' receive header checksum
|
||||||
|
and rcv_chk, #$ff
|
||||||
|
cmp rxdata, rcv_chk wz
|
||||||
|
if_nz jmp #rxerror
|
||||||
|
cmp rcv_length, rcv_max wz, wc
|
||||||
|
if_a jmp #rxerror
|
||||||
|
mov crc, #0
|
||||||
|
mov rcv_cnt, rcv_length wz
|
||||||
|
if_z jmp #:crc
|
||||||
|
:next call #rxbyte ' receive the next data byte
|
||||||
|
mov crcdata, rxdata
|
||||||
|
call #updcrc ' update the crc
|
||||||
|
wrbyte rxdata, rcv_ptr
|
||||||
|
add rcv_ptr, #1
|
||||||
|
djnz rcv_cnt, #:next
|
||||||
|
:crc call #rxbyte
|
||||||
|
mov crcdata, rxdata
|
||||||
|
call #updcrc ' update the crc
|
||||||
|
call #rxbyte
|
||||||
|
mov crcdata, rxdata
|
||||||
|
call #updcrc ' update the crc
|
||||||
|
cmp crc, #0 wz ' check the crc
|
||||||
|
if_nz jmp #rxerror
|
||||||
|
test $, #1 wc ' set c to indicate success
|
||||||
|
rxpacket_ret ret
|
||||||
|
|
||||||
|
rxerror test $, #0 wc ' clear c to indicate failure
|
||||||
|
jmp rxpacket_ret
|
||||||
|
|
||||||
|
' transmit a packet
|
||||||
|
' input:
|
||||||
|
' xmt_type is the packet type
|
||||||
|
' xmt_ptr points to the packet data
|
||||||
|
' xmt_length is the number of bytes of data
|
||||||
|
' output:
|
||||||
|
' C is set on return if the packet was received successfully
|
||||||
|
' C is clear on return if there was an error
|
||||||
|
txpacket mov txdata, #SOH
|
||||||
|
call #txbyte
|
||||||
|
mov txdata, xmt_type
|
||||||
|
mov xmt_chk, txdata
|
||||||
|
call #txbyte
|
||||||
|
mov txdata, xmt_length
|
||||||
|
shr txdata, #8
|
||||||
|
add xmt_chk, txdata
|
||||||
|
call #txbyte
|
||||||
|
mov txdata, xmt_length
|
||||||
|
and txdata, #$ff
|
||||||
|
add xmt_chk, txdata
|
||||||
|
call #txbyte
|
||||||
|
mov txdata, xmt_chk
|
||||||
|
and txdata, #$ff
|
||||||
|
call #txbyte
|
||||||
|
mov crc, #0
|
||||||
|
mov xmt_cnt, xmt_length wz
|
||||||
|
if_z jmp #:crc
|
||||||
|
:next rdbyte txdata, xmt_ptr
|
||||||
|
add xmt_ptr, #1
|
||||||
|
mov crcdata, txdata
|
||||||
|
call #updcrc
|
||||||
|
call #txbyte
|
||||||
|
djnz xmt_cnt, #:next
|
||||||
|
:crc mov crcdata, #0
|
||||||
|
call #updcrc
|
||||||
|
call #updcrc
|
||||||
|
mov txdata, crc
|
||||||
|
shr txdata, #8
|
||||||
|
call #txbyte
|
||||||
|
mov txdata, crc
|
||||||
|
and txdata, #$ff
|
||||||
|
call #txbyte
|
||||||
|
test $, #1 wc ' set c to indicate success
|
||||||
|
txpacket_ret ret
|
||||||
|
|
||||||
|
' receive a byte
|
||||||
|
' output:
|
||||||
|
' rxdata is the byte received
|
||||||
|
rxbyte waitpne rxmask, rxmask ' wait for a start bit
|
||||||
|
mov rxcnt, bitticks ' wait until half way through the bit time
|
||||||
|
shr rxcnt, #1
|
||||||
|
add rxcnt, bitticks
|
||||||
|
add rxcnt, cnt
|
||||||
|
mov rxbits, #9 ' receive 8 data bits and the stop bit
|
||||||
|
:next waitcnt rxcnt, bitticks ' wait until the center of the next bit
|
||||||
|
test rxmask, ina wc ' sample the rx pin
|
||||||
|
rcr rxdata, #1 ' add to the byte being received
|
||||||
|
djnz rxbits, #:next
|
||||||
|
shr rxdata, #32-9 ' shift the received data to the low bits
|
||||||
|
and rxdata, #$ff ' mask off the stop bit
|
||||||
|
waitpeq rxmask, rxmask ' wait for the end of the stop bit
|
||||||
|
rxbyte_ret ret
|
||||||
|
|
||||||
|
' transmit a byte
|
||||||
|
' input:
|
||||||
|
' txdata is the byte to send (destroyed on return)
|
||||||
|
txbyte or txdata, #$100 ' or in a stop bit
|
||||||
|
shl txdata, #1 ' shift in a start bit
|
||||||
|
mov txcnt, cnt
|
||||||
|
add txcnt, bitticks
|
||||||
|
mov txbits, #10
|
||||||
|
:next shr txdata, #1 wc
|
||||||
|
muxc outa, txmask
|
||||||
|
waitcnt txcnt, bitticks
|
||||||
|
djnz txbits, #:next
|
||||||
|
waitcnt txcnt, bitticks
|
||||||
|
txbyte_ret ret
|
||||||
|
|
||||||
|
bitticks long 0
|
||||||
|
rxmask long 0
|
||||||
|
rxdata long 0
|
||||||
|
rxbits long 0
|
||||||
|
rxcnt long 0
|
||||||
|
txmask long 0
|
||||||
|
txdata long 0
|
||||||
|
txbits long 0
|
||||||
|
txcnt long 0
|
||||||
|
|
||||||
|
' update the crc
|
||||||
|
' input:
|
||||||
|
' crc the current crc
|
||||||
|
' crcdata the data to add to the crc
|
||||||
|
' output:
|
||||||
|
' crc the updated crc
|
||||||
|
updcrc mov t1, crc
|
||||||
|
test t1, #$100 wz
|
||||||
|
shr t1, #9
|
||||||
|
add t1, #crctab
|
||||||
|
movs :load, t1
|
||||||
|
shl crc, #8
|
||||||
|
:load mov t1, 0-0
|
||||||
|
if_nz shr t1, #16
|
||||||
|
xor crc, t1
|
||||||
|
xor crc, crcdata
|
||||||
|
and crc, word_mask
|
||||||
|
updcrc_ret ret
|
||||||
|
|
||||||
|
crc long 0
|
||||||
|
crcdata long 0
|
||||||
|
|
||||||
|
'
|
||||||
|
'
|
||||||
|
' Initialized data
|
||||||
|
'
|
||||||
|
'
|
||||||
|
zero long 0
|
||||||
|
word_mask long $ffff
|
||||||
|
|
||||||
|
crctab
|
||||||
|
word $0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7
|
||||||
|
word $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef
|
||||||
|
word $1231, $0210, $3273, $2252, $52b5, $4294, $72f7, $62d6
|
||||||
|
word $9339, $8318, $b37b, $a35a, $d3bd, $c39c, $f3ff, $e3de
|
||||||
|
word $2462, $3443, $0420, $1401, $64e6, $74c7, $44a4, $5485
|
||||||
|
word $a56a, $b54b, $8528, $9509, $e5ee, $f5cf, $c5ac, $d58d
|
||||||
|
word $3653, $2672, $1611, $0630, $76d7, $66f6, $5695, $46b4
|
||||||
|
word $b75b, $a77a, $9719, $8738, $f7df, $e7fe, $d79d, $c7bc
|
||||||
|
word $48c4, $58e5, $6886, $78a7, $0840, $1861, $2802, $3823
|
||||||
|
word $c9cc, $d9ed, $e98e, $f9af, $8948, $9969, $a90a, $b92b
|
||||||
|
word $5af5, $4ad4, $7ab7, $6a96, $1a71, $0a50, $3a33, $2a12
|
||||||
|
word $dbfd, $cbdc, $fbbf, $eb9e, $9b79, $8b58, $bb3b, $ab1a
|
||||||
|
word $6ca6, $7c87, $4ce4, $5cc5, $2c22, $3c03, $0c60, $1c41
|
||||||
|
word $edae, $fd8f, $cdec, $ddcd, $ad2a, $bd0b, $8d68, $9d49
|
||||||
|
word $7e97, $6eb6, $5ed5, $4ef4, $3e13, $2e32, $1e51, $0e70
|
||||||
|
word $ff9f, $efbe, $dfdd, $cffc, $bf1b, $af3a, $9f59, $8f78
|
||||||
|
word $9188, $81a9, $b1ca, $a1eb, $d10c, $c12d, $f14e, $e16f
|
||||||
|
word $1080, $00a1, $30c2, $20e3, $5004, $4025, $7046, $6067
|
||||||
|
word $83b9, $9398, $a3fb, $b3da, $c33d, $d31c, $e37f, $f35e
|
||||||
|
word $02b1, $1290, $22f3, $32d2, $4235, $5214, $6277, $7256
|
||||||
|
word $b5ea, $a5cb, $95a8, $8589, $f56e, $e54f, $d52c, $c50d
|
||||||
|
word $34e2, $24c3, $14a0, $0481, $7466, $6447, $5424, $4405
|
||||||
|
word $a7db, $b7fa, $8799, $97b8, $e75f, $f77e, $c71d, $d73c
|
||||||
|
word $26d3, $36f2, $0691, $16b0, $6657, $7676, $4615, $5634
|
||||||
|
word $d94c, $c96d, $f90e, $e92f, $99c8, $89e9, $b98a, $a9ab
|
||||||
|
word $5844, $4865, $7806, $6827, $18c0, $08e1, $3882, $28a3
|
||||||
|
word $cb7d, $db5c, $eb3f, $fb1e, $8bf9, $9bd8, $abbb, $bb9a
|
||||||
|
word $4a75, $5a54, $6a37, $7a16, $0af1, $1ad0, $2ab3, $3a92
|
||||||
|
word $fd2e, $ed0f, $dd6c, $cd4d, $bdaa, $ad8b, $9de8, $8dc9
|
||||||
|
word $7c26, $6c07, $5c64, $4c45, $3ca2, $2c83, $1ce0, $0cc1
|
||||||
|
word $ef1f, $ff3e, $cf5d, $df7c, $af9b, $bfba, $8fd9, $9ff8
|
||||||
|
word $6e17, $7e36, $4e55, $5e74, $2e93, $3eb2, $0ed1, $1ef0
|
||||||
|
|
||||||
|
'
|
||||||
|
' Uninitialized data
|
||||||
|
'
|
||||||
|
t1 res 1
|
||||||
|
t2 res 1
|
||||||
|
|
||||||
|
xmt_type res 1
|
||||||
|
xmt_length res 1
|
||||||
|
xmt_chk res 1
|
||||||
|
xmt_ptr res 1
|
||||||
|
xmt_cnt res 1
|
||||||
|
|
||||||
|
rcv_type res 1
|
||||||
|
rcv_length res 1 'packet length
|
||||||
|
rcv_chk res 1 'header checksum
|
||||||
|
rcv_max res 1 'maximum packet data length
|
||||||
|
rcv_ptr res 1 'data buffer pointer
|
||||||
|
rcv_cnt res 1 'data buffer count
|
||||||
|
|
||||||
|
cmd_ptr res 1
|
||||||
|
pkt_type_ptr res 1
|
||||||
|
pkt_buffer_ptr res 1
|
||||||
|
pkt_length_ptr res 1
|
||||||
|
pkt_status_ptr res 1
|
||||||
|
|
||||||
|
fit 496
|
29
ploader.c
29
ploader.c
@ -41,26 +41,20 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
|
|||||||
{
|
{
|
||||||
int i, sts;
|
int i, sts;
|
||||||
|
|
||||||
|
/* report the start of program loading */
|
||||||
|
if (state->progress)
|
||||||
|
(*state->progress)(state->progressData, LOAD_PHASE_PROGRAM);
|
||||||
|
|
||||||
TLong(state, loadType);
|
TLong(state, loadType);
|
||||||
TLong(state, size / sizeof(uint32_t));
|
TLong(state, size / sizeof(uint32_t));
|
||||||
|
|
||||||
/* download the spin binary */
|
/* download the spin binary */
|
||||||
for (i = 0; i < size; i += 4) {
|
for (i = 0; i < size; i += 4) {
|
||||||
|
|
||||||
/* report load progress */
|
|
||||||
if (state->progress && (i % 1024) == 0)
|
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_PROGRAM, i);
|
|
||||||
|
|
||||||
/* transmit the next long */
|
|
||||||
uint32_t data = image[i] | (image[i + 1] << 8) | (image[i + 2] << 16) | (image[i + 3] << 24);
|
uint32_t data = image[i] | (image[i + 1] << 8) | (image[i + 2] << 16) | (image[i + 3] << 24);
|
||||||
TLong(state, data);
|
TLong(state, data);
|
||||||
}
|
}
|
||||||
TComm(state);
|
TComm(state);
|
||||||
|
|
||||||
/* report load of program code finished */
|
|
||||||
if (state->progress)
|
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_PROGRAM, size);
|
|
||||||
|
|
||||||
/* wait for an ACK indicating a successful load */
|
/* wait for an ACK indicating a successful load */
|
||||||
if ((sts = WaitForAck(state, CHECKSUM_RETRIES)) < 0)
|
if ((sts = WaitForAck(state, CHECKSUM_RETRIES)) < 0)
|
||||||
return LOAD_STS_TIMEOUT;
|
return LOAD_STS_TIMEOUT;
|
||||||
@ -72,7 +66,7 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
|
|||||||
|
|
||||||
/* report the start of the eeprom writing phase */
|
/* report the start of the eeprom writing phase */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_EEPROM_WRITE, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_EEPROM_WRITE);
|
||||||
|
|
||||||
/* wait for an ACK indicating a successful EEPROM programming */
|
/* wait for an ACK indicating a successful EEPROM programming */
|
||||||
if ((sts = WaitForAck(state, EEPROM_PROGRAMMING_RETRIES)) < 0)
|
if ((sts = WaitForAck(state, EEPROM_PROGRAMMING_RETRIES)) < 0)
|
||||||
@ -82,7 +76,7 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
|
|||||||
|
|
||||||
/* report the start of the eeprom verification phase */
|
/* report the start of the eeprom verification phase */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_EEPROM_VERIFY, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_EEPROM_VERIFY);
|
||||||
|
|
||||||
/* wait for an ACK indicating a successful EEPROM verification */
|
/* wait for an ACK indicating a successful EEPROM verification */
|
||||||
if ((sts = WaitForAck(state, EEPROM_VERIFICATION_RETRIES)) < 0)
|
if ((sts = WaitForAck(state, EEPROM_VERIFICATION_RETRIES)) < 0)
|
||||||
@ -93,7 +87,7 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
|
|||||||
|
|
||||||
/* report load completion */
|
/* report load completion */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_DONE, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_DONE);
|
||||||
|
|
||||||
/* load completed successfully */
|
/* load completed successfully */
|
||||||
return LOAD_STS_OK;
|
return LOAD_STS_OK;
|
||||||
@ -103,6 +97,7 @@ static int WaitForAck(PL_state *state, int retries)
|
|||||||
{
|
{
|
||||||
uint8_t buf[1];
|
uint8_t buf[1];
|
||||||
while (--retries >= 0) {
|
while (--retries >= 0) {
|
||||||
|
(*state->msleep)(state->serialData, 20);
|
||||||
TByte(state, 0xf9);
|
TByte(state, 0xf9);
|
||||||
TComm(state);
|
TComm(state);
|
||||||
if ((*state->rx_timeout)(state->serialData, buf, 1, ACK_TIMEOUT) > 0)
|
if ((*state->rx_timeout)(state->serialData, buf, 1, ACK_TIMEOUT) > 0)
|
||||||
@ -122,7 +117,7 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
|
|||||||
|
|
||||||
/* report the start of the handshake phase */
|
/* report the start of the handshake phase */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_HANDSHAKE, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_HANDSHAKE);
|
||||||
|
|
||||||
/* reset the propeller (includes post-reset delay of 100ms) */
|
/* reset the propeller (includes post-reset delay of 100ms) */
|
||||||
(*state->reset)(state->serialData);
|
(*state->reset)(state->serialData);
|
||||||
@ -144,7 +139,7 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
|
|||||||
|
|
||||||
/* report the start of the handshake response phase */
|
/* report the start of the handshake response phase */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_RESPONSE, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_RESPONSE);
|
||||||
|
|
||||||
/* receive the connection response */
|
/* receive the connection response */
|
||||||
for (i = 0; i < 250; ++i) {
|
for (i = 0; i < 250; ++i) {
|
||||||
@ -157,7 +152,7 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
|
|||||||
|
|
||||||
/* report the start of the version phase */
|
/* report the start of the version phase */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_VERSION, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_VERSION);
|
||||||
|
|
||||||
/* receive the chip version */
|
/* receive the chip version */
|
||||||
for (version = i = 0; i < 8; ++i) {
|
for (version = i = 0; i < 8; ++i) {
|
||||||
@ -170,7 +165,7 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
|
|||||||
|
|
||||||
/* report handshake completion */
|
/* report handshake completion */
|
||||||
if (state->progress)
|
if (state->progress)
|
||||||
(*state->progress)(state->progressData, LOAD_PHASE_HANDSHAKE_DONE, 0);
|
(*state->progress)(state->progressData, LOAD_PHASE_HANDSHAKE_DONE);
|
||||||
|
|
||||||
/* return successfully */
|
/* return successfully */
|
||||||
return LOAD_STS_OK;
|
return LOAD_STS_OK;
|
||||||
|
22
ploader.h
22
ploader.h
@ -26,6 +26,18 @@ extern "C"
|
|||||||
#define LOAD_TYPE_EEPROM 2
|
#define LOAD_TYPE_EEPROM 2
|
||||||
#define LOAD_TYPE_EEPROM_RUN 3
|
#define LOAD_TYPE_EEPROM_RUN 3
|
||||||
|
|
||||||
|
/* constants taken from the Propeller Tool loader */
|
||||||
|
#define BaudRate 115200 // Likely Baud rate of Propeller communication
|
||||||
|
#define ResetPulsePeriod 25 // Reset pulse size (in ms)
|
||||||
|
#define MinResetDelay 60 // Minimum post-reset delay
|
||||||
|
#define MaxResetDelay 500 // Maximum post-reset delay
|
||||||
|
|
||||||
|
/* Transmit buffer size is 32K / 4 = 8K longs * 11 bytes per long plus two longs for the command and size */
|
||||||
|
#define TxBufSize ((((1024 * 32) / 4) + 2) * 11)
|
||||||
|
|
||||||
|
/* Receive buffer is large enough to receive max possible bytes during reset + 250 bytes for handshake response */
|
||||||
|
#define RxBufSize (((BaudRate / 10 * (ResetPulsePeriod + MaxResetDelay) / 1000) & 0xFFFFFFFE) + 258)
|
||||||
|
|
||||||
/* loader state structure - filled in by the loader functions */
|
/* loader state structure - filled in by the loader functions */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
@ -33,16 +45,20 @@ typedef struct {
|
|||||||
void (*reset)(void *data);
|
void (*reset)(void *data);
|
||||||
int (*tx)(void *data, uint8_t* buf, int n);
|
int (*tx)(void *data, uint8_t* buf, int n);
|
||||||
int (*rx_timeout)(void *data, uint8_t* buf, int n, int timeout);
|
int (*rx_timeout)(void *data, uint8_t* buf, int n, int timeout);
|
||||||
|
void (*msleep)(void *data, int msecs);
|
||||||
void *serialData;
|
void *serialData;
|
||||||
|
|
||||||
|
/* propeller version */
|
||||||
|
int version;
|
||||||
|
|
||||||
/* load progress interface */
|
/* load progress interface */
|
||||||
void (*progress)(void *data, int phase, int current);
|
void (*progress)(void *data, int phase);
|
||||||
void *progressData;
|
void *progressData;
|
||||||
|
|
||||||
/* internal variables */
|
/* internal variables */
|
||||||
uint8_t txbuf[1024];
|
uint8_t txbuf[TxBufSize];
|
||||||
int txcnt;
|
int txcnt;
|
||||||
uint8_t rxbuf[1024];
|
uint8_t rxbuf[RxBufSize];
|
||||||
int rxnext;
|
int rxnext;
|
||||||
int rxcnt;
|
int rxcnt;
|
||||||
uint8_t lfsr;
|
uint8_t lfsr;
|
||||||
|
160
port.c
Normal file
160
port.c
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "port.h"
|
||||||
|
#include "ploader.h"
|
||||||
|
#include "osint.h"
|
||||||
|
|
||||||
|
/* CheckPort state structure */
|
||||||
|
typedef struct {
|
||||||
|
PL_state *state;
|
||||||
|
int baud;
|
||||||
|
int verbose;
|
||||||
|
char *actualport;
|
||||||
|
} CheckPortInfo;
|
||||||
|
|
||||||
|
void ShowPorts(PL_state *state, char *prefix);
|
||||||
|
int InitPort(PL_state *state, char *prefix, char *port, int baud, int verbose, char *actualport);
|
||||||
|
|
||||||
|
static int ShowPort(const char *port, void *data);
|
||||||
|
static int CheckPort(const char *port, void *data);
|
||||||
|
static int OpenPort(PL_state *state, const char *port, int baud);
|
||||||
|
static void cb_reset(void *data);
|
||||||
|
static int cb_tx(void *data, uint8_t* buf, int n);
|
||||||
|
static int cb_rx_timeout(void *data, uint8_t* buf, int n, int timeout);
|
||||||
|
static void cb_msleep(void *data, int msecs);
|
||||||
|
static void cb_progress(void *data, int phase);
|
||||||
|
|
||||||
|
void InitPortState(PL_state *state)
|
||||||
|
{
|
||||||
|
PL_Init(state);
|
||||||
|
state->reset = cb_reset;
|
||||||
|
state->tx = cb_tx;
|
||||||
|
state->rx_timeout = cb_rx_timeout;
|
||||||
|
state->progress = cb_progress;
|
||||||
|
state->msleep = cb_msleep;
|
||||||
|
#ifdef RASPBERRY_PI
|
||||||
|
{
|
||||||
|
char cmd[20] = "gpio,17,0";
|
||||||
|
// use_reset_method uses strtok to parse the string so it can't be a constant
|
||||||
|
use_reset_method(cmd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowPorts(PL_state *state, char *prefix)
|
||||||
|
{
|
||||||
|
serial_find(prefix, ShowPort, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InitPort(PL_state *state, char *prefix, char *port, int baud, int verbose, char *actualport)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (port) {
|
||||||
|
if (actualport) {
|
||||||
|
strncpy(actualport, port, PATH_MAX - 1);
|
||||||
|
actualport[PATH_MAX - 1] = '\0';
|
||||||
|
}
|
||||||
|
result = OpenPort(state, port, baud);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CheckPortInfo info;
|
||||||
|
info.state = state;
|
||||||
|
info.baud = baud;
|
||||||
|
info.verbose = verbose;
|
||||||
|
info.actualport = actualport;
|
||||||
|
if (serial_find(prefix, CheckPort, &info) == 0)
|
||||||
|
result = CHECK_PORT_OK;
|
||||||
|
else
|
||||||
|
result = CHECK_PORT_NO_PROPELLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ShowPort(const char *port, void *data)
|
||||||
|
{
|
||||||
|
printf("%s\n", port);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CheckPort(const char *port, void *data)
|
||||||
|
{
|
||||||
|
CheckPortInfo *info = (CheckPortInfo*)data;
|
||||||
|
int rc;
|
||||||
|
if (info->verbose)
|
||||||
|
printf("Trying %s \n", port); fflush(stdout);
|
||||||
|
if ((rc = OpenPort(info->state, port, info->baud)) != CHECK_PORT_OK)
|
||||||
|
return rc;
|
||||||
|
if (info->actualport) {
|
||||||
|
strncpy(info->actualport, port, PATH_MAX - 1);
|
||||||
|
info->actualport[PATH_MAX - 1] = '\0';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OpenPort(PL_state *state, const char *port, int baud)
|
||||||
|
{
|
||||||
|
/* open the port */
|
||||||
|
if (serial_init(port, baud) == 0)
|
||||||
|
return CHECK_PORT_OPEN_FAILED;
|
||||||
|
|
||||||
|
/* check for a propeller on this port */
|
||||||
|
if (PL_HardwareFound(state, &state->version) != LOAD_STS_OK) {
|
||||||
|
serial_done();
|
||||||
|
return CHECK_PORT_NO_PROPELLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CHECK_PORT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_reset(void *data)
|
||||||
|
{
|
||||||
|
hwreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_tx(void *data, uint8_t* buf, int n)
|
||||||
|
{
|
||||||
|
return tx(buf, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cb_rx_timeout(void *data, uint8_t* buf, int n, int timeout)
|
||||||
|
{
|
||||||
|
return rx_timeout(buf, n, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_msleep(void *data, int msecs)
|
||||||
|
{
|
||||||
|
msleep(msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_progress(void *data, int phase)
|
||||||
|
{
|
||||||
|
switch (phase) {
|
||||||
|
case LOAD_PHASE_HANDSHAKE:
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_RESPONSE:
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_VERSION:
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_HANDSHAKE_DONE:
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_PROGRAM:
|
||||||
|
printf("Loading hub memory ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_EEPROM_WRITE:
|
||||||
|
printf("OK\nWriting EEPROM ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_EEPROM_VERIFY:
|
||||||
|
printf("OK\nVerifying EEPROM ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
break;
|
||||||
|
case LOAD_PHASE_DONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
18
port.h
Normal file
18
port.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef __PORT_H__
|
||||||
|
#define __PORT_H__
|
||||||
|
|
||||||
|
#include "ploader.h"
|
||||||
|
|
||||||
|
/* CheckPort result codes */
|
||||||
|
enum {
|
||||||
|
CHECK_PORT_OK,
|
||||||
|
CHECK_PORT_OPEN_FAILED,
|
||||||
|
CHECK_PORT_NO_PROPELLER
|
||||||
|
};
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
void InitPortState(PL_state *state);
|
||||||
|
void ShowPorts(PL_state *state, char *prefix);
|
||||||
|
int InitPort(PL_state *state, char *prefix, char *port, int baud, int verbose, char *actualport);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user