Add code to check the success of EEPROM write and verify.

This commit is contained in:
David Betz 2015-02-07 22:49:50 -05:00
parent 60d4399cd7
commit 082e1636a8
3 changed files with 60 additions and 30 deletions

View File

@ -210,7 +210,7 @@ int main(int argc, char *argv[])
if (file) { if (file) {
if ((image = ReadEntireFile(file, &imageSize)) != NULL) { if ((image = ReadEntireFile(file, &imageSize)) != NULL) {
printf("Loading '%s' (%ld bytes)\n", file, imageSize); printf("Loading '%s' (%ld bytes)\n", file, imageSize);
if (PL_LoadSpinBinary(&state, loadType, image, imageSize) != 0) if (PL_LoadSpinBinary(&state, loadType, image, imageSize) <= 0)
printf("Load failed!\n"); printf("Load failed!\n");
} }
} }

View File

@ -1,8 +1,4 @@
#ifdef MINGW #include <stdio.h>
#include <unistd.h>
#else
#include <time.h>
#endif
#include "ploader.h" #include "ploader.h"
#ifndef TRUE #ifndef TRUE
@ -10,9 +6,12 @@
#define FALSE 0 #define FALSE 0
#endif #endif
#define ACK_TIMEOUT 20 #define ACK_TIMEOUT 25
#define CHECKSUM_RETRIES (2000 / ACK_TIMEOUT)
#define EEPROM_PROGRAMMING_RETRIES (5000 / ACK_TIMEOUT)
#define EEPROM_VERIFICATION_RETRIES (2000 / ACK_TIMEOUT)
static int us_sleep(unsigned long usecs); static int WaitForAck(PL_state *state, int retries);
static void SerialInit(PL_state *state); static void SerialInit(PL_state *state);
static void TByte(PL_state *state, uint8_t x); static void TByte(PL_state *state, uint8_t x);
static void TLong(PL_state *state, uint32_t x); static void TLong(PL_state *state, uint32_t x);
@ -26,12 +25,19 @@ void PL_Init(PL_state *state, PL_serial *serial, void *data)
state->serialData = data; state->serialData = data;
} }
/* PL_Shutdown - shutdown the loader */
void PL_Shutdown(PL_state *state)
{
TLong(state, LOAD_TYPE_SHUTDOWN);
TComm(state);
}
/* PL_LoadSpinBinary - load a spin binary using the rom loader */ /* PL_LoadSpinBinary - load a spin binary using the rom loader */
int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size) int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
{ {
int retries = 100; int i, sts;
uint8_t buf[1];
int i; printf("Loading hub memory ... "); fflush(stdout);
TLong(state, loadType); TLong(state, loadType);
TLong(state, size / sizeof(uint32_t)); TLong(state, size / sizeof(uint32_t));
@ -42,35 +48,56 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
TLong(state, data); TLong(state, data);
} }
TComm(state); TComm(state);
us_sleep(1000);
/* wait for an ACK */ /* wait for an ACK indicating a successful load */
while (--retries >= 0) { if ((sts = WaitForAck(state, CHECKSUM_RETRIES)) <= 0) {
TByte(state, 0xf9); if (sts < 0)
TComm(state); printf("Timeout waiting for checksum\n");
if ((*state->serial->rx_timeout)(state->serialData, buf, 1, ACK_TIMEOUT) <= 0) else
continue; printf("Checksum error\n");
if (buf[0] == 0xfe) return sts;
break;
} }
printf("OK\n");
/* wait for eeprom programming and verification */ /* wait for eeprom programming and verification */
if (loadType == LOAD_TYPE_EEPROM || loadType == LOAD_TYPE_EEPROM_RUN) { if (loadType == LOAD_TYPE_EEPROM || loadType == LOAD_TYPE_EEPROM_RUN) {
/* BUG: need to add handling of ACK/NAK from EEPROM programming */
/* BUG: need to add handling of ACK/NAK from EEPROM verification */ /* 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");
/* 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");
} }
return retries >= 0 ? 0 : -1; return 1;
} }
static int us_sleep(unsigned long usecs) static int WaitForAck(PL_state *state, int retries)
{ {
struct timespec req; uint8_t buf[1];
req.tv_sec = (int)(usecs / 1000000L); while (--retries >= 0) {
req.tv_nsec = (usecs - (req.tv_sec * 1000000L)) * 1000L; TByte(state, 0xf9);
while (nanosleep(&req, &req) < 0) TComm(state);
; if ((*state->serial->rx_timeout)(state->serialData, buf, 1, ACK_TIMEOUT) > 0)
return 1; return buf[0] == 0xfe;
}
return -1; // timeout
} }
/* this code is adapted from Chip Gracey's PNut IDE */ /* this code is adapted from Chip Gracey's PNut IDE */

View File

@ -35,6 +35,9 @@ typedef struct {
/* PL_Init - Initializes the loader state structure. */ /* PL_Init - Initializes the loader state structure. */
void PL_Init(PL_state *state, PL_serial *serial, void *data); void PL_Init(PL_state *state, PL_serial *serial, void *data);
/* PL_Shutdown - Shutdown the loader.*/
void PL_Shutdown(PL_state *state);
/* PL_HardwareFound - Sends the handshake sequence and returns non-zero if a Propeller /* 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 chip is found on the serial interface and also sets the version parameter to the
chip version. chip version.