Add callbacks for load phases to get rid of the use of printf in ploader.c.
This commit is contained in:
parent
082e1636a8
commit
cfec83ceb6
55
p1load.c
55
p1load.c
@ -59,7 +59,37 @@ static int cb_rx_timeout(void *data, uint8_t* buf, int n, int timeout)
|
||||
return rx_timeout(buf, n, timeout);
|
||||
}
|
||||
|
||||
static PL_serial serial = { cb_reset, cb_tx, cb_rx_timeout };
|
||||
static void cb_progress(void *data, int phase, int current, int total)
|
||||
{
|
||||
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("\rLoading hub memory ... OK \nWriting EEPROM ... ");
|
||||
fflush(stdout);
|
||||
break;
|
||||
case LOAD_PHASE_EEPROM_VERIFY:
|
||||
printf("OK\nVerifying EEPROM ... ");
|
||||
fflush(stdout);
|
||||
break;
|
||||
case LOAD_PHASE_DONE:
|
||||
printf("OK\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static PL_state state;
|
||||
static int version;
|
||||
|
||||
@ -86,7 +116,11 @@ int main(int argc, char *argv[])
|
||||
port = NULL;
|
||||
|
||||
/* initialize the loader */
|
||||
PL_Init(&state, &serial, NULL);
|
||||
PL_Init(&state);
|
||||
state.reset = cb_reset;
|
||||
state.tx = cb_tx;
|
||||
state.rx_timeout = cb_rx_timeout;
|
||||
state.progress = cb_progress;
|
||||
|
||||
/* process the position-independent arguments */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
@ -210,8 +244,19 @@ int main(int argc, char *argv[])
|
||||
if (file) {
|
||||
if ((image = ReadEntireFile(file, &imageSize)) != NULL) {
|
||||
printf("Loading '%s' (%ld bytes)\n", file, imageSize);
|
||||
if (PL_LoadSpinBinary(&state, loadType, image, imageSize) <= 0)
|
||||
printf("Load failed!\n");
|
||||
switch (PL_LoadSpinBinary(&state, loadType, image, imageSize)) {
|
||||
case LOAD_STS_OK:
|
||||
break;
|
||||
case LOAD_STS_ERROR:
|
||||
printf("Error\n");
|
||||
break;
|
||||
case LOAD_STS_TIMEOUT:
|
||||
printf("Timeout\n");
|
||||
break;
|
||||
default:
|
||||
printf("Internal error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,7 +392,7 @@ static int OpenPort(const char* port, int baud)
|
||||
return CHECK_PORT_OPEN_FAILED;
|
||||
|
||||
/* check for a propeller on this port */
|
||||
if (!PL_HardwareFound(&state, &version)) {
|
||||
if (PL_HardwareFound(&state, &version) != LOAD_STS_OK) {
|
||||
serial_done();
|
||||
return CHECK_PORT_NO_PROPELLER;
|
||||
}
|
||||
|
116
ploader.c
116
ploader.c
@ -1,4 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "ploader.h"
|
||||
|
||||
#ifndef TRUE
|
||||
@ -6,10 +6,15 @@
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* timeouts in milliseconds */
|
||||
#define ACK_TIMEOUT 25
|
||||
#define CHECKSUM_RETRIES (2000 / ACK_TIMEOUT)
|
||||
#define EEPROM_PROGRAMMING_RETRIES (5000 / ACK_TIMEOUT)
|
||||
#define EEPROM_VERIFICATION_RETRIES (2000 / ACK_TIMEOUT)
|
||||
#define CHECKSUM_TIMEOUT 10000 // big because it includes program loading
|
||||
#define EEPROM_PROGRAMMING_TIMEOUT 5000
|
||||
#define EEPROM_VERIFICATION_TIMEOUT 2000
|
||||
|
||||
#define CHECKSUM_RETRIES (CHECKSUM_TIMEOUT / ACK_TIMEOUT)
|
||||
#define EEPROM_PROGRAMMING_RETRIES (EEPROM_PROGRAMMING_TIMEOUT / ACK_TIMEOUT)
|
||||
#define EEPROM_VERIFICATION_RETRIES (EEPROM_VERIFICATION_TIMEOUT / ACK_TIMEOUT)
|
||||
|
||||
static int WaitForAck(PL_state *state, int retries);
|
||||
static void SerialInit(PL_state *state);
|
||||
@ -19,10 +24,9 @@ static void TComm(PL_state *state);
|
||||
static int RBit(PL_state *state, int timeout);
|
||||
static int IterateLFSR(PL_state *state);
|
||||
|
||||
void PL_Init(PL_state *state, PL_serial *serial, void *data)
|
||||
void PL_Init(PL_state *state)
|
||||
{
|
||||
state->serial = serial;
|
||||
state->serialData = data;
|
||||
memset(state, 0, sizeof(PL_state));
|
||||
}
|
||||
|
||||
/* PL_Shutdown - shutdown the loader */
|
||||
@ -37,55 +41,57 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
|
||||
{
|
||||
int i, sts;
|
||||
|
||||
printf("Loading hub memory ... "); fflush(stdout);
|
||||
|
||||
TLong(state, loadType);
|
||||
TLong(state, size / sizeof(uint32_t));
|
||||
|
||||
/* download the spin binary */
|
||||
for (i = 0; i < size; i += 4) {
|
||||
|
||||
/* report load progress */
|
||||
if (state->progress && (i % 1024) == 0)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_PROGRAM, i, size);
|
||||
|
||||
/* transmit the next long */
|
||||
uint32_t data = image[i] | (image[i + 1] << 8) | (image[i + 2] << 16) | (image[i + 3] << 24);
|
||||
TLong(state, data);
|
||||
}
|
||||
TComm(state);
|
||||
|
||||
/* wait for an ACK indicating a successful load */
|
||||
if ((sts = WaitForAck(state, CHECKSUM_RETRIES)) <= 0) {
|
||||
if (sts < 0)
|
||||
printf("Timeout waiting for checksum\n");
|
||||
else
|
||||
printf("Checksum error\n");
|
||||
return sts;
|
||||
}
|
||||
printf("OK\n");
|
||||
if ((sts = WaitForAck(state, CHECKSUM_RETRIES)) < 0)
|
||||
return LOAD_STS_TIMEOUT;
|
||||
else if (sts == 0)
|
||||
return LOAD_STS_ERROR;
|
||||
|
||||
/* wait for eeprom programming and verification */
|
||||
if (loadType == LOAD_TYPE_EEPROM || loadType == LOAD_TYPE_EEPROM_RUN) {
|
||||
|
||||
/* report the start of the eeprom writing phase */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_EEPROM_WRITE, 0, size);
|
||||
|
||||
/* wait for an ACK indicating a successful EEPROM programming */
|
||||
printf("Writing EEPROM ... "); fflush(stdout);
|
||||
if ((sts = WaitForAck(state, EEPROM_PROGRAMMING_RETRIES)) <= 0) {
|
||||
if (sts < 0)
|
||||
printf("Timeout\n");
|
||||
else
|
||||
printf("Failed\n");
|
||||
return sts;
|
||||
}
|
||||
printf("OK\n");
|
||||
if ((sts = WaitForAck(state, EEPROM_PROGRAMMING_RETRIES)) < 0)
|
||||
return LOAD_STS_TIMEOUT;
|
||||
else if (sts == 0)
|
||||
return LOAD_STS_ERROR;
|
||||
|
||||
/* report the start of the eeprom verification phase */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_EEPROM_VERIFY, 0, size);
|
||||
|
||||
/* wait for an ACK indicating a successful EEPROM verification */
|
||||
printf("Verifying EEPROM ... "); fflush(stdout);
|
||||
if ((sts = WaitForAck(state, EEPROM_VERIFICATION_RETRIES)) <= 0) {
|
||||
if (sts < 0)
|
||||
printf("Timeout\n");
|
||||
else
|
||||
printf("Failed\n");
|
||||
return sts;
|
||||
}
|
||||
printf("OK\n");
|
||||
if ((sts = WaitForAck(state, EEPROM_VERIFICATION_RETRIES)) < 0)
|
||||
return LOAD_STS_TIMEOUT;
|
||||
else if (sts == 0)
|
||||
return LOAD_STS_ERROR;
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* report load completion */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_DONE, 0, size);
|
||||
|
||||
return LOAD_STS_OK;
|
||||
}
|
||||
|
||||
static int WaitForAck(PL_state *state, int retries)
|
||||
@ -94,7 +100,7 @@ static int WaitForAck(PL_state *state, int retries)
|
||||
while (--retries >= 0) {
|
||||
TByte(state, 0xf9);
|
||||
TComm(state);
|
||||
if ((*state->serial->rx_timeout)(state->serialData, buf, 1, ACK_TIMEOUT) > 0)
|
||||
if ((*state->rx_timeout)(state->serialData, buf, 1, ACK_TIMEOUT) > 0)
|
||||
return buf[0] == 0xfe;
|
||||
}
|
||||
return -1; // timeout
|
||||
@ -109,8 +115,12 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
|
||||
/* initialize the serial buffers */
|
||||
SerialInit(state);
|
||||
|
||||
/* report the start of the handshake phase */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_HANDSHAKE, 0, 0);
|
||||
|
||||
/* reset the propeller (includes post-reset delay of 100ms) */
|
||||
(*state->serial->reset)(state->serialData);
|
||||
(*state->reset)(state->serialData);
|
||||
|
||||
/* transmit the calibration pulses */
|
||||
TByte(state, 0xf9);
|
||||
@ -127,22 +137,38 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
|
||||
/* flush the transmit buffer */
|
||||
TComm(state);
|
||||
|
||||
/* report the start of the handshake response phase */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_RESPONSE, 0, 0);
|
||||
|
||||
/* receive the connection response */
|
||||
for (i = 0; i < 250; ++i)
|
||||
if (RBit(state, 100) != IterateLFSR(state))
|
||||
return FALSE;
|
||||
for (i = 0; i < 250; ++i) {
|
||||
int bit = RBit(state, 100);
|
||||
if (bit < 0)
|
||||
return LOAD_STS_TIMEOUT;
|
||||
else if (bit != IterateLFSR(state))
|
||||
return LOAD_STS_ERROR;
|
||||
}
|
||||
|
||||
/* report the start of the version phase */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_VERSION, 0, 0);
|
||||
|
||||
/* receive the chip version */
|
||||
for (version = i = 0; i < 8; ++i) {
|
||||
int bit = RBit(state, 50);
|
||||
if (bit < 0)
|
||||
return FALSE;
|
||||
return LOAD_STS_TIMEOUT;
|
||||
version = ((version >> 1) & 0x7f) | (bit << 7);
|
||||
}
|
||||
*pVersion = version;
|
||||
|
||||
/* report handshake completion */
|
||||
if (state->progress)
|
||||
(*state->progress)(state->progressData, LOAD_PHASE_HANDSHAKE_DONE, 0, 0);
|
||||
|
||||
/* return successfully */
|
||||
return TRUE;
|
||||
return LOAD_STS_OK;
|
||||
}
|
||||
|
||||
/* SerialInit - initialize the serial buffers */
|
||||
@ -193,7 +219,7 @@ static void TLong(PL_state *state, uint32_t x)
|
||||
/* TComm - write the transmit buffer to the port */
|
||||
static void TComm(PL_state *state)
|
||||
{
|
||||
(*state->serial->tx)(state->serialData, state->txbuf, state->txcnt);
|
||||
(*state->tx)(state->serialData, state->txbuf, state->txcnt);
|
||||
state->txcnt = 0;
|
||||
}
|
||||
|
||||
@ -203,7 +229,7 @@ static int RBit(PL_state *state, int timeout)
|
||||
int result;
|
||||
for (;;) {
|
||||
if (state->rxnext >= state->rxcnt) {
|
||||
state->rxcnt = (*state->serial->rx_timeout)(state->serialData, state->rxbuf, sizeof(state->rxbuf), timeout);
|
||||
state->rxcnt = (*state->rx_timeout)(state->serialData, state->rxbuf, sizeof(state->rxbuf), timeout);
|
||||
if (state->rxcnt <= 0) {
|
||||
/* hardware lost */
|
||||
return -1;
|
||||
|
46
ploader.h
46
ploader.h
@ -8,22 +8,38 @@ extern "C"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define LOAD_TYPE_SHUTDOWN 0
|
||||
#define LOAD_TYPE_RUN 1
|
||||
#define LOAD_TYPE_EEPROM 2
|
||||
#define LOAD_TYPE_EEPROM_RUN 3
|
||||
#define LOAD_PHASE_HANDSHAKE 0
|
||||
#define LOAD_PHASE_RESPONSE 1
|
||||
#define LOAD_PHASE_VERSION 2
|
||||
#define LOAD_PHASE_HANDSHAKE_DONE 3
|
||||
#define LOAD_PHASE_PROGRAM 4
|
||||
#define LOAD_PHASE_EEPROM_WRITE 5
|
||||
#define LOAD_PHASE_EEPROM_VERIFY 6
|
||||
#define LOAD_PHASE_DONE 7
|
||||
|
||||
/* serial port interface - filled in by the user prior to calling PL_Init */
|
||||
typedef struct {
|
||||
void (*reset)(void *data);
|
||||
int (*tx)(void *data, uint8_t* buf, int n);
|
||||
int (*rx_timeout)(void *data, uint8_t* buf, int n, int timeout);
|
||||
} PL_serial;
|
||||
#define LOAD_STS_OK 0
|
||||
#define LOAD_STS_ERROR -1
|
||||
#define LOAD_STS_TIMEOUT -2
|
||||
|
||||
#define LOAD_TYPE_SHUTDOWN 0
|
||||
#define LOAD_TYPE_RUN 1
|
||||
#define LOAD_TYPE_EEPROM 2
|
||||
#define LOAD_TYPE_EEPROM_RUN 3
|
||||
|
||||
/* loader state structure - filled in by the loader functions */
|
||||
typedef struct {
|
||||
PL_serial *serial;
|
||||
|
||||
/* serial driver interface */
|
||||
void (*reset)(void *data);
|
||||
int (*tx)(void *data, uint8_t* buf, int n);
|
||||
int (*rx_timeout)(void *data, uint8_t* buf, int n, int timeout);
|
||||
void *serialData;
|
||||
|
||||
/* load progress interface */
|
||||
void (*progress)(void *data, int phase, int current, int total);
|
||||
void *progressData;
|
||||
|
||||
/* internal variables */
|
||||
uint8_t txbuf[1024];
|
||||
int txcnt;
|
||||
uint8_t rxbuf[1024];
|
||||
@ -33,10 +49,7 @@ typedef struct {
|
||||
} PL_state;
|
||||
|
||||
/* PL_Init - Initializes the loader state structure. */
|
||||
void PL_Init(PL_state *state, PL_serial *serial, void *data);
|
||||
|
||||
/* PL_Shutdown - Shutdown the loader.*/
|
||||
void PL_Shutdown(PL_state *state);
|
||||
void PL_Init(PL_state *state);
|
||||
|
||||
/* PL_HardwareFound - Sends the handshake sequence and returns non-zero if a Propeller
|
||||
chip is found on the serial interface and also sets the version parameter to the
|
||||
@ -49,6 +62,9 @@ int PL_HardwareFound(PL_state *state, int *pVersion);
|
||||
*/
|
||||
int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size);
|
||||
|
||||
/* PL_Shutdown - Shutdown the loader.*/
|
||||
void PL_Shutdown(PL_state *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user