📄 lpc21isp.c
字号:
/***************************** SendComPort ******************************/
/** Sends a string out the opened com port.
\param [in] s string to send.
*/
static void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s)
{
SendComPortBlock( IspEnvironment, s, strlen(s));
}
/***************************** ReceiveComPortBlock **********************/
/** Receives a buffer from the open com port. Returns all the characters
ready (waits for up to 'n' milliseconds before accepting that no more
characters are ready) or when the buffer is full. 'n' is system dependant,
see SerialTimeout routines.
\param [out] answer buffer to hold the bytes read from the serial port.
\param [in] max_size the size of buffer pointed to by answer.
\param [out] real_size pointer to a long that returns the amout of the
buffer that is actually used.
*/
static void ReceiveComPortBlock( ISP_ENVIRONMENT *IspEnvironment,
void *answer, unsigned long max_size,
unsigned long *real_size)
{
char tmp_string[32];
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
ReadFile(IspEnvironment->hCom, answer, max_size, real_size, NULL);
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
*real_size = read(IspEnvironment->fdCom, answer, max_size);
#endif // defined COMPILE_FOR_LINUX
sprintf(tmp_string, "Read(Length=%ld): ", (*real_size));
DumpString( 5, answer, (*real_size), tmp_string);
if( *real_size == 0)
{
SerialTimeoutTick( IspEnvironment );
}
}
/***************************** SerialTimeoutSet *************************/
/** Sets (or resets) the timeout to the timout period requested. Starts
counting to this period. This timeout support is a little odd in that the
timeout specifies the accumulated deadtime waiting to read not the total
time waiting to read. They should be close enought to the same for this
use. Used by the serial input routines, the actual counting takes place in
ReceiveComPortBlock.
\param [in] timeout_milliseconds the time in milliseconds to use for
timeout. Note that just because it is set in milliseconds doesn't mean
that the granularity is that fine. In many cases (particularly Linux) it
will be coarser.
*/
static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds)
{
#if defined COMPILE_FOR_LINUX
IspEnvironment->serial_timeout_count = timeout_milliseconds/100;
#elif defined COMPILE_FOR_LPC21
IspEnvironment->serial_timeout_count = timeout_milliseconds*200;
#else
IspEnvironment->serial_timeout_count = timeout_milliseconds;
#endif
}
/***************************** SerialTimeoutTick ************************/
/** Performs a timer tick. In this simple case all we do is count down
with protection against underflow and wrapping at the low end.
*/
static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment)
{
if( IspEnvironment->serial_timeout_count <= 1)
{
IspEnvironment->serial_timeout_count = 0;
}
else
{
IspEnvironment->serial_timeout_count--;
}
}
/***************************** SerialTimeoutCheck ***********************/
/** Check to see if the serial timeout timer has run down.
\retval 1 if timer has run out.
\retval 0 if timer still has time left.
*/
static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment)
{
if( IspEnvironment->serial_timeout_count == 0)
{
return 1;
}
return 0;
}
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
/***************************** getch ************************************/
/** Replacement for the common dos function of the same name. Reads a
single unbuffered character from the 'keyboard'.
\return The character read from the keyboard.
*/
static int getch(void)
{
char ch;
/* Read in one character */
read(0,&ch,1);
return ch;
}
#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
/***************************** kbhit ************************************/
/** Replacement for the common dos function of the same name. Indicates if
there are characters to be read from the console.
\retval 0 No characters ready.
\retval 1 Characters from the console ready to be read.
*/
static int kbhit(void)
{
/* return 0 for no key pressed, 1 for key pressed */
int return_value = 0;
/* time struct for the select() function, to only wait a little while */
struct timeval select_time;
/* file descriptor variable for the select() call */
fd_set readset;
/* we're only interested in STDIN */
FD_ZERO(&readset);
FD_SET(STDIN_FILENO, &readset);
/* how long to block for - this must be > 0.0, but could be changed
to some other setting. 10-18msec seems to work well and only
minimally load the system (0% CPU loading) */
select_time.tv_sec = 0;
select_time.tv_usec = 10;
/* is there a keystroke there? */
if (select(1, &readset, NULL, NULL, &select_time))
{
/* yes, remember it */
return_value = 1;
}
/* return with what we found out */
return return_value;
}
#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
/***************************** PrepareKeyboardTtySettings ***************/
/** Set the keyboard tty to be able to check for new characters via kbhit
getting them via getch
*/
static void PrepareKeyboardTtySettings(void)
{
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
/* store the current tty settings */
if (!tcgetattr(0, &keyboard_origtty))
{
struct termios tty;
/* start with the current settings */
tty = keyboard_origtty;
/* make modifications to put it in raw mode, turn off echo */
tty.c_lflag &= ~ICANON;
tty.c_lflag &= ~ECHO;
tty.c_lflag &= ~ISIG;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
/* put the settings into effect */
tcsetattr(0, TCSADRAIN, &tty);
}
#endif
}
/***************************** ResetKeyboardTtySettings *****************/
/** Reset the keyboard tty to original settings
*/
static void ResetKeyboardTtySettings(void)
{
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
/* reset the tty to its original settings */
tcsetattr(0, TCSADRAIN, &keyboard_origtty);
#endif
}
#if !defined COMPILE_FOR_LPC21
/***************************** ControlModemLines ************************/
/** Controls the modem lines to place the microcontroller into various
states during the programming process.
error rather abruptly terminates the program.
\param [in] DTR the state to set the DTR line to.
\param [in] RTS the state to set the RTS line to.
*/
static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS)
{
#if defined COMPILE_FOR_LINUX
int status;
if(ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
{
DebugPrintf( 1, "ioctl get ok, status = %X\n",status);
}
else
{
DebugPrintf( 1, "ioctl get failed\n");
}
if(DTR) status |= TIOCM_DTR;
else status &= ~TIOCM_DTR;
if(RTS) status |= TIOCM_RTS;
else status &= ~TIOCM_RTS;
if(ioctl(IspEnvironment->fdCom, TIOCMSET, &status) == 0)
{
DebugPrintf( 1, "ioctl set ok, status = %X\n",status);
}
else
{
DebugPrintf( 1, "ioctl set failed\n");
}
if(ioctl(IspEnvironment->fdCom, TIOCMGET, &status) == 0)
{
DebugPrintf( 1, "ioctl get ok, status = %X\n",status);
}
else
{
DebugPrintf( 1, "ioctl get failed\n");
}
#endif // defined COMPILE_FOR_LINUX
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
if(DTR) EscapeCommFunction(IspEnvironment->hCom, SETDTR);
else EscapeCommFunction(IspEnvironment->hCom, CLRDTR);
if(RTS) EscapeCommFunction(IspEnvironment->hCom, SETRTS);
else EscapeCommFunction(IspEnvironment->hCom, CLRRTS);
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
DebugPrintf( 3, "DTR (%d), RTS (%d)\n", DTR, RTS);
}
/***************************** ClearSerialPortBuffers********************/
/** Empty the serial port buffers. Cleans things to a known state.
*/
static void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment)
{
#if defined COMPILE_FOR_LINUX
/* variables to store the current tty state, create a new one */
struct termios origtty, tty;
/* store the current tty settings */
tcgetattr(IspEnvironment->fdCom, &origtty);
// Flush input and output buffers
tcsetattr(IspEnvironment->fdCom, TCSAFLUSH, &tty);
/* reset the tty to its original settings */
tcsetattr(IspEnvironment->fdCom, TCSADRAIN, &origtty);
#endif // defined COMPILE_FOR_LINUX
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
PurgeComm(IspEnvironment->hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
}
#endif // !defined COMPILE_FOR_LPC21
#if defined COMPILE_FOR_LINUX
/***************************** Sleep ************************************/
/** Provide linux replacement for windows function.
\param [in] Milliseconds the time to wait for in milliseconds.
*/
static void Sleep(unsigned long MilliSeconds)
{
usleep(MilliSeconds*1000); //convert to microseconds
}
#endif // defined COMPILE_FOR_LINUX
#if defined COMPILE_FOR_LPC21
/** Provide linux replacement for windows function.
\note I implement that one in my private header file today...
\param [in] Milliseconds the time to wait for in milliseconds.
*/
/*static void Sleep(unsigned long MilliSeconds)
{
# warning Sleep function not implemented
}
*/
#endif // defined COMPILE_FOR_LPC21
/************* Applicationlayer. */
#if !defined COMPILE_FOR_LPC21
/***************************** DebugPrintf ******************************/
/** Prints a debug string depending the current debug level. The higher
the debug level the more detail that will be printed. Each print
has an associated level, the higher the level the more detailed the
debugging information being sent.
\param [in] level the debug level of the print statement, if the level
is less than or equal to the current debug level it will be printed.
\param [in] fmt a standard printf style format string.
\param [in] ... the usual printf parameters.
*/
static void DebugPrintf( int level, const char *fmt, ...)
{
va_list ap;
if( level <= debug_level)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -