📄 lpc21isp.c
字号:
} TARGET;
typedef struct
{
unsigned long id;
unsigned Product;
unsigned FlashSize; /* in kiB, for informational purposes only */
unsigned RAMSize; /* in kiB, for informational purposes only */
unsigned FlashSectors; /* total number of sectors */
unsigned MaxCopySize; /* maximum size that can be copied to Flash in a single command */
const int *SectorTable; /* pointer to a sector table with constant the sector sizes */
} LPC_DEVICE_TYPE;
typedef struct
{
#if !defined COMPILE_FOR_LPC21
TARGET micro; /**< The type of micro that will be
* programmed. */
int debug_level;
unsigned char TerminalAfterUpload;
unsigned char FormatHex;
unsigned char ControlLines;
unsigned char LogFile;
char *input_file; /**< Name of the file to get input from. */
char *serial_port; /**< Name of the serial port to use to
* communicate with the microcontroller.
* Read from the command line. */
#endif // !defined COMPILE_FOR_LPC21
unsigned char TerminalOnly;
unsigned char DetectOnly;
unsigned char WipeDevice;
unsigned char LocalEcho;
unsigned char Verify;
int DetectedDevice; /* index in LPCtypes[] array */
char *baud_rate; /**< Baud rate to use on the serial
* port communicating with the
* microcontroller. Read from the
* command line. */
char StringOscillator[6]; /**< Holds representation of oscillator
* speed from the command line. */
BINARY *BinaryContent; /**< Binary image of the */
/* microcontroller's memory. */
unsigned long BinaryLength;
unsigned long BinaryOffset;
unsigned long StartAddress;
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
HANDLE hCom;
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
int fdCom;
#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
#if defined COMPILE_FOR_LINUX
struct termios oldtio, newtio;
#endif // defined COMPILE_FOR_LINUX
unsigned serial_timeout_count; /**< Local used to track
* timeouts on serial port read. */
} ISP_ENVIRONMENT;
static void DumpString(int level, const void *s, size_t size, const char *prefix_string);
static void SendComPort(ISP_ENVIRONMENT *IspEnvironment, const char *s);
static void ReceiveComPort(ISP_ENVIRONMENT *IspEnvironment, void *Answer, unsigned long MaxSize, unsigned long *RealSize, unsigned long WantedNr0x0A,unsigned timeOutMilliseconds);
static void PhilipsOutputErrorMessage(unsigned char ErrorNumber);
static unsigned char GetErrorNumber(const char *Answer);
static void SerialTimeoutSet(ISP_ENVIRONMENT *IspEnvironment, unsigned timeout_milliseconds);
static void SerialTimeoutTick(ISP_ENVIRONMENT *IspEnvironment);
static int SerialTimeoutCheck(ISP_ENVIRONMENT *IspEnvironment);
#if !defined COMPILE_FOR_LPC21
static int debug_level = 2;
static void DebugPrintf( int level, const char *fmt, ...);
static void ClearSerialPortBuffers(ISP_ENVIRONMENT *IspEnvironment);
static void ControlModemLines(ISP_ENVIRONMENT *IspEnvironment, unsigned char DTR, unsigned char RTS);
static unsigned char Ascii2Hex(unsigned char c);
#endif
static const int SectorTable_210x[] = { 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
8192, 8192, 8192, 8192, 8192, 8192, 8192 };
static const int SectorTable_2103[] = { 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096 };
static const int SectorTable_211x[] = { 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
8192, 8192, 8192, 8192, 8192, 8192, 8192, };
static const int SectorTable_212x[] = { 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
65536, 65536, 8192, 8192, 8192, 8192, 8192, 8192,
8192 };
static const int SectorTable_213x[] = { 4096, 4096, 4096, 4096, 4096, 4096, 4096, 4096,
32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768,
32768, 32768, 32768, 32768, 32768, 32768, 4096, 4096,
4096, 4096, 4096 };
static int SectorTable_RAM[] = { 65000 };
static LPC_DEVICE_TYPE LPCtypes[] =
{
{ 0, 0, 0 }, /* unknown */
{ 0x0004FF11, 2103, 32, 8, 8, 4096, SectorTable_2103 },
{ 0xFFF0FF12, 2104, 128, 16, 15, 8192, SectorTable_210x },
{ 0xFFF0FF22, 2105, 128, 32, 15, 8192, SectorTable_210x },
{ 0xFFF0FF32, 2106, 128, 64, 15, 8192, SectorTable_210x },
{ 0x0101FF12, 2114, 128, 16, 15, 8192, SectorTable_211x },
{ 0x0201FF12, 2119, 128, 16, 15, 8192, SectorTable_211x },
{ 0x0101FF13, 2124, 256, 16, 17, 8192, SectorTable_212x },
{ 0x0201FF13, 2129, 256, 16, 17, 8192, SectorTable_212x },
{ 0x0002FF01, 2131, 32, 8, 8, 4096, SectorTable_213x },
{ 0x0002FF11, 2132, 64, 16, 9, 4096, SectorTable_213x },
{ 0x0002FF12, 2134, 128, 16, 11, 4096, SectorTable_213x },
{ 0x0002FF23, 2136, 256, 32, 15, 4096, SectorTable_213x },
{ 0x0002FF25, 2138, 512, 32, 27, 4096, SectorTable_213x },
{ 0x0402FF01, 2141, 32, 8, 8, 4096, SectorTable_213x },
{ 0x0402FF11, 2142, 64, 16, 9, 4096, SectorTable_213x },
{ 0x0402FF12, 2144, 128, 16, 11, 4096, SectorTable_213x },
{ 0x0402FF23, 2146, 256, 40, 15, 4096, SectorTable_213x },
{ 0x0402FF25, 2148, 512, 40, 27, 4096, SectorTable_213x },
{ 0x0301FF13, 2194, 256, 16, 17, 8192, SectorTable_212x },
{ 0x0301FF12, 2210, 0, 16, 0, 8192, SectorTable_211x }, /* table is a "don't care" */
{ 0x0401FF12, 2212, 128, 16, 15, 8192, SectorTable_211x },
{ 0x0601FF13, 2214, 256, 16, 17, 8192, SectorTable_212x },
/* 2290; same id as the LPC2210 */
{ 0x0401FF13, 2292, 256, 16, 17, 8192, SectorTable_212x },
{ 0x0501FF13, 2294, 256, 16, 17, 8192, SectorTable_212x },
{ 0x0603FB02, 2364, 128, 34, 11, 4096, SectorTable_213x },
{ 0x0603FB23, 2366, 256, 58, 15, 4096, SectorTable_213x },
{ 0x0603FB25, 2368, 512, 58, 27, 4096, SectorTable_213x },
{ 0x0703FF25, 2378, 512, 58, 27, 4096, SectorTable_213x },
{ 0x0503FF35, 2458, 512, 98, 27, 4096, SectorTable_213x },
{ 0x0603FF35, 2468, 512, 98, 27, 4096, SectorTable_213x }
};
/************* Portability layer. Serial and console I/O differences */
/* are taken care of here. */
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
static int kbhit( void);
static int getch( void);
#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
static void PrepareKeyboardTtySettings(void);
static void ResetKeyboardTtySettings(void);
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_CYGWIN
struct termios keyboard_origtty;
#endif
#if defined COMPILE_FOR_LINUX
static void Sleep(unsigned long MilliSeconds);
#endif // defined COMPILE_FOR_LINUX
#if !defined COMPILE_FOR_LPC21
static void OpenSerialPort(ISP_ENVIRONMENT *IspEnvironment)
{
// Open COM-Port (different between Windows and Linux)
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
DCB dcb;
COMMTIMEOUTS commtimeouts;
IspEnvironment->hCom = CreateFile(IspEnvironment->serial_port, GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(IspEnvironment->hCom == INVALID_HANDLE_VALUE)
{
DebugPrintf( 1, "Can't open COM-Port %s ! - Error: %ld\n", IspEnvironment->serial_port, GetLastError());
exit(2);
}
DebugPrintf( 3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
GetCommState(IspEnvironment->hCom, &dcb);
dcb.BaudRate = atol(IspEnvironment->baud_rate);
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
if(SetCommState(IspEnvironment->hCom, &dcb) == 0)
{
DebugPrintf( 1, "Can't set baudrate %s ! - Error: %ld", IspEnvironment->baud_rate, GetLastError());
exit(3);
}
SetCommMask(IspEnvironment->hCom,EV_RXCHAR | EV_TXEMPTY);
commtimeouts.ReadIntervalTimeout = MAXDWORD;
commtimeouts.ReadTotalTimeoutMultiplier = 0;
commtimeouts.ReadTotalTimeoutConstant = 1;
commtimeouts.WriteTotalTimeoutMultiplier = 0;
commtimeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(IspEnvironment->hCom, &commtimeouts);
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
#if defined COMPILE_FOR_LINUX
IspEnvironment->fdCom = open(IspEnvironment->serial_port, O_RDWR | O_NOCTTY | O_NONBLOCK );
if(IspEnvironment->fdCom < 0)
{
DebugPrintf( 1, "Can't open COM-Port %s !\n", IspEnvironment->serial_port);
exit(2);
}
DebugPrintf( 3, "COM-Port %s opened...\n", IspEnvironment->serial_port);
/* clear input & output buffers, then switch to "blocking mode" */
tcflush(IspEnvironment->fdCom, TCOFLUSH);
tcflush(IspEnvironment->fdCom, TCIFLUSH);
fcntl(IspEnvironment->fdCom, F_SETFL, fcntl(IspEnvironment->fdCom, F_GETFL) & ~O_NONBLOCK);
tcgetattr(IspEnvironment->fdCom, &IspEnvironment->oldtio); /* save current port settings */
bzero(&IspEnvironment->newtio, sizeof(IspEnvironment->newtio));
IspEnvironment->newtio.c_cflag = CS8 | CLOCAL | CREAD;
#ifdef __APPLE__
#define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_ispeed = IspEnvironment->newtio.c_ospeed = bps;
#else
#define NEWTERMIOS_SETBAUDARTE(bps) IspEnvironment->newtio.c_cflag |= bps;
#endif
switch(atol(IspEnvironment->baud_rate))
{
#ifdef B1152000
case 1152000: NEWTERMIOS_SETBAUDARTE( B1152000 ); break;
#endif // B1152000
#ifdef B576000
case 576000: NEWTERMIOS_SETBAUDARTE( B576000 ); break;
#endif // B576000
#ifdef B230400
case 230400: NEWTERMIOS_SETBAUDARTE( B230400 ); break;
#endif // B230400
#ifdef B115200
case 115200: NEWTERMIOS_SETBAUDARTE( B115200 ); break;
#endif // B115200
#ifdef B57600
case 57600: NEWTERMIOS_SETBAUDARTE( B57600 ); break;
#endif // B57600
#ifdef B38400
case 38400: NEWTERMIOS_SETBAUDARTE( B38400 ); break;
#endif // B38400
#ifdef B19200
case 19200: NEWTERMIOS_SETBAUDARTE( B19200 ); break;
#endif // B19200
#ifdef B9600
case 9600: NEWTERMIOS_SETBAUDARTE( B9600 ); break;
#endif // B9600
default:
{
DebugPrintf( 1, "unknown baudrate %s\n", IspEnvironment->baud_rate);
exit(3);
}
}
IspEnvironment->newtio.c_iflag = IGNPAR | IGNBRK | IXON | IXOFF;
IspEnvironment->newtio.c_oflag = 0;
/* set input mode (non-canonical, no echo,...) */
IspEnvironment->newtio.c_lflag = 0;
cfmakeraw(&IspEnvironment->newtio);
IspEnvironment->newtio.c_cc[VTIME] = 1; /* inter-character timer used */
IspEnvironment->newtio.c_cc[VMIN] = 0; /* blocking read until 0 chars received */
tcflush(IspEnvironment->fdCom, TCIFLUSH);
tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->newtio);
#endif // defined COMPILE_FOR_LINUX
}
static void CloseSerialPort(ISP_ENVIRONMENT *IspEnvironment)
{
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
CloseHandle(IspEnvironment->hCom);
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
#if defined COMPILE_FOR_LINUX
tcflush(IspEnvironment->fdCom, TCOFLUSH);
tcflush(IspEnvironment->fdCom, TCIFLUSH);
tcsetattr(IspEnvironment->fdCom, TCSANOW, &IspEnvironment->oldtio);
close(IspEnvironment->fdCom);
#endif // defined COMPILE_FOR_LINUX
}
#endif // !defined COMPILE_FOR_LPC21
/***************************** SendComPortBlock *************************/
/** Sends a block of bytes out the opened com port.
\param [in] s block to send.
\param [in] n size of the block.
*/
static void SendComPortBlock(ISP_ENVIRONMENT *IspEnvironment, const void *s, size_t n)
{
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
unsigned long realsize;
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
DumpString( 4, s, n, "Sending ");
#if defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
WriteFile(IspEnvironment->hCom, s, n, &realsize, NULL);
#endif // defined COMPILE_FOR_WINDOWS || defined COMPILE_FOR_CYGWIN
#if defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
write(IspEnvironment->fdCom, s, n);
#endif // defined COMPILE_FOR_LINUX || defined COMPILE_FOR_LPC21
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -