Add callbacks for load phases to get rid of the use of printf in ploader.c.

This commit is contained in:
David Betz 2015-02-08 08:21:46 -05:00
parent 082e1636a8
commit cfec83ceb6
3 changed files with 152 additions and 65 deletions

View File

@ -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
View File

@ -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;

View File

@ -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