/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss or reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

/** @addtogroup tool */
/** @{ */
/** 	@defgroup lpc_rsa		lpc-rsa, a key extractor for RSA */
/** 	@defgroup lpc_clk		lpc-clk, a clock calculation tool */
/** 	@defgroup lpc_prg		lpc-prg, a serial programmer (needs Tcl/Tk) */
/**		@defgroup lpc_prg_lib	Serial programming C library */
/**		@defgroup lpc_prg_tcl	Serial programming Tcl library */
/** @} */

/** @addtogroup tool

The library comes with a few command line tools.

These tools are built on your host machine and can be found in the <tt>bin</tt>
direcory within your installation directory. Here you can find the usage
instructions for these tools.

*/

/** @addtogroup lpc_clk

LPCxxxx PLL and UART calculator tool.
This program can calculate the PLL settings for a given clock source
and desired CPU clock frequency. In addition, it can calculate the
UART's division parameters (integer and fractional) for a given set
of baud rates.

@section tool_clk_u	Usage
<tt>lpc-clk <i>options list_of_baud_rates</i></tt>
<br><br>
The output of the program is in the format of a valid C header file,
so you can incorporate it in your sources and use the generated values
without actually typing them from the screen.
If you start the program without any command line switches, it will print
a usage message that details all options. It will also list all the chips
which it knows.<br><br>
If you supply the required parameters on the command line, then the
program calculates the PLL and UART settings, formats them so that they
can be included in your C source and prints the result on the standard
output, which you can redirect to a file. The requirements and the actual
achieved values and deviations are also written as C comments.<br>
The following list tells you what can possibly be defined in the output.
Some of these definitions may be omitted, due to not being requested or
the given chip not supporting the given feature. The names below all
start with <tt>CLOCK_</tt>, but that can be changed with a command line
option. All defined values are integers.
@verbatim
CLOCK_XTAL       is the crystal frequency, in Hz
CLOCK_CCLK       is the (achieved) CPU frequency, in Hz
CLOCK_PLL_M      is the 'M' value for the PLL
CLOCK_PLL_N      is the 'N' value for the PLL
CLOCK_PLL_P      is the 'P' setting for the PLL
CLOCK_CPU_DIV    is the CPU clock division value
CLOCK_USB_DIV    is the USB clock division value
CLOCK_MAM_TIM    is the minimum MAM time value
CLOCK_RTC_DIV    is the peripheral clock prescaler code for the RTC
CLOCK_RTC_CLK    is the actual prepheral clock for the RTC, in Hz
CLOCK_RTC_INT    is the RTC fractional divider integer value
CLOCK_RTC_FRA    is the RTC fractional divider remainder value
CLOCK_SIO_DIV    is the peripheral clock prescaler code for the UART
CLOCK_SIO_CLK    is the actual prepheral clock for the UART, in Hz
@endverbatim
Further definitions are emitted for the UART, their format is explained under
the <b>-a</b> option. In case of an error, an error message is sent to
<tt>stderr</tt>.<br>
Note that the PLL_M and PLL_N as well as the CPU_DIV and USB_DIV values are
the actual numbers (from which you have to subtract 1 before you write them
into the relevant register), the PLL_P, RTC_DIV and SIO_DIV values are the
actual field values as encoded by the chip. It is because there is no simple
mapping between the codes and values for the latter set. For the same reason
the chip header files in the package are expecting the values exactly in the
format generated by this tool. For example, booting the PLL on an LPC2103
using the values calculated by this tool and the headers from this package
looks something like this:
@code
#include "clock.h" 				// The file generated by the tool
#include <chips/LPC210x/scb.h>	// The header for the SCB module of the chip
	...

	// Load the PLL divisor values

	lpc_scb->pllcfg	 = SCB_PLLCFG_MSEL( CLOCK_PLL_M ) |
					   SCB_PLLCFG_PSEL( CLOCK_PLL_P );
	lpc_scb->pllfeed = SCB_PLLFEED_FOOD1;
	lpc_scb->pllfeed = SCB_PLLFEED_FOOD2;

	// Enable the PLL

	lpc_scb->pllcon	 = SCB_PLLCON_PLLE;
	lpc_scb->pllfeed = SCB_PLLFEED_FOOD1;
	lpc_scb->pllfeed = SCB_PLLFEED_FOOD2;

	// Wait for the PLL to stabilise

	while ( ! ( lpc_scb->pllstat & SCB_PLLSTAT_PLOCK ) );

	// Connect the PLL.

	lpc_scb->pllcon  = SCB_PLLCON_PLLE | SCB_PLLCON_PLLC;
	lpc_scb->pllfeed = SCB_PLLFEED_FOOD1;
	lpc_scb->pllfeed = SCB_PLLFEED_FOOD2;

	// Now we're running from our nominal clock, enable memory acceleration.

	lpc_scb->mamtim  = CLOCK_MAM_TIM;
	lpc_scb->mamcr	 = SCB_MAMCR_MODE_FULL;

	// Load the peripheral clock divider, as per the UART settings

	lpc_scb->apbdiv  = CLOCK_SIO_DIV;

	...
@endcode

@section tool_clk_o Options
- <tt><b>-d <i>device</i></b></tt><br>
	Specifies the device. It is an integer, which is the chip's type with
	the leading LPC part omitted. The list of known chips can be obtained
	by starting the tool without any arguments.<br>
    For backward compatibility reasons this option defaults to 2378.

- <tt><b>-x <i>xtal</i></b></tt><br>
    The reference clock frequency (float)<br>
    If the number is less than 100, it is taken as MHz, otherwise as Hz.
    Values between 32.768kHz and 40MHz are accepted.<br>
    This option is mandatory.

- <tt><b>-c <i>cclk</i></b></tt><br>
    The required CPU clock (float).<br>
    If the number is less than 100, it is taken as MHz, otherwise as Hz.<br>
    This option is mandatory.

- <tt><b>-s <i>stem</i></b></tt><br>
	The name stem for all definitions. It defaults to <tt>CLOCK</tt>.
	The program does not check if the stem is a valid C identifier or not.

- <tt><b>-h <i>max_clock</i></b></tt><br>
    Maximum CPU clock (float).<br>
    If the number is less than 100, it is taken as MHz, otherwise as Hz.
    The default is 60MHz or the specified clock (whichever is larger).
    If you specify a value that is less than the requested clock frequency
    the the requested clock frequency will be used instead.
    This value is only used if the required CPU clock can not be exactly
    achieved. A value close to the requested frequency will be accepted if
    it is not higher than this value.

- <tt><b>-l <i>min_clock</i></b></tt><br>
    Minimum CPU clock (float).<br>
    If the number is less than 100, it is taken as MHz, otherwise as Hz.
    The default is 0. If you specify a value that is more than the requested
    clock frequency then the requested clock frequency will be used instead.
    This value is only used if the required CPU clock can not be exactly
    achieved. A value close to the requested frequency will be accepted if
    it is not lower than this value.

- <tt><b>-u <i>max_error</i></b></tt><br>
	 Maximum USB error (float).<br>
    Indicates that USB is needed. In that case the VCO frequency must be
    set to an exact multiple of 96MHz. The parameter indicates the maximum
	 frequency error, in ppm. Specifying 0 or a negative value disables the
    USB calculations. The default is 0. Suggested value is 500ppm.

- <tt><b>-p <i>n</i></b></tt><br>
    The peripheral clock divider for the UART's clock (1, 2, 4 or 8).<br>
    For chips with only one peripheral divider, if this option is specified
    and the <b>-r</b> option is also specified, the two values must be the
    same. If this option is omitted but the <b>-r</b> option is used, then
    the value specified there will be used. If neither <b>-p</b> nor <b>-r</b>
    are used, then the default value of 4 will be used.

- <tt><b>-r <i>n</i></b></tt><br>
    The peripheral clock divider for the RTC's clock (1, 2, 4 or 8).<br>
    If the value is specified, then RTC calculations will be performed.
    For chips with only one peripheral divider, if this option is specified
    and the <tt>-p</tt> option is also specified, the two values must be the
    same.

- <tt><b>-i <i>string</i></b></tt><br>
    The identifier to be used for the \#ifndef directive protecting the
    header file from multiple inclusions. It must be a valid C identifier.
    The program does *not* check the validity of the string, it uses it
    verbatim. The default is <tt>_LPC_CLOCK_TOOL</tt>.

- <tt><b>-a</b></tt><br>
    Selects the alternate format for UART calculations.<br>
    The default is to create three definitions for each baudrate:<br>
	<tt>CLOCK_SIO_I_<i>XXXX</i></tt> is the UART's integer divider for baud
	rate <i>XXXX</i><br>
	<tt>CLOCK_SIO_M_<i>XXXX</i></tt> is the UART's fractional divider's
	'M' value<br>
	<tt>CLOCK_SIO_A_<i>XXXX</i></tt> is the UART's fractional divider's
	'A' value<br>
    The alternative format is that an initialiser is defined for an
    array of structures. The structure has to have 4 members, the first
    one is the baud rate, the next one is the integer divider value,
    then the fractional divider's M value and finally the fractional
    divider's A value. The suggested member sizes are int, short,
    char and char, all unsigned. The initialiser is called
    <tt>CLOCK_SIO_TABLE</tt> and can be used like this:
	@code
	// Structure to store the baud rate parameters

	typedef struct {
		unsigned int	b;	// Baud rate
		unsigned short	i;	// Integer divisor
		unsigned char	m;	// Fractional divider M value
		unsigned char	a;	// Fractional divider A value
	} BAUDS;

	// Table holding the baud rates

	static const BAUDS brate_table[] = { CLOCK_SIO_TABLE };
	@endcode

@section tool_clk_b List of baud rates
It is an optional list of integers, separated by space. Each number is
a baud rate for which the divisor values should be calculated. For example,
the list<br>
<tt>9600 38400 115200</tt><br>
will make the tool calculate the divisor values for three common baud rates.

@section tool_clk_e Exit code

0 : success<br>
1 : command line format error or illegal parameter value<br>
2 : the requirements could not be satisfied

*/

