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();
msleep(10);
deassert_reset();
msleep(90);
msleep(100);
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
*
* Copyright (c) 2011 by Steve Denson.
*
* MIT License
*
* 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.
*
*/
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <stdarg.h>
#include "osint.h"
static HANDLE hSerial = INVALID_HANDLE_VALUE;
static COMMTIMEOUTS original_timeouts;
static COMMTIMEOUTS timeouts;
static void ShowLastError(void);
/* normally we use DTR for reset but setting this variable to non-zero will use RTS instead */
static int use_rts_for_reset = 0;
void serial_use_rts_for_reset(int use_rts)
{
use_rts_for_reset = use_rts;
}
int serial_init(const char *port, unsigned long baud)
{
char fullPort[20];
sprintf(fullPort, "\\\\.\\%s", port);
hSerial = CreateFile(
fullPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hSerial == INVALID_HANDLE_VALUE)
return FALSE;
/* Set the baud rate. Always succeeds with mingw. */
if (!serial_baud(baud)) {
serial_done();
return 0;
}
GetCommTimeouts(hSerial, &original_timeouts);
timeouts = original_timeouts;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.WriteTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
/* setup device buffers */
SetupComm(hSerial, 10000, 10000);
/* purge any information in the buffer */
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
return TRUE;
}
void serial_done(void)
{
if (hSerial != INVALID_HANDLE_VALUE) {
FlushFileBuffers(hSerial);
CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;
}
}
/**
* change the baud rate of the serial port
* @param baud - baud rate
* @returns 1 for success and 0 for failure
*/
int serial_baud(unsigned long baud)
{
DCB state;
GetCommState(hSerial, &state);
switch (baud) {
case 9600:
state.BaudRate = CBR_9600;
break;
case 19200:
state.BaudRate = CBR_19200;
break;
case 38400:
state.BaudRate = CBR_38400;
break;
case 57600:
state.BaudRate = CBR_57600;
break;
case 115200:
state.BaudRate = CBR_115200;
break;
default:
printf("Unsupported baudrate. Use ");
printf("115200, 57600, 38400, 19200, or 9600\n");
printf("Setting default 115200\n");
state.BaudRate = CBR_115200;
break;
}
state.ByteSize = 8;
state.Parity = NOPARITY;
state.StopBits = ONESTOPBIT;
state.fOutxDsrFlow = FALSE;
state.fDtrControl = DTR_CONTROL_DISABLE;
state.fOutxCtsFlow = FALSE;
state.fRtsControl = RTS_CONTROL_DISABLE;
state.fInX = FALSE;
state.fOutX = FALSE;
state.fBinary = TRUE;
state.fParity = FALSE;
state.fDsrSensitivity = FALSE;
state.fTXContinueOnXoff = TRUE;
state.fNull = FALSE;
state.fAbortOnError = FALSE;
SetCommState(hSerial, &state);
return 1;
}
/**
* transmit a buffer
* @param buff - char pointer to buffer
* @param n - number of bytes in buffer to send
* @returns zero on failure
*/
int tx(uint8_t* buff, int n)
{
DWORD dwBytes = 0;
if(!WriteFile(hSerial, buff, n, &dwBytes, NULL)){
printf("Error writing port\n");
ShowLastError();
return 0;
}
return dwBytes;
}
/**
* receive a buffer
* @param buff - char pointer to buffer
* @param n - number of bytes in buffer to read
* @returns number of bytes read
*/
int rx(uint8_t* buff, int n)
{
DWORD dwBytes = 0;
SetCommTimeouts(hSerial, &original_timeouts);
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
printf("Error reading port\n");
ShowLastError();
return 0;
}
return dwBytes;
}
/**
* 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
* @returns number of bytes read or SERIAL_TIMEOUT
*/
int rx_timeout(uint8_t* buff, int n, int timeout)
{
DWORD dwBytes = 0;
timeouts.ReadTotalTimeoutConstant = timeout;
SetCommTimeouts(hSerial, &timeouts);
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
printf("Error reading port\n");
ShowLastError();
return 0;
}
return dwBytes > 0 ? dwBytes : SERIAL_TIMEOUT;
}
/**
* hwreset ... resets Propeller hardware using DTR
* @returns void
*/
void hwreset(void)
{
// reset then purge port
EscapeCommFunction(hSerial, use_rts_for_reset ? SETRTS : SETDTR);
Sleep(25);
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
EscapeCommFunction(hSerial, use_rts_for_reset ? CLRRTS : CLRDTR);
Sleep(90);
// Purge here after reset helps to get rid of buffered data.
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
}
static unsigned long getms()
{
LARGE_INTEGER ticksPerSecond;
LARGE_INTEGER tick; // A point in time
LARGE_INTEGER time; // For converting tick into real time
// get the high resolution counter's accuracy
QueryPerformanceFrequency(&ticksPerSecond);
if(ticksPerSecond.QuadPart < 1000) {
printf("Your system does not meet timer requirement. Try another computer. Exiting program.\n");
exit(1);
}
// what time is it?
QueryPerformanceCounter(&tick);
time.QuadPart = (tick.QuadPart*1000/ticksPerSecond.QuadPart);
return (unsigned long)(time.QuadPart);
}
/**
* sleep for ms milliseconds
* @param ms - time to wait in milliseconds
*/
void msleep(int ms)
{
unsigned long t = getms();
while((t+ms+10) > getms())
;
}
static void ShowLastError(void)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
printf(" %s\n", (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1); // exit on error
}
/* escape from terminal mode */
#define ESC 0x1b
/*
* if "check_for_exit" is true, then
* a sequence EXIT_CHAR 00 nn indicates that we should exit
*/
#define EXIT_CHAR 0xff
void terminal_mode(int check_for_exit, int pst_mode)
{
int sawexit_char = 0;
int sawexit_valid = 0;
int exitcode = 0;
int continue_terminal = 1;
while (continue_terminal) {
uint8_t buf[1];
if (rx_timeout(buf, 1, 0) != SERIAL_TIMEOUT) {
if (sawexit_valid) {
exitcode = buf[0];
continue_terminal = 0;
}
else if (sawexit_char) {
if (buf[0] == 0) {
sawexit_valid = 1;
} else {
putchar(EXIT_CHAR);
putchar(buf[0]);
fflush(stdout);
//sawexit_char = 0;
}
}
else if (check_for_exit && buf[0] == EXIT_CHAR) {
sawexit_char = 1;
}
else {
putchar(buf[0]);
if (pst_mode && buf[0] == '\r')
putchar('\n');
fflush(stdout);
}
}
else if (kbhit()) {
if ((buf[0] = getch()) == ESC)
break;
tx(buf, 1);
}
}
if (check_for_exit && sawexit_valid) {
exit(exitcode);
}
}
/*
* osint_mingw.c - serial i/o routines for win32api via mingw
*
* Copyright (c) 2011 by Steve Denson.
*
* MIT License
*
* 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.
*
*/
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <stdarg.h>
#include "osint.h"
static HANDLE hSerial = INVALID_HANDLE_VALUE;
static COMMTIMEOUTS original_timeouts;
static COMMTIMEOUTS timeouts;
static void ShowLastError(void);
/* Normally we use DTR for reset */
static reset_method_t reset_method = RESET_WITH_DTR;
int use_reset_method(char* method)
{
if (strcasecmp(method, "dtr") == 0)
reset_method = RESET_WITH_DTR;
else if (strcasecmp(method, "rts") == 0)
reset_method = RESET_WITH_RTS;
else {
return -1;
}
return 0;
}
int serial_init(const char *port, unsigned long baud)
{
char fullPort[20];
DCB state;
sprintf(fullPort, "\\\\.\\%s", port);
hSerial = CreateFile(
fullPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hSerial == INVALID_HANDLE_VALUE)
return FALSE;
GetCommState(hSerial, &state);
switch (baud) {
case 9600:
state.BaudRate = CBR_9600;
break;
case 19200:
state.BaudRate = CBR_19200;
break;
case 38400:
state.BaudRate = CBR_38400;
break;
case 57600:
state.BaudRate = CBR_57600;
break;
case 115200:
state.BaudRate = CBR_115200;
break;
default:
return FALSE;
}
state.ByteSize = 8;
state.Parity = NOPARITY;
state.StopBits = ONESTOPBIT;
state.fOutxDsrFlow = FALSE;
state.fDtrControl = DTR_CONTROL_DISABLE;
state.fOutxCtsFlow = FALSE;
state.fRtsControl = RTS_CONTROL_DISABLE;
state.fInX = FALSE;
state.fOutX = FALSE;
state.fBinary = TRUE;
state.fParity = FALSE;
state.fDsrSensitivity = FALSE;
state.fTXContinueOnXoff = TRUE;
state.fNull = FALSE;
state.fAbortOnError = FALSE;
SetCommState(hSerial, &state);
GetCommTimeouts(hSerial, &original_timeouts);
timeouts = original_timeouts;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
/* setup device buffers */
SetupComm(hSerial, 10000, 10000);
/* purge any information in the buffer */
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
return TRUE;
}
void serial_done(void)
{
if (hSerial != INVALID_HANDLE_VALUE) {
FlushFileBuffers(hSerial);
CloseHandle(hSerial);
hSerial = INVALID_HANDLE_VALUE;
}
}
/**
* transmit a buffer
* @param buff - char pointer to buffer
* @param n - number of bytes in buffer to send
* @returns zero on failure
*/
int tx(uint8_t* buff, int n)
{
DWORD dwBytes = 0;
if(!WriteFile(hSerial, buff, n, &dwBytes, NULL)){
printf("Error writing port\n");
ShowLastError();
return 0;
}
return dwBytes;
}
/**
* receive a buffer
* @param buff - char pointer to buffer
* @param n - number of bytes in buffer to read
* @returns number of bytes read
*/
int rx(uint8_t* buff, int n)
{
DWORD dwBytes = 0;
SetCommTimeouts(hSerial, &original_timeouts);
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
printf("Error reading port\n");
ShowLastError();
return 0;
}
return dwBytes;
}
/**
* 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
* @returns number of bytes read or SERIAL_TIMEOUT
*/
int rx_timeout(uint8_t* buff, int n, int timeout)
{
DWORD dwBytes = 0;
timeouts.ReadTotalTimeoutConstant = timeout;
SetCommTimeouts(hSerial, &timeouts);
if(!ReadFile(hSerial, buff, n, &dwBytes, NULL)){
printf("Error reading port\n");
ShowLastError();
return 0;
}
return dwBytes > 0 ? dwBytes : SERIAL_TIMEOUT;
}
/**
* hwreset ... resets Propeller hardware using DTR
* @returns void
*/
void hwreset(void)
{
EscapeCommFunction(hSerial, reset_method == RESET_WITH_RTS ? SETRTS : SETDTR);
Sleep(25);
EscapeCommFunction(hSerial, reset_method == RESET_WITH_RTS ? CLRRTS : CLRDTR);
Sleep(90);
// Purge here after reset helps to get rid of buffered data.
PurgeComm(hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
}
static unsigned long getms()
{
LARGE_INTEGER ticksPerSecond;
LARGE_INTEGER tick; // A point in time
LARGE_INTEGER time; // For converting tick into real time
// get the high resolution counter's accuracy
QueryPerformanceFrequency(&ticksPerSecond);
if(ticksPerSecond.QuadPart < 1000) {
printf("Your system does not meet timer requirement. Try another computer. Exiting program.\n");
exit(1);
}
// what time is it?
QueryPerformanceCounter(&tick);
time.QuadPart = (tick.QuadPart*1000/ticksPerSecond.QuadPart);
return (unsigned long)(time.QuadPart);
}
/**
* sleep for ms milliseconds
* @param ms - time to wait in milliseconds
*/
void msleep(int ms)
{
unsigned long t = getms();
while((t+ms+10) > getms())
;
}
static void ShowLastError(void)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
printf(" %s\n", (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1); // exit on error
}
/* escape from terminal mode */
#define ESC 0x1b
/*
* if "check_for_exit" is true, then
* a sequence EXIT_CHAR 00 nn indicates that we should exit
*/
#define EXIT_CHAR 0xff
void terminal_mode(int check_for_exit, int pst_mode)
{
int sawexit_char = 0;
int sawexit_valid = 0;
int exitcode = 0;
int continue_terminal = 1;
while (continue_terminal) {
uint8_t buf[1];
if (rx_timeout(buf, 1, 0) != SERIAL_TIMEOUT) {
if (sawexit_valid) {
exitcode = buf[0];
continue_terminal = 0;
}
else if (sawexit_char) {
if (buf[0] == 0) {
sawexit_valid = 1;
} else {
putchar(EXIT_CHAR);
putchar(buf[0]);
fflush(stdout);
}
}
else if (check_for_exit && buf[0] == EXIT_CHAR) {
sawexit_char = 1;
}
else {
putchar(buf[0]);
if (pst_mode && buf[0] == '\r')
putchar('\n');
fflush(stdout);
}
}
else if (kbhit()) {
if ((buf[0] = getch()) == ESC)
break;
tx(buf, 1);
/* this should be handled by the library */
#if 0
if(buf[0] == '\r') {
buf[0] = '\n';
tx(buf, 1);
}
#endif
}
}
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;
uint8_t buf[1];
int i;
TLong(state, loadType);
TLong(state, size / sizeof(uint32_t));
@ -54,6 +54,12 @@ int PL_LoadSpinBinary(PL_state *state, int loadType, uint8_t *image, int size)
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;
}
@ -76,19 +82,25 @@ int PL_HardwareFound(PL_state *state, int *pVersion)
/* initialize the serial buffers */
SerialInit(state);
/* reset the propeller */
/* reset the propeller (includes post-reset delay of 100ms) */
(*state->serial->reset)(state->serialData);
/* send the connect string + blanks for echoes */
/* transmit the calibration pulses */
TByte(state, 0xf9);
/* transmit the handshake pattern */
state->lfsr = 'P';
for (i = 0; i < 250; ++i)
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)
TByte(state, 0xf9);
/* flush the transmit buffer */
TComm(state);
/* receive the connect string */
/* receive the connection response */
for (i = 0; i < 250; ++i)
if (RBit(state, 100) != IterateLFSR(state))
return FALSE;