# Serial programming Tcl library
[LPC2xxx related tools running on the host]

An other programming library to be used from Tcl scripts. More...

An other programming library to be used from Tcl scripts.

Based on the Serial programming C library 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 lpc-prg, a serial programmer (needs Tcl/Tk) 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 `bin` directory under the installation directory in your library path, for example by adding the line:

`LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/armlib/bin`

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 `/etc/ld.so.conf`.

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

`load liblpctcl.so`

The library defines a single Tcl command `lpcprg` 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). Note that this is not the return value but a success code. See the man page for `return(n)` for details. 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 `catch` command. When a procedure fails, it sets ist return value to the error message, which you can obtain through `catch`. Furthermore, if the error occured in the underlying C library, you can obtain an other error message by calling the `lpclib errormsg` 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:

## Logging commands

- `lpcprg logproc procedure argument`
  The `procedure` 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 `argument` 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:

          proc mylog { unused logmsg } {
              puts $logmsg
          }
          ...
          load liblpctcl.so
          ...
          lpcprg logproc mylog ""

  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.
  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.

- `lpcprg logon logtype1 logtype2 ...`
  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:
  - `serial`
    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.
    Note that when you go into monitor mode, the communication is not logged any more.
    Log entries are marked by a `[ser]` tag.
  - `target`
    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.
    Log entries are marked by a `[tgt]` tag.
  - `fileio`
    Logs hexfile related activities.
    Log entries are marked by a `[i/o]` tag.
  - `deltas`
    Each log entry will have a timestamp which is the time elapsed since the last log entry, in milliseconds.

- `lpcprg logoff logtype1 logtype2 ...`
  Disables the logging of the given events. The logtypes are the same as for the `lpcprg logon` command.

- `lpcprg errormsg`
  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.

## Serial port related commands

- `lpcprg port device lockfile`
  The command opens the `device` for communicating with the target. It is typically a real serial device, like `/dev/ttyS0` or a USB adapter, like `/dev/ttyUSB0` or similar. You must have read/write permission for the device.
  The `lockfile` argument is optional. If you omit it, then the serial device will not be locked. If you specify an empty string, that is, `""`, then the `flock()` 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 `/var/lock/ttyS0` then you must have read/write permissions for the `/var/lock` directory. The file will contain the PID of your program.

- `lpcprg baud init fast`
  If no arguments are present, then the function simply returns the current baud rate of the serial port. If the `init` argument is present but the `fast` is not, then the latter is taken as if it was the same as the former.
  The `init` 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.
  If the `fast` argument is present and is larger than `init`, 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 `init` argument.
  When you call this procedure, the switching to the `init` rate is immediate, so if you already have connected to the target at a different rate, you will lose comms.

- `lpcprg modem reset ISP`
  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.
  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:
  - `+rts`
    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).
  - `-rts`
    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).
  - `+dtr`
    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).
  - `-dtr`
    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).

- `lpcprg manual procedure argument`
  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.
  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:
  - 0 You have to assert reset (i.e. pull to GND)
  - 1 You have to negate reset (i.e. pull to Vcc)
  - 2 You have to assert ISP (i.e. pull to GND)
  - 3 You have to negate ISP (i.e. pull to Vcc)

- `lpcprg close`
  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.

## Target commands

These commands, with the exception of `connect` 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.

- `lpcprg progress callback argument`
  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 callback argument. The two arguments passed to that procedure will be argument and a string, which contains some information about what's going on inside the library (it is always a human readable message).
  If the procedure is called with no arguments, then the progess callback functionality will be disabled.

- `lpcprg crystal clock-frequency`
  Sets the clock frequency for the target. This procedure must be called before connecting to the target. The clock-frequency 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.

- `lpcprg power procedure`
  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 procedure 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 procedure parameter is omitted, then the callback will be deleted.

- `lpcprg connect`
  Resets the chip and attempts to connect to the target chip's ISP.

- `lpcprg reset`
  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.

- `lpcprg chiptype`
  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.

- `lpcprg flash`
  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.

- `lpcprg send string`
  Sends the string 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.

- `lpcprg recv`
  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 not 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 `send`, 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.

## 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:

- `lpcprg format type`
  Specifies the file format for loading and saving operations. The argument must be either `srec` or ihex, specifying Motorola S-record or Intel hex formats, respectively.

- `lpcprg load file`
  Loads a hexfile into the buffer. The file 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.

- `lpcprg save file trim`
  Copies the target's FLASH to the buffer (thus any bytes overwritten by a `load` command will be lost then saves the entire buffer into a hexfile. The first argument is the name of the file. The second argument, trim, 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.

- `lpcprg burn mode`
  Burns the buffer into the target. The mode parameter specifies how the burning is done:
  - `norm`
    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.
  - `keep`
    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>
    .
  - `wipe`
    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.

- `lpcprg vector`
  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).

- `lpcprg invalidate`
  Invalidates the buffer, marking every byte as unknown.