/** @addtogroup lpc_rsa

RSA key extractor.

To use the @ref rsa routines in the crypto library, you need RSA keys.
The ssh-keygen program can generate you an RSA key pair, or you may have
received a public key generated by a third party. However, the RSA routines
in the crypto library can not work with SSH format keyfiles, they have to be
transformed into a different format first. This program does just that.<br>
It reads an SSH format RSA keyfile from the standard input and generates
a C file that contains the keys as constant data, in the format that the
RSA routines in the library can use. That C file is printed on the standard
output. If there's an error the program prints an error message on the
standard error.<br>
If you start the program without any command line switches, it will print
a usage message and exit.

@section tool_rsa_u Usage

First you need an RSA key. The program can process RSA keys generated by
the SSH package's <tt>ssh-keygen</tt> program. If you want to generate
your own key (that is, your own private key/public key pair), then you
have to run the <tt>ssh-keygen</tt> program:
@verbatim
ssh-keygen -b key_length -t rsa -f key_file
@endverbatim
The <tt><i>key_length</i></tt> is the length of the key, in bits. The
minimum is 768. The value 1024 is common but 2048 bit long keys are
getting popular. The <tt><i>key_file</i></tt> argument is the name
of the file where you want your key to be stored. Two files are
generated by the program, <tt>key_file</tt> and <tt>key_file.pub</tt>
of which the former contains your private key and the latter contains
the public key. (Note that the private key file actually contains
both the private and the public keys) These files look something like
this:<br><br>
<tt>key_file</tt>:
@verbatim
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDBgRtt0/8Xx+QysgZIJDKhem8ZIdMmLUXOtsRNX0QpEiW43uvn
dFxZJ0fIIbXo9akZhwKd8OiNuOf22FyNBTyb4sIsTgFTntHIa5QMa2vegjjEvFPA
F50zZ5T2I+3zpsz/I9hPtObGQwfA0ylziSHc86lTOCEJCxMbOCRIOa7KSwIBIwKB
gDzQzhsz/7cETwieWb7mzhV+QCx4WE3TttqRNmF1tlYNBIqPNDLMzJEMWGN4Tx1U
hZpPANKNiuq2dMnsOlg02Ig2c5S2oMuT3fxOJn9DUe2w+JlX0zcOM66TE/Ak6q68
l5Qw83LlkD+rwq/3rLeKIuhtHbU+uo/9No1kyeZe1+A7AkEA/nrg4u0ND+0Mh6PV
aivxYuSMjQRVgg0kLkZqBDz75k2U0He95nfhEgK6qRJUa8KpDLC1DVxDKryCHhVS
KbQ1GQJBAMKo/eAr7VtQ9jEYohPG4Y8l8y8ju2hf+wg9p00jV2huks7lmJbpvYLf
Yed9NDdNORdrjAYWEwB6eh8vdigF4wMCQQDoqtw9MID4njdXcTgmjpONncJVC0bd
Tdfvy1mdeZXZ4IgPDmR68ULOo2jVGBKrqqkwLIhGusERIWEFj9YXgDCLAkEAliqX
9hNCEz50xsncHeKQvuLC6dm8dRbXmKSXAP4BmbRin5sskaz/6J2x7RdxbH1mjmjo
XHdtvopeNVB/uHmR3QJBAM8KaCsomBTERjK7/hpnWXaiCMBo5qFwBhVKNRi0KkHt
xeeqBo7d19h6FhmtvrzYc+39SH3wTEnWG/xWqam6+fs=
-----END RSA PRIVATE KEY-----
@endverbatim
<tt>key_file.pub</tt>:
@verbatim
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwYEbbdP/F8fkMrIGSCQyoXpvGSHT
Ji1FzrbETV9EKRIluN7r53RcWSdHyCG16PWpGYcCnfDojbjn9thcjQU8m+LCLE4B
U57RyGuUDGtr3oI4xLxTwBedM2eU9iPt86bM/yPYT7TmxkMHwNMpc4kh3POpUzgh
CQsTGzgkSDmuyks= user@hostname
@endverbatim
When you want to transform a keyfile into a format usable by the
RSA functions of the crypto library, you have to invoke the
<tt>lpc-rsa</tt> program, the one of which the documentation you're
now reading:
<br><br>
<tt>lpc-rsa <i>options</i> \< <i>key_file</i> \> <i>mykeys.c</i></tt>
<br><br>
That is, the program reads a keyfile generated by <tt>ssh-keygen</tt>
on the standard input and generates a C file on the standard output.
The C file will contain the RSA key(s) in a format that's usable by
the RSA functions in the library.

@section tool_rsa_o Options

- <tt><b>-private<br>-public<br>-both<br></b></tt>
	One and only one of the above three options must be given. It makes
	the program to extract the public key, the private key or both keys,
	respectively. If, and only if you specified <tt>-public</tt>, then the
	program accepts a public key file on the input (but it still accepts
	the private key file as well). For the other two cases you must pass
	the private key file to the program. Using the public key file might
	be necessary if the keys are generated by a third party, in which
	case naturally you only have access the public key.

- <tt><b>-stem </b><i>identifier</i></tt><br>
	The extracted key(s) are stored in structures. This option sets
	the name stem for the structures. The default is <tt>rsa</tt>.
	The structure(s) defined in the C file will be<br>
	<br>
	<tt><b>const</b> BC_RSA_PUBLIC_KEY <i>stem</i>_public_key;<br>
	<b>const</b> BC_RSA_PRIVATE_KEY <i>stem</i>_private_key;</tt><br><br>
	for the public and/or private key, respectively.

@section tool_rsa_e Exit code

0 : success<br>
1 : command line error<br>
2 : key file error

*/

