m8cprog - General programmer for the M8C microcontroller family
===============================================================

Copyright 2006 Werner Almesberger

The files in this directory are distributed under the terms of the
GNU General Public License (GPL), version 2. This license is
included in the file ../COPYING.GPLv2.


Overview
--------

m8cprog is a programmer for all the chips described in Cypress'
application notes AN2026A and AN2026B, i.e., all current CY8C2
models.

The programmer communicates with the programmer hardware through a
driver. Drivers are statically linked into the programmer and
handles the low-level program to the hardware and any data format
conversions needed. m8cprog controls the overall programming
operation and performs file I/O.


Quick start
-----------

m8cprog has a lot of options, which can be confusing. The most common
task is to simply write an Intel HEX or ROM file to Flash, and to
verify the outcome. This can be accomplished with

... -w -c -s filename

-w tells m8cprog to write the file to Flash, -c tells it to compare
the Flash content with what was written, and -s tells it to also
check the security data. This is the most thorough checking available.
m8cprog can usually auto-detect the file format.

Furthermore, the driver for the programmer needs to be selected.
This is done with

... -d programmer ...

E.g., -d watpp, for the trivial parallel-port programmer.

It is usually necessary to tell m8cprog what voltage to use (-3 or
-5, for 3 and 5 volts, respectively) and whether to use reset or
power-on mode. The default is reset mode.  Power-on mode is selected
with the option -P.

For example, reset mode and 5 V operation is selected with

... -5 ...

Last but not least, if running m8cprog from a privileged account
(e.g., root), it is a good idea to request real-time priority:

... -R ...

So the entire command line would look like this:

m8cprog -d watpp -5 -R -w -c -s somefile.rom


Usage
-----

m8cprog reads and writes either raw binary files, "ROM" files,
or files in the Intel HEX format. The file type is auto-detected
when reading. The auto-detection can be overridden by selecting
the binary format with the option -b. When writing, the default
format is "ROM", which can be overridden with -b (binary) and -i
(Intel HEX).

The name of the file to read or write is specified on the, with the
special name "-" meaning standard input or output. The file name can
be omitted, in which case also standard input or output is used.

The programmer can perform the following operations:

- erase the entire Flash (-e). This is implied when writing.
- write from a file to Flash and verify the checksum (-w). If using
  an Intel HEX file, also the security data can be written. Security
  data can also be supplied in the form of a flashsecurity.txt file
  (option -f filename) or chip-wide with the option -F mode. Allowed
  modes are U, R, and W. m8cprog also accepts mode F, but warns
  about its limitations. Modes can be in upper or lower case.
  Command-line settings override any security data in the Intel HEX
  file.
- read from Flash to a file (-r)
- compare file content with Flash content (-c). This can be combined
  with all other operations. If combined with reading, the
  comparison is done before writing the file, so no file will be
  written if the data read differs from the data obtained for
  comparison.
- retrieve the per-block Flash protection ("security") bits (-s).
  This is an undocumented operation and is only done if explicitly
  requested. -s -s also retrieves and prints protection bits that
  are not normally used, but may be settable.

As a precaution against accidently overwriting the input file,
reading cannot be combined with writing. Reading and comparing fail
when they encounter a read-protected block. This can be changed by
setting the -z option (in which the case the offending block is
filled with zeroes or skipped). Furthermore, if security data is
available, this information is used to skip unreadable blocks.

The driver for the programmer hardware is selected with the option
"-d driver". The name is case-insensitive. A list of available
drivers can be obtained with "m8cprog -l". A default driver name
can be set via the environment variable M8CPROG_DRIVER. If no
driver is specified, the first driver in the internal driver list
is used.

The port to which the driver is attached (if applicable) can be set
with the option "-p port". A default can be provided through the
environment variable M8CPROG_PORT. If no port is set, the default
depends on the driver hardware. For hardware attached via a serial
port, the default is /dev/ttyS0.

For hardware attached via the parallel port, the default is
/dev/parport0. Note that the kernel must support user-space
parallel port device drivers (CONFIG_PPDEV) to use programmers
attached to the parallel port. Programmers requiring advanced
parallel port capabilities, such as EPP, may also need these
capabilities in the BIOS setup.

Additional options can be passed to the driver with "-O option".
The use of these options is specific to the driver. Most drivers
simply ignore them.

If the driver has to perform timing-critical operations, such as
sending an initial vector within a deadline, on the host CPU,
timing may be improved by requesting real-time priority with the
option -R. This option requires root privileges. Note that a buggy
driver that busy loops in that function can hang the system.

The name of the chip to program can be specified as a the command
line argument. The name is case-insensitive. A list of supported
chips can be obtained with "m8cprog -l". If no chip name is
specified, m8cprog will auto-detect the chip. Note that the chip
name argument must be specified if the file name happens to be a
valid chip name.

The voltage at which the chip operates is set with the options -3
(3V) and -5 (5V). This option is required if the programmer does
not sense the chip voltage or if the programmer needs to provide
power to the circuit being programmed, and has to decide between
3V and 5V. In all other cases, the voltage is auto-detected,
provided that the programmer hardware is capable of doing this. If
the voltage is also specified on the command line, and the
auto-detected voltage does not correspond to it, m8cprog aborts
with an error.

By default, m8cprog uses reset mode. Power-on mode can be selected
with the option -P.

