Moved a new version of osint_mingw.c from the propeller-load project but still needs serial_baud() function to work.

Started adding some better comments in ploader.c.
This commit is contained in:
David Betz 2015-02-03 08:45:38 -05:00
parent 808ba62a7b
commit bfd131d38b
3 changed files with 326 additions and 327 deletions

View File

@ -464,7 +464,7 @@ void hwreset(void)
assert_reset(); assert_reset();
msleep(10); msleep(10);
deassert_reset(); deassert_reset();
msleep(90); msleep(100);
tcflush(hSerial, TCIFLUSH); tcflush(hSerial, TCIFLUSH);
} }

631
osint_mingw.c Executable file → Normal file
View File

@ -1,322 +1,309 @@
/* /*
* osint_mingw.c - serial i/o routines for win32api via mingw * osint_mingw.c - serial i/o routines for win32api via mingw
* *
* Copyright (c) 2011 by Steve Denson. * Copyright (c) 2011 by Steve Denson.
* *
* MIT License * MIT License
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
*/ */
#include <windows.h> #include <windows.h>
#include <conio.h> #include <conio.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include "osint.h" #include "osint.h"
static HANDLE hSerial = INVALID_HANDLE_VALUE; static HANDLE hSerial = INVALID_HANDLE_VALUE;
static COMMTIMEOUTS original_timeouts; static COMMTIMEOUTS original_timeouts;
static COMMTIMEOUTS timeouts; static COMMTIMEOUTS timeouts;
static void ShowLastError(void); static void ShowLastError(void);
/* normally we use DTR for reset but setting this variable to non-zero will use RTS instead */ /* Normally we use DTR for reset */
static int use_rts_for_reset = 0; static reset_method_t reset_method = RESET_WITH_DTR;
void serial_use_rts_for_reset(int use_rts) int use_reset_method(char* method)
{ {
use_rts_for_reset = use_rts; if (strcasecmp(method, "dtr") == 0)
} reset_method = RESET_WITH_DTR;
else if (strcasecmp(method, "rts") == 0)
int serial_init(const char *port, unsigned long baud) reset_method = RESET_WITH_RTS;
{ else {
char fullPort[20]; return -1;
}
sprintf(fullPort, "\\\\.\\%s", port); return 0;
}
hSerial = CreateFile(
fullPort, int serial_init(const char *port, unsigned long baud)
GENERIC_READ | GENERIC_WRITE, {
0, char fullPort[20];
NULL, DCB state;
OPEN_EXISTING,
0, sprintf(fullPort, "\\\\.\\%s", port);
NULL);
hSerial = CreateFile(
if (hSerial == INVALID_HANDLE_VALUE) fullPort,
return FALSE; GENERIC_READ | GENERIC_WRITE,
0,
/* Set the baud rate. Always succeeds with mingw. */ NULL,
if (!serial_baud(baud)) { OPEN_EXISTING,
serial_done(); 0,
return 0; NULL);
}
if (hSerial == INVALID_HANDLE_VALUE)
return FALSE;
GetCommTimeouts(hSerial, &original_timeouts);
timeouts = original_timeouts; GetCommState(hSerial, &state);
timeouts.ReadIntervalTimeout = MAXDWORD; switch (baud) {
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; case 9600:
timeouts.WriteTotalTimeoutConstant = 1; state.BaudRate = CBR_9600;
timeouts.WriteTotalTimeoutMultiplier = 1; break;
case 19200:
/* setup device buffers */ state.BaudRate = CBR_19200;
SetupComm(hSerial, 10000, 10000); break;
case 38400:
/* purge any information in the buffer */ state.BaudRate = CBR_38400;
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); break;
case 57600:
return TRUE; state.BaudRate = CBR_57600;
} break;
case 115200:
void serial_done(void) state.BaudRate = CBR_115200;
{ break;
if (hSerial != INVALID_HANDLE_VALUE) { default:
FlushFileBuffers(hSerial); return FALSE;
CloseHandle(hSerial); }
hSerial = INVALID_HANDLE_VALUE; state.ByteSize = 8;
} state.Parity = NOPARITY;
} state.StopBits = ONESTOPBIT;
state.fOutxDsrFlow = FALSE;
/** state.fDtrControl = DTR_CONTROL_DISABLE;
* change the baud rate of the serial port state.fOutxCtsFlow = FALSE;
* @param baud - baud rate state.fRtsControl = RTS_CONTROL_DISABLE;
* @returns 1 for success and 0 for failure state.fInX = FALSE;
*/ state.fOutX = FALSE;
int serial_baud(unsigned long baud) state.fBinary = TRUE;
{ state.fParity = FALSE;
DCB state; state.fDsrSensitivity = FALSE;
GetCommState(hSerial, &state); state.fTXContinueOnXoff = TRUE;
switch (baud) { state.fNull = FALSE;
case 9600: state.fAbortOnError = FALSE;
state.BaudRate = CBR_9600; SetCommState(hSerial, &state);
break;
case 19200: GetCommTimeouts(hSerial, &original_timeouts);
state.BaudRate = CBR_19200; timeouts = original_timeouts;
break; timeouts.ReadIntervalTimeout = MAXDWORD;
case 38400: timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
state.BaudRate = CBR_38400;
break; /* setup device buffers */
case 57600: SetupComm(hSerial, 10000, 10000);
state.BaudRate = CBR_57600;
break; /* purge any information in the buffer */
case 115200: PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
state.BaudRate = CBR_115200;
break; return TRUE;
default: }
printf("Unsupported baudrate. Use ");
printf("115200, 57600, 38400, 19200, or 9600\n"); void serial_done(void)
printf("Setting default 115200\n"); {
state.BaudRate = CBR_115200; if (hSerial != INVALID_HANDLE_VALUE) {
break; FlushFileBuffers(hSerial);
} CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;
state.ByteSize = 8; }
state.Parity = NOPARITY; }
state.StopBits = ONESTOPBIT;
state.fOutxDsrFlow = FALSE; /**
state.fDtrControl = DTR_CONTROL_DISABLE; * transmit a buffer
state.fOutxCtsFlow = FALSE; * @param buff - char pointer to buffer
state.fRtsControl = RTS_CONTROL_DISABLE; * @param n - number of bytes in buffer to send
state.fInX = FALSE; * @returns zero on failure
state.fOutX = FALSE; */
state.fBinary = TRUE; int tx(uint8_t* buff, int n)
state.fParity = FALSE; {
state.fDsrSensitivity = FALSE; DWORD dwBytes = 0;
state.fTXContinueOnXoff = TRUE; if(!WriteFile(hSerial, buff, n, &dwBytes, NULL)){
state.fNull = FALSE; printf("Error writing port\n");
state.fAbortOnError = FALSE; ShowLastError();
SetCommState(hSerial, &state); return 0;
}
return 1; return dwBytes;
} }
/** /**
* transmit a buffer * receive a buffer
* @param buff - char pointer to buffer * @param buff - char pointer to buffer
* @param n - number of bytes in buffer to send * @param n - number of bytes in buffer to read
* @returns zero on failure * @returns number of bytes read
*/ */
int tx(uint8_t* buff, int n) int rx(uint8_t* buff, int n)
{ {
DWORD dwBytes = 0; DWORD dwBytes = 0;
if(!WriteFile(hSerial, buff, n, &dwBytes, NULL)){ SetCommTimeouts(hSerial, &original_timeouts);
printf("Error writing port\n"); if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
ShowLastError(); printf("Error reading port\n");
return 0; ShowLastError();
} return 0;
return dwBytes; }
} return dwBytes;
}
/**
* receive a buffer /**
* @param buff - char pointer to buffer * receive a buffer with a timeout
* @param n - number of bytes in buffer to read * @param buff - char pointer to buffer
* @returns number of bytes read * @param n - number of bytes in buffer to read
*/ * @param timeout - timeout in milliseconds
int rx(uint8_t* buff, int n) * @returns number of bytes read or SERIAL_TIMEOUT
{ */
DWORD dwBytes = 0; int rx_timeout(uint8_t* buff, int n, int timeout)
SetCommTimeouts(hSerial, &original_timeouts); {
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){ DWORD dwBytes = 0;
printf("Error reading port\n"); timeouts.ReadTotalTimeoutConstant = timeout;
ShowLastError(); SetCommTimeouts(hSerial, &timeouts);
return 0; if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
} printf("Error reading port\n");
return dwBytes; ShowLastError();
} return 0;
}
/** return dwBytes > 0 ? dwBytes : SERIAL_TIMEOUT;
* receive a buffer with a timeout }
* @param buff - char pointer to buffer
* @param n - number of bytes in buffer to read /**
* @param timeout - timeout in milliseconds * hwreset ... resets Propeller hardware using DTR
* @returns number of bytes read or SERIAL_TIMEOUT * @returns void
*/ */
int rx_timeout(uint8_t* buff, int n, int timeout) void hwreset(void)
{ {
DWORD dwBytes = 0; EscapeCommFunction(hSerial, reset_method == RESET_WITH_RTS ? SETRTS : SETDTR);
timeouts.ReadTotalTimeoutConstant = timeout; Sleep(25);
SetCommTimeouts(hSerial, &timeouts); EscapeCommFunction(hSerial, reset_method == RESET_WITH_RTS ? CLRRTS : CLRDTR);
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){ Sleep(90);
printf("Error reading port\n"); // Purge here after reset helps to get rid of buffered data.
ShowLastError(); PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
return 0; }
}
return dwBytes > 0 ? dwBytes : SERIAL_TIMEOUT; static unsigned long getms()
} {
LARGE_INTEGER ticksPerSecond;
/** LARGE_INTEGER tick; // A point in time
* hwreset ... resets Propeller hardware using DTR LARGE_INTEGER time; // For converting tick into real time
* @returns void // get the high resolution counter's accuracy
*/ QueryPerformanceFrequency(&ticksPerSecond);
void hwreset(void) if(ticksPerSecond.QuadPart < 1000) {
{ printf("Your system does not meet timer requirement. Try another computer. Exiting program.\n");
// reset then purge port exit(1);
EscapeCommFunction(hSerial, use_rts_for_reset ? SETRTS : SETDTR); }
Sleep(25); // what time is it?
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); QueryPerformanceCounter(&tick);
EscapeCommFunction(hSerial, use_rts_for_reset ? CLRRTS : CLRDTR); time.QuadPart = (tick.QuadPart*1000/ticksPerSecond.QuadPart);
Sleep(90); return (unsigned long)(time.QuadPart);
// Purge here after reset helps to get rid of buffered data. }
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
} /**
* sleep for ms milliseconds
static unsigned long getms() * @param ms - time to wait in milliseconds
{ */
LARGE_INTEGER ticksPerSecond; void msleep(int ms)
LARGE_INTEGER tick; // A point in time {
LARGE_INTEGER time; // For converting tick into real time unsigned long t = getms();
// get the high resolution counter's accuracy while((t+ms+10) > getms())
QueryPerformanceFrequency(&ticksPerSecond); ;
if(ticksPerSecond.QuadPart < 1000) { }
printf("Your system does not meet timer requirement. Try another computer. Exiting program.\n");
exit(1); static void ShowLastError(void)
} {
// what time is it? LPVOID lpMsgBuf;
QueryPerformanceCounter(&tick); FormatMessage(
time.QuadPart = (tick.QuadPart*1000/ticksPerSecond.QuadPart); FORMAT_MESSAGE_ALLOCATE_BUFFER |
return (unsigned long)(time.QuadPart); FORMAT_MESSAGE_FROM_SYSTEM |
} FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
/** GetLastError(),
* sleep for ms milliseconds MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
* @param ms - time to wait in milliseconds (LPTSTR)&lpMsgBuf,
*/ 0, NULL);
void msleep(int ms) printf(" %s\n", (char *)lpMsgBuf);
{ LocalFree(lpMsgBuf);
unsigned long t = getms(); exit(1); // exit on error
while((t+ms+10) > getms()) }
;
} /* escape from terminal mode */
#define ESC 0x1b
static void ShowLastError(void)
{ /*
LPVOID lpMsgBuf; * if "check_for_exit" is true, then
FormatMessage( * a sequence EXIT_CHAR 00 nn indicates that we should exit
FORMAT_MESSAGE_ALLOCATE_BUFFER | */
FORMAT_MESSAGE_FROM_SYSTEM | #define EXIT_CHAR 0xff
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, void terminal_mode(int check_for_exit, int pst_mode)
GetLastError(), {
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), int sawexit_char = 0;
(LPTSTR)&lpMsgBuf, int sawexit_valid = 0;
0, NULL); int exitcode = 0;
printf(" %s\n", (char *)lpMsgBuf); int continue_terminal = 1;
LocalFree(lpMsgBuf);
exit(1); // exit on error while (continue_terminal) {
} uint8_t buf[1];
if (rx_timeout(buf, 1, 0) != SERIAL_TIMEOUT) {
/* escape from terminal mode */ if (sawexit_valid) {
#define ESC 0x1b exitcode = buf[0];
continue_terminal = 0;
/* }
* if "check_for_exit" is true, then else if (sawexit_char) {
* a sequence EXIT_CHAR 00 nn indicates that we should exit if (buf[0] == 0) {
*/ sawexit_valid = 1;
#define EXIT_CHAR 0xff } else {
putchar(EXIT_CHAR);
void terminal_mode(int check_for_exit, int pst_mode) putchar(buf[0]);
{ fflush(stdout);
int sawexit_char = 0; }
int sawexit_valid = 0; }
int exitcode = 0; else if (check_for_exit && buf[0] == EXIT_CHAR) {
int continue_terminal = 1; sawexit_char = 1;
}
while (continue_terminal) { else {
uint8_t buf[1]; putchar(buf[0]);
if (rx_timeout(buf, 1, 0) != SERIAL_TIMEOUT) { if (pst_mode && buf[0] == '\r')
if (sawexit_valid) { putchar('\n');
exitcode = buf[0]; fflush(stdout);
continue_terminal = 0; }
} }
else if (sawexit_char) { else if (kbhit()) {
if (buf[0] == 0) { if ((buf[0] = getch()) == ESC)
sawexit_valid = 1; break;
} else { tx(buf, 1);
putchar(EXIT_CHAR); /* this should be handled by the library */
putchar(buf[0]); #if 0
fflush(stdout); if(buf[0] == '\r') {
//sawexit_char = 0; buf[0] = '\n';
} tx(buf, 1);
} }
else if (check_for_exit && buf[0] == EXIT_CHAR) { #endif
sawexit_char = 1; }
} }
else {
putchar(buf[0]); if (check_for_exit && sawexit_valid) {
if (pst_mode && buf[0] == '\r') exit(exitcode);
putchar('\n'); }
fflush(stdout); }
}
}
else if (kbhit()) {
if ((buf[0] = getch()) == ESC)
break;
tx(buf, 1);
}
}
if (check_for_exit && sawexit_valid) {
exit(exitcode);
}
}