/** @addtogroup lpc_prg_lib

The LPC2xxx series chips have an on-chip bootloader that allows programming
the chip through a serial line, eliminating the need for a JTAG interface
hardware. This library provides access to the LPC2xxxx ISP (In-System
Programming) functionality. It can be used to read/write the FLASH of the
target chip, read or write the RAM and execute code on the target. In addition,
convenience functions are provided to load and store files in Motorola S-record
or Intel-hex format.
<br><br>
The library has several function groups.

@section lpc_prg_lib_top	Highest level functions

Before using it, you have to open the library using the LPC_Open() call. It
will return a pointer to an opaque object, containing all the internal state
of the library. You will need to supply this object to every call.<br>
In this group you also find logging functions, so that you can trace what
goes on between your computer and the target.

@section lpc_prg_lib_ser	Serial port low level functions

All functions in this group has an <tt>LPC_Serial</tt> prefix. This group
contains the functionality that deals with the low level control of the
serial port. Apart from opening the port, if you only want to program
the target or read its content, you will not need to use these functions.
They are provided, however, to facilitate you writing your own access
functions to the target.

@section lpc_prg_lib_tgt	Target functions

This group, which has the prefix of <tt>LPC_Target</tt> contains the
functions that can be used to establish a link to the target, to access
its FLASH and RAM. These functions deliver the functionality provided by
the ISP of the target but hide the actual low level serial communication
details.

@section lpc_prg_lib_log	Logging functions

*/