Upon successful termination, m8cprog powers down the target and/or
holds it in reset. This can be changed with the option -D, which
(provided that the programmer hardware supports this) tri-states
SDATA and SCLK, and sends an XRES pulse to the target. The effect
is that the target no longer "sees" the programmer, and starts
executing its firmware. "m8cprog -D", without any of the options
-c, -e, -r, -s, and -w, simply resets the target.

Last but not least, several degrees of verboseness can be selected
with the options -q and -v. By default, m8cprog only displays
progress bars, which can be turned off with -q. A single -v adds
general progress messages. More -v options add more and more noise.
Note that excessive output may slow down some programmers such that
they fail to meet protocol deadlines.

Examples:

% m8cprog -3 -w prog.hex

Writes the file prog.hex to the programmer, using defaults. The
voltage is set to 3V.

% m8cprog -d waspic -p /dev/ttyS1 -3 -r -b data.hex

Silently reads the Flash content with a "waspic" programmer
connected to /dev/ttyS1, and stores it in binary format.

% m8cprog -l

Lists the supported programmers (drivers) and chips.


Writing a driver
----------------

Drivers can operate any one or more of the following layers:

- "operations": highest-level operations, such as transferring
  the entire Flash content or verifying the checksum of all banks

- "primitives": the ISSP primitives described in AN2026

- "vectors": individual memory/register read/write operations,
  conveyed in 22 bit vectors

- "bit-banging": toggling of SCLK and SDATA under program control

The protocol stack in m8cprog automatically substitutes high-level
functions not provided by the driver with operations using the
lower-level functions.

Each driver needs to provide a "struct prog_common", with the
driver's name and general functions to open and close the driver.
In its "open" function, the driver calls "prog_init", passing
pointers to its functions for all the layers. For layers not
directly supported by the driver, NULL is passed.


High-level operations
- - - - - - - - - - -

Programmers that implement high-level operations, such as those
affecting the entire Flash, in a single function, can use the
high-level interface for this.

Note that this interface is still subject to refining.


ISSP primitives
- - - - - - - -

Programmers that implement entire ISSP primitives or even sequences
of them in firmware can use the "primitives" interface. It basically
provides a functions for each ISSP operation documented in AN2026.

The driver can omit any of these functions (as long as it provides
vector or bit-banging functions), in which case they are replaced by
the corresponding sequence of vector operations.

If supported by the firmware, a vector-based interface should be
provided alongside with the ISSP primitives, to allow for use of
m8csim's DIY ICE. Also, retrieval of protection bits is not documented
in AN2026 and may have to be performed though vector-level operations.


Vector-based
- - - - - -

The "vector" function receives the vector to send. It is passed
as the first 19 bits of the vector in a 32 bit word, with the
first bit to send at position 0x40000, and the last bit at
position 0.

If the vector is zero, the programmer must follow its 19 bits
with three more zero bits. If the vector is a write, the
programmer must follow its 19 bits with three ones. If the vector
is a ready, the programmer must only send the first 11 bits, then
send a Z, read eight bits, send another Z, and finally send a 1.

If the vector contains a read, "vector" returns the byte read
from the hardware. Otherwise, the return value is unspecified.

If the vector will execute an SSC instruction, the programmer
must perform the WAIT-AND-POLL procedure described in AN2026A.
Vectors executing an SSC are marked by or-ing them with
PROG_SSC_FLAG.

A simple driver for a PIC-based programmer connected via the
serial port can be found in prog_waspic.c. Schematic and firmware
of the programmer itself are in the directory ../waspic


Bit-banging
- - - - - -

The bit-banging interface consists of three functions: one to
send a bit on SDATA while pulsing SCLK, one to make SDATA an
input (Z) and pulse SCLK, and one to read the current status of
SDATA (which is an input at that time).

Examples for bit-banging drivers include "watpp" and "watsp".


Programmer testing
------------------

The file torture.c contains a simple tester for communication
between host and target, through the programmer. It writes
blocks of pseudo-random data to memory, and then retrieves them
twice, comparing each time with the original data. Note that no
write to Flash performed, so this type of testing can be done
indefinitely.

Bytes inside a block read or write are transferred back-to-back
(to the extent that the programmer supports this), and a brief
sequence of zeroes is inserted after each block transfer to allow
for recovery in case a small number of clock pulses was lost or
added.

There are the following error patterns:

- the same mismatch in both readback phases:
  an error occurred while writing.

- mismatch in one of the readback phases or at both, but at
  different places or with different values:
  an error occurred while reading.

- there is a large number of corrupt bytes following the first
  one (e.g., all until the end of the block, or almost as many):
  a clock pulse (SCLK) was lost or added.

- there are typically only one or two corrupt bytes in a block:
  SDATA was mis-set or mis-read

Note that for each data byte read or written, one address byte
is sent to the target, so if corruption occurs in the way to the
target, it is equally likely to affect the address as it is to
affect data. Similarly, also the three bits identifying the
operation can be corrupted.

To build the torture-tester, do "make torture". It is then
available as "./torture". Since libcrypto (needed for MD5, which
is used to generate a pseudo-random data pattern) may not be
available on all systems, a static version of "torture" can be
built with "make torture-static".

"torture" accepts the usual programmer options. The program loops
forever and reports its findings to standard error. If the number
of cycles per session is passed as an argument, "torture" will
close the programmer session and re-open it again whenever the
specified number of cycles has been reached in the a session.