View File

@ -32,7 +32,7 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
int retries = 100; int retries = 100;
uint8_t buf[1]; uint8_t buf[1];
int i; int i;
TLong(state, loadType); TLong(state, loadType);
TLong(state, size / sizeof(uint32_t)); TLong(state, size / sizeof(uint32_t));
@ -54,6 +54,12 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
break; break;
} }
/* wait for eeprom programming and verification */
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 */
}
return retries >= 0 ? 0 : -1; return retries >= 0 ? 0 : -1;
} }
@ -76,19 +82,25 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
/* initialize the serial buffers */ /* initialize the serial buffers */
SerialInit(state); SerialInit(state);
/* reset the propeller */ /* reset the propeller (includes post-reset delay of 100ms) */
(*state->serial->reset)(state->serialData); (*state->serial->reset)(state->serialData);
/* send the connect string + blanks for echoes */ /* transmit the calibration pulses */
TByte(state, 0xf9); TByte(state, 0xf9);
/* transmit the handshake pattern */
state->lfsr = 'P'; state->lfsr = 'P';
for (i = 0; i < 250; ++i) for (i = 0; i < 250; ++i)
TByte(state, IterateLFSR(state) | 0xfe); TByte(state, IterateLFSR(state) | 0xfe);
/* transmit calibration pulses to clock out the connection response and the version byte */
for (i = 0; i < 250 + 8; ++i) for (i = 0; i < 250 + 8; ++i)
TByte(state, 0xf9); TByte(state, 0xf9);
/* flush the transmit buffer */
TComm(state); TComm(state);
/* receive the connect string */ /* receive the connection response */
for (i = 0; i < 250; ++i) for (i = 0; i < 250; ++i)
if (RBit(state, 100) != IterateLFSR(state)) if (RBit(state, 100) != IterateLFSR(state))
return FALSE; return FALSE;