/** @addtogroup lpc_prg

A very simple programming tool. Although this tool is fairly limited, it is
sufficient to program a target board through the serial port and it even
provides a very simple console to talk to your application. The tool is
actually a <tt>wish</tt> (the Tk shell) script, therefore you can only
use it if you have Tcl/Tk installed. The script assumes that <tt>wish</tt>
can be found in the <tt>/usr/bin</tt> directory.

Also, the program relies on the @ref lpc_prg_tcl.
Thus, you have to have that library in your library path. If you installed
the library at the default location, that means that you will have to add
the following lines to you shell init script (if you use bash or similar):

<tt>LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/armlib/bin<br>
export LD_LIBRARY_PATH</tt>

@section lpc_prg_u	Usage

When you start the program, you will get a simple GUI:
@image html programmer.png
As you can see, it is divided to several panels:

@subsection lpc_prg_u_serial Serial port settings

The bottom panel deals with the serial port settings. You can set the serial
device by clicking in the field and editing it; you have to press Enter to
finalise the editing. You have to specify the full pathname to the serial
device file, i.e. <tt>/dev/ttyS0</tt> or <tt>/dev/ttyUSB2</tt> or similar.

Underneath the device selection you will find three spinboxes that set the
initial baudrate and the maximum baudrate to use while talking to the target
chip's ISP and a third baud rate to use when the serial console is talking
to your application code. Note that it is best to leave the initial baud
rate at 9600 baud, it is in use for a very short time anyway.

The reset and the ISP lines of your target can be controlled manually
or automatically, which you can select using the bottom-left radiobuttons.
If you choose manual mode, every time one of those signals must be changed,
you will get a message box asking you to assert or negate it. In case of
automatic control, which you can only use if your reset and ISP signals are
connected to the serial port's RTS and DTR signals, you have to specify
whether you connected the reset to RTS or DTR (and, obviously, ISP to the
other one). Furthermore, you have to specify if you inverted any of these
signals. The non inverted signal means that you logically connected the
serial chip's TTL level RTS and DTR, which are active low signals, to reset
and ISP (or the other way around), which also are active low signals. On the
RS-232 lines it means that whenever the RS-232 signal is active (i.e. it is
above +3V) you have to activate (i.e. pull down) the target's reset or ISP.

@subsection lpc_prg_u_trace Trace

The middle-right panel is your trace panel. Most of the time you do not need
it, but it can be handy to debug serial problems. The <tt>Open trace window</tt>
button opens a window where internal messages from the low level C library,
@ref lpc_prg_lib are shown. Error messages are always shown. Target action
messages tell you what is happening through the ISP command set, at a high
level, such as reading/writing memory, erasing sectors and so on. If you are
interested in the actual communication between your computer and the target
chip, enable the serial comms tracing as well. The file I/O trace tells you
about opening files, reading/writing them and so on. Finally, if you enable
timstamping, then each log entry will have a timestamp, which is the time
since the previous log entry, in milliseconds. If you opened the trace window,
the button will change from open to close and you can use that to close the
window, if you don't need it any more.

@subsection lpc_prg_u_target Target

The target panel has only one field that you can edit. It is the target chip's
clock frequency, in MHz. It is only important for chips that do not start up
from an internal RC oscillator, such as the LPC2103. For chips that come up
with an internally generated clock, this value is ignored. However, if it is
set to the frequency of the internal clock, connecting becomes a tad faster.
In any case, after connecting to the target, if the target has an internal
clock, this field will be automatically set to the correct value. If you edit
this field, you have to finish your editing by pressing Enter.

Below the clock field there are three fields that tell you information about
the target if you are connected. The bottom line of the target panel is used
to give you a progress feedback for slower operations.

@subsection lpc_prg_u_option Options

The tool can handle Motorola S-record or Intel hex file formats. You can
select one or the other to be used for all further file operations.

When you burn the FLASH in the target chip, you can select one of three
modes. The simplest case is to erase only the sectors into which your
code will go. That is, if you burn a 200 byte long code into an LPC2378,
only the first 4KB of the FLASH (i.e. the first sector) will be erased,
the remaining 500KB will not be touched.<br>
By choosing <tt>Erase the entire FLASH</tt> you can tell the tool to wipe
the whole chip before burning your code into it.<br>
Your third option is to keep every byte in the FLASH that is not actually
modified by your code. Although sectors modified by your code must be erased
entirely, they will be read from the chip and merged with your code before
the sector gets erased and burned.

If you save the content of the chip's FLASH into a file, you can choose
not to save erased (i.e. containing 0xFF) sections. This makes your save
file smaller, if you use only part of the FLASH.

In addition, you can tell the tool to automatically calculate the checksum
of the vector table that the chip's ISP uses to decide whether to start the
application or not. Note that the vector table checksum is only calculated if
you loaded code into the vector table area (the first 32 bytes of the FLASH).

The manual power control option is helpful when your target chip gets
seemingly unprogrammable. Due to a bug in the ISP code in the LPC2xxx
chips, under certain circumstances the chip ignores the ISP line after
reset, thus it starts the application code. However, if you power cycle
the chip and keep reset low when you apply the power, you can force it
to go to ISP mode. If you turn that option on, you will get a message
box asking you to remove or apply the power so that the above method
can be used to recover a chip that went to gaga land. It is a rarely
needed option, but at those occasions it is indeed very useful.

@subsection lpc_prg_u_actions Actions

Initially, you can only connect to the target. Pressing the <tt>Connect</tt>
button makes the program to attempt to drive the chip into ISP mode and
get its identifier. If that fails, you get an error message. If it succeeds,
then the button changes from <tt>Connect</tt> to <tt>Disconnect</tt> and
the other actions become available.

The <tt>Load hexfile</tt> button pops up a file selection box. You can select
a hexfile, which will be loaded into the internal buffer of the program. The
hexfile must not contain addresses outside of the range of the target's
FLASH.

The <tt>Save the FLASH</tt> button copies the content of the chip into the
program's internal buffer then saves the buffer content into a hexfile.
You have to provide the name of the hexfile, naturally. Note that this
command makes the program's buffer to be a copy of the FLASH, therefore
any previously loaded data will be lost.

The <tt>Burn the FLASH</tt> button burns the content that was loaded into
the buffer into the target's FLASH, optionally calculating the checksum for
the vector table before doing so.

The <tt>Start console</tt> button opens the console window, see below.
Once you start the console, you will lose the content of the buffer and
you will have to re-connect to the chip.

@subsection lpc_prg_u_console The console window

*/

/** @addtogroup lpc_prg_tcl

An other programming library to be used from Tcl scripts.

Based on the @ref lpc_prg_lib an other shared library is created, which you
can load into a Tcl interpreter and have access to the functions provided
by the C library from your Tcl or Tk script. That allows you to put together
a programmer (even a GUI one) probably faster than if you had to write it in
C. In fact the programming tool @ref lpc_prg supplied with the package
is actually a Tk application using this library. Note that the library is
created only if you have Tcl 8.4 or newer on your system.

To use the library, you have to have the <tt>bin</tt> directory under the
installation directory in your library path, for example by adding the
line:

<tt>LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/armlib/bin</tt>

to your shell init script; alternatively you can copy the library files from
that directory to your system library directory or you can add the location
to <tt>/etc/ld.so.conf</tt>.

Then you can load the library by putting the following line at the beginning
of your Tcl or Tk script:

<tt>load liblpctcl.so</tt>

The library defines a single Tcl command <tt>lpcprg</tt> which represents the
entry point for all library procedures. Most procedures return nothing.
For the ones that do, the return value is described in the individual
procedure description.

In case of any error all of the procedures return with an error code of 1
(i.e. error). <i>Note that this is not the return value but a success code.
See the man page for <tt>return(n)</tt> for details.</i> Normally the Tcl
interpreter will exit if it receives an error, so if you want graceful
error handling you have to invoke the procedures through the
<tt><b>catch</b></tt> command. When a procedure fails, it sets ist return value
to the error message, which you can obtain through <tt>catch</tt>. Furthermore,
if the error occured in the underlying C library, you can obtain an other
error message by calling the <tt>lpclib errormsg</tt> procedure (which never
fails). That error message might contain a more detailed description of the
reason for the error (although not necessarily).

The following procedures are defined:

@section lpc_prg_tcl_log Logging commands

- <tt><b>lpcprg logproc</b> <i>procedure argument</i></tt><br>
	The <tt><i>procedure</i></tt> argument is the name of a Tcl procedure.
	The procedure must take two arguments. Whenever the underlying C library
	has anything to log, the given Tcl procedure will be called with two
	arguments. The first argument is the same as the <tt><i>argument</i></tt>
	passed to this procedure. The second is a string containing the log entry.
	The string is not terminated by newline. For example, you could use the
	following code to simply print the log messages to the stdout:
	@code
	proc mylog { unused logmsg } {
		puts $logmsg
	}
	...
	load liblpctcl.so
	...
	lpcprg logproc mylog ""
	@endcode
	The procedure does not have to exist at the time of the call, it will
	only be looked up when logging takes place. If the procedure is not
	found, then the logging routine silently discards the log message.<br>
	If you omit the arguments, then the callback will be deleted and no
	further logging is done until you issue the command with the arguments
	again.

- <tt><b>lpcprg logon</b> <i>logtype1 logtype2 ...</i></tt><br>
	Enables the logging of the given events. Errors are always logged.
	This command can be used to enable the logging of all other event types.
	The following log types are defined:
	- <tt><b>serial</b></tt><br>
		Logs everything that happens through the serial port. That includes
		the opening of the port, changes to modem control signals, transmit
		and receive data and read timeouts.<br>
		Note that when you go into monitor mode, the communication is not
		logged any more.<br>
		Log entries are marked by a <tt>[ser]</tt> tag.
		<br><br>
	- <tt><b>target</b></tt><br>
		Logs target actions, like reading, writing, erasing, testing and so
		on. It is not a log of the actual target command strings but the
		actions achieved by issuing those strings. If you want to see what
		was written to the target, use the serial logging.<br>
		Log entries are marked by a <tt>[tgt]</tt> tag.
		<br><br>
	- <tt><b>fileio</b></tt><br>
		Logs hexfile related activities. <br>
		Log entries are marked by a <tt>[i/o]</tt> tag.
		<br><br>
	- <tt><b>deltas</b></tt><br>
		Each log entry will have a timestamp which is the time elapsed
		since the last log entry, in milliseconds.

- <tt><b>lpcprg logoff</b> <i>logtype1 logtype2 ...</i></tt><br>
	Disables the logging of the given events. The logtypes are the same
	as for the <tt>lpcprg logon</tt> command.

- <tt><b>lpcprg errormsg</b></tt><br>
	Although it is not really a logging procedure, it is described in this
	group. This procedure always succeeds. It returns a string which contains
	the last low-level error message from the underlaying C library. After
	returning the error message it will be deleted internally, so subsequent
	calls of this procedure will return an empty string. The error string is
	only valid if you call this procedure after the one that failed but
	before you call any other procedure in the library.

@section lpc_prg_tcl_ser Serial port related commands

- <tt><b>lpcprg port</b> <i>device lockfile</i></tt><br>
	The command opens the <tt><i>device</i></tt> for communicating
	with the target. It is typically a real serial device, like
	<tt>/dev/ttyS0</tt> or a USB adapter, like <tt>/dev/ttyUSB0</tt> or
	similar. You must have read/write permission for the device.<br>
	The <tt>lockfile</tt> argument is optional. If you omit it, then
	the serial device will not be locked. If you specify an empty string,
	that is, <tt>""</tt>, then the <tt>flock()</tt> system call will be used.
	If you specify a real file, then that file will be used as lockfile.
	Of course if you specify for example <tt>/var/lock/ttyS0</tt> then you
	must have read/write permissions for the <tt>/var/lock</tt> directory.
	The file will contain the PID of your program.

- <tt><b>lpcprg baud</b> <i>init fast</i></tt><br>
	If no arguments are present, then the function simply returns the
	current baud rate of the serial port. If the <tt><i>init</i></tt>
	argument is present but the <tt><i>fast</i></tt> is not, then the
	latter is taken as if it was the same as the former.<br>
	The <tt><i>init</i></tt> argument is the baud rate used to contact
	the target. Using 9600 baud is a safe bet. Only 9600, 19200, 38400,
	57600 or 115200 baud are allowed, due to limitations of the ISP code
	in the LPC chips.<br>
	If the <tt><i>fast</i></tt> argument is present and is larger than
	<tt><i>init</i></tt>, then after the initial connection to the chip
	the program tries to negotiate with the target to switch to the
	faster baud rate. If the target can not use the fast baud rate, then
	the initial baud rate is retained. If the target agrees to use the fast
	rate, then both the target and your serial device is switched to that
	rate and everything will happen on that rate. The same baud rates are
	allowed as for the <tt><i>init</i></tt> argument.<br>
	When you call this procedure, the switching to the <tt><i>init</i></tt>
	rate is immediate, so if you already have connected to the target at a
	different rate, you will lose comms.

- <tt><b>lpcprg modem</b> <i>reset ISP</i></tt><br>
	In order to program an LPC2xxx chip, you have to control its reset and
	ISP signals. A convenient way to do that is to connect those signals
	to the serial port's RTS and DTR modem control signals. This call tells
	the library to use that method and specifies the way you connected the
	modem control lines to the target's reset and ISP.<br>
	The command has two arguments. The first argument associates a modem
	control signal with the target's reset while the second associates a
	modem control with the target's ISP. If you try to assign the same
	modem control signal to both target signals, you will get an error.
	The arguments themselves must be one of the following 4 strings:
	- <tt><b>+rts</b></tt><br>
		The target's signal is controlled by the RTS modem control signal.
		The target's reset or ISP is activated when the RS-232 RTS signal
		is active (i.e. it is \> +3V).
	- <tt><b>-rts</b></tt><br>
		The target's signal is controlled by the RTS modem control signal.
		The target's reset or ISP is activated when the RS-232 RTS signal
		is inactive (i.e. it is \< -3V).
	- <tt><b>+dtr</b></tt><br>
		The target's signal is controlled by the DTR modem control signal.
		The target's reset or ISP is activated when the RS-232 DTR signal
		is active (i.e. it is \> +3V).
	- <tt><b>-dtr</b></tt><br>
		The target's signal is controlled by the DTR modem control signal.
		The target's reset or ISP is activated when the RS-232 DTR signal
		is inactive (i.e. it is \< -3V).

- <tt><b>lpcprg manual</b> <i>procedure argument</i></tt><br>
	If your target's reset and ISP signals are not connected to the serial
	port's modem control signals, you can use this command to control them.
	The command has two arguments, the first is a Tcl procedure and the
	second is a parameter that will be passed to that procedure.<br>
	Whenever the library wants to change the state of a target signal it
	will call the given Tcl procedure. passing it two arguments. The first
	argument is whatever you specified as the last argument for this command.
	The second argument is a number, which is guaranteed to be between 0 and
	3, telling you what to do. You can wait in this function as much as you
	want, that is, you can just emit a message to the user to change the
	signal state and wait until (s)he confirms that it's done. The meaning
	of the numeric argument is:
	- <b>0</b> You have to assert reset (i.e. pull to GND)
	- <b>1</b> You have to negate reset (i.e. pull to Vcc)
	- <b>2</b> You have to assert ISP (i.e. pull to GND)
	- <b>3</b> You have to negate ISP (i.e. pull to Vcc)

- <tt><b>lpcprg close</b></tt><br>
	The command closes the serial port and if a chip was connected, will
	delete the current chip type. It is not an error to close the port
	if it was not open. The baud rate and control signal assignments remain
	as they were set last time.

@section lpc_prg_tcl_tgt Target commands

These commands, with the exception of <tt>connect</tt> itself can only be
issued when the target is connected. The serial port must be open, the baud
rate(s) must be set up and the signal control must be assigned.

- <tt><b>lpcprg progress</b> <i>callback argument</i></tt><br>
	Some target functions can take a long time to execute. This call
	can be used to set up a progress feedback. The feedback is provided
	by calling a TCL procedure with two arguments. The procedure to call
	is the <i>callback</i> argument. The two arguments passed to that
	procedure will be <i>argument</i> and a string, which contains some
	information about what's going on inside the library (it is always
	a human readable message).<br>
	If the procedure is called with no arguments, then the progess callback
	functionality will be disabled.

- <tt><b>lpcprg crystal</b> <i>clock-frequency</i></tt><br>
	Sets the clock frequency for the target. This procedure must be called
	before connecting to the target. The <i>clock-frequency</i> argument
	must be a float value, which is the target's clock frequency in MHz.
	Values between 4.0 and 25.0 are accepted. Not all target chips need
	this call but connecting to the chip will fail if the connect procedure
	identifies a chip that needs it and it was not set.

- <tt><b>lpcprg power</b> <i>procedure</i></tt><br>
	Under some circumstances the LPC2xxx ISP code gets into a state where
	it ignores the ISP signal after reset. In that case the only way to
	access the ISP is to power up the target while the reset is asserted.
	This call establishes a callback which can be used to tell the user
	to power up or down the target. Whenever the target power needs to
	be changed, the <i>procedure</i> Tcl procedure will be called, with
	a single integer argument. The argument is 0 if the power should be
	reoved and 1 if it should be applied. If the <i>procedure</i> parameter
	is omitted, then the callback will be deleted.

- <tt><b>lpcprg connect</b></tt><br>
	Resets the chip and attempts to connect to the target chip's ISP.

- <tt><b>lpcprg reset</b></tt><br>
	Resets the target and lets it run, without going into ISP mode.
	The serial port remains open, so communication with the target is
	still possible.

- <tt><b>lpcprg chiptype</b></tt><br>
	Returns the type of the chip that is currently connected. The returned
	value is a number, the chip's type after the LPC bit. That is, for an
	LPC2378 the procedure returns 2378.

- <tt><b>lpcprg flash</b></tt><br>
	Returns the amoutn of FLASH in the chip that is currently connected.
	The returned value is a number, the size of the target's FLASH in KB.

- <tt><b>lpcprg send</b> <i>string</i></tt><br>
	Sends the <i>string</i> to the target through the serial port, with the
	current baud rate. This function goes over the head of all the internal
	state, thus if you do something with a connected target, you'll bear the
	consequences later. This call is intended to provide communication with
	the target running user code, not the ISP.

- <tt><b>lpcprg recv</b></tt><br>
	Reads the data from the target's serial port. Returns a string, which
	can be any long up to 1KB. If it returns an empty string, it means that
	there is nothing in the serial buffer. However, if it returns a string,
	even if one that is shorter than 1KB, that does <i>not</i> mean that
	the serial buffer has been emptied. If you want to be sure that you
	got everything that the target sent, you will have to call this procedure
	in a loop until it returns an empty string.
	Like <tt>send</tt>, this function also goes over the head of the internal
	state, with the same responsibilities.
	This call, too, is provided to communicate with the target running user
	code.

@section lpc_prg_tcl_buf FLASH buffer commands

When a chip is connected, it gets associated with a buffer of the same
size as its FLASH. That buffer is used for various file and FLASH operations.
With each byte in the buffer a state is associated. This qualifies the data
in the buffer. The following states are recognised:
-	The byte is unknown. It was not read from the FLASH and was not loaded from
	a file.
-	The byte was written by a file operation. It is not known whether the
	FLASH has the same byte in the given location or not.
-	The byte reflects the current FLASH content
-	The byte was modified by some file operation but it is known that the
	FLASH contains FF at the given location (i.e. it is erased).

Using the status information the various functions can often avoid
unnecessary FLASH operations. The following operations are defined:

- <tt><b>lpcprg format</b> <i>type</i></tt><br>
	Specifies the file format for loading and saving operations. The
	argument must be either <tt>srec</tt> or <i>ihex</i>, specifying
	Motorola S-record or Intel hex formats, respectively.

- <tt><b>lpcprg load</b> <i>file</i></tt><br>
	Loads a hexfile into the buffer. The <i>file</i> argument is the
	name of the file to read. The hexfile will be read into the buffer
	and the relevant buffer bytes will be marked as known.

- <tt><b>lpcprg save</b> <i>file trim</i></tt><br>
	Copies the target's FLASH to the buffer (thus any bytes overwritten
	by a <tt>load</tt> command will be lost then saves the entire buffer
	into a hexfile. The first argument is the name of the file. The second
	argument, <i>trim</i>, must be an integer. If it is not 0, then any
	records that would contain only FF-s (i.e. erased FLASH) will not
	be written into the file. If the second argument is 0, then every byte
	will be saved.

- <tt><b>lpcprg burn</b> <i>mode</i></tt><br>
	Burns the buffer into the target. The <i>mode</i> parameter specifies
	how the burning is done:
	- <tt>norm</tt><br>
		Specifies normal operation. Only those FLASH sectors will be erased
		that corresponds to buffer regions with bytes modified by a load
		command. All other FLASH sectors will remain intact.<br><br>
	- <tt>keep</tt><br>
		Similar to the previos option, except that it keeps the bytes that
		were not modified by the file operation. That is, this mode behaves
		as if the FLASH was read to the buffer before the hexfile was loaded
		or the buffer otherwise modified<br><br>.
	- <tt>wipe</tt><br>
		Erases the entire FLASH of the target before the write. Only bytes
		that were actually modified in the buffer will then be written, thus
		any previous information in the FLASH will be wiped.

- <tt><b>lpcprg vector</b></tt><br>
	If a previous buffer operation wrote into the first 32 bytes of the
	buffer, then this function recalculates the vector table checksum, which
	is needed to run application code on the LPC2xxx chips. The new checksum
	is written into the buffer as if it was read from a file (i.e. it will
	be marked as modified).

- <tt><b>lpcprg invalidate</b></tt><br>
	Invalidates the buffer, marking every byte as unknown.

*/


