summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2009-04-17 00:25:44 +0200
committerNicolas Schodet2009-04-17 00:25:44 +0200
commit0476a9aed588828414a13361ee6f1983265416e5 (patch)
tree8f29efba48647dfd52e0506709ce1494f0ec07dc
parent06ae1ef9e5fe5ecaddce8408f8bd9df8bd08fb2f (diff)
* digital/avr/modules/isp:
- added low level programing methods.
-rw-r--r--digital/avr/modules/isp/Makefile.module1
-rw-r--r--digital/avr/modules/isp/README27
-rw-r--r--digital/avr/modules/isp/isp.c544
-rw-r--r--digital/avr/modules/isp/isp.h115
-rw-r--r--digital/avr/modules/isp/test/Makefile12
-rw-r--r--digital/avr/modules/isp/test/avrconfig.h28
-rw-r--r--digital/avr/modules/isp/test/test_isp.c35
7 files changed, 762 insertions, 0 deletions
diff --git a/digital/avr/modules/isp/Makefile.module b/digital/avr/modules/isp/Makefile.module
new file mode 100644
index 00000000..f5e7cfa3
--- /dev/null
+++ b/digital/avr/modules/isp/Makefile.module
@@ -0,0 +1 @@
+isp_SOURCES = isp.c
diff --git a/digital/avr/modules/isp/README b/digital/avr/modules/isp/README
new file mode 100644
index 00000000..27761d47
--- /dev/null
+++ b/digital/avr/modules/isp/README
@@ -0,0 +1,27 @@
+avr.isp - Serial programming AVR module.
+
+Provide support to program an AVR device using ISP. This includes low level
+programming methods, and AVRISP and STK500v2 compatible protocol handling.
+
+See modules README for more details about AVR modules.
+
+
+Copyright (C) 2009 Nicolas Schodet
+
+APBTeam:
+ Web: http://apbteam.org/
+ Email: team AT apbteam DOT org
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
diff --git a/digital/avr/modules/isp/isp.c b/digital/avr/modules/isp/isp.c
new file mode 100644
index 00000000..c1f10190
--- /dev/null
+++ b/digital/avr/modules/isp/isp.c
@@ -0,0 +1,544 @@
+/* isp.c - ISP AVR programming. */
+/* avr.isp - Serial programming AVR module. {{{
+ *
+ * Copyright (C) 2008 Nicolas Schodet
+ *
+ * Inspired by STK500 programmer by Guido Socher.
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+
+#include "isp.h"
+
+/** ISP context. */
+struct isp_t
+{
+ /** Current address. */
+ uint16_t addr;
+ /** Current extended address. */
+ uint8_t ext_addr;
+ /** Extended address loaded in device. */
+ uint8_t last_ext_addr;
+ /** Whether the device needs extended addressing. */
+ uint8_t larger_than_64k;
+ /** Programming start address (used for page program command). */
+ uint16_t start_addr;
+ /** Number of bytes left to process. */
+ uint16_t bytes_left;
+ /** Programming mode. */
+ uint8_t mode;
+ /** Programming delay if no other poll method. */
+ uint8_t delay_ms;
+ /** Write Program Memory or Load Page. */
+ uint8_t cmd_write_mem;
+ /** Write Page. */
+ uint8_t cmd_write_page;
+ /** Read Program Memory. */
+ uint8_t cmd_read_mem;
+ /** Value read until memory is programmed for value polling. */
+ uint8_t poll[2];
+ /** Whether the page can be polled (if almost one byte is not poll[0]).
+ * This is non zero if true, with LSB = 1 for high byte. */
+ uint8_t pollable;
+ /** Address to use for polling. */
+ uint16_t poll_addr;
+ /** Whether this is a flash memory. */
+ uint8_t flash;
+ /** Whether addresses are words addresses. */
+#define word_addr flash
+};
+
+/** Command used to load extended address. */
+#define ISP_CMD_LOAD_EXTENDED_ADDRESS 0x4d
+/** Bit to address high byte. */
+#define ISP_CMD_HIGH_BYTE (1 << 3)
+/** Extra EEPROM programming delay. */
+#define ISP_EEPROM_DELAY_MS 2
+/** Miscellaneous read delay. */
+#define ISP_MISC_READ_DELAY_MS 5
+
+/** Global context. */
+static struct isp_t isp_global;
+
+/** Enable SPI port and enter programing mode.
+ * - timeout_ms: command time-out, unused.
+ * - stab_delay_ms: stabilisation delay once device is reseted and SPI
+ * initialised.
+ * - cmd_exe_delay_ms: delay for the command execution.
+ * - synch_loops: number of synchronisation loops (there is no start of frame
+ * in SPI).
+ * - byte_delay_ms: delay between each byte.
+ * - poll_value: value to read to consider the sequence is correct.
+ * - poll_index: transfer index at which the poll_value must be read.
+ * - cmd: command bytes to be transfered.
+ * - returns: ISP_OK or ISP_FAILED if no synchronisation. */
+uint8_t
+isp_enter_progmode (uint8_t timeout_ms, uint8_t stab_delay_ms,
+ uint8_t cmd_exe_delay_ms, uint8_t synch_loops,
+ uint8_t byte_delay_ms, uint8_t poll_value,
+ uint8_t poll_index, uint8_t cmd[4])
+{
+ uint8_t i, tmp1, tmp2;
+ /* Reset context. */
+ isp_global.ext_addr = 0;
+ isp_global.last_ext_addr = 0xff;
+ isp_global.larger_than_64k = 0;
+ isp_global.bytes_left = 0;
+ /* Enable SPI. */
+ isp_spi_enable ();
+ isp_delay_ms (stab_delay_ms);
+ /* Limit the number of loops. */
+ if (synch_loops > 48)
+ synch_loops = 48;
+ /* Minimum byte delay. */
+ if (byte_delay_ms < 1)
+ byte_delay_ms = 1;
+ /* Synchronisation loops. */
+ for (i = 0; i < synch_loops; i++)
+ {
+ isp_wd_kick ();
+ isp_delay_ms (cmd_exe_delay_ms);
+ isp_spi_tx (cmd[0]);
+ isp_delay_ms (byte_delay_ms);
+ isp_spi_tx (cmd[1]);
+ isp_delay_ms (byte_delay_ms);
+ tmp1 = isp_spi_tx (cmd[2]);
+ isp_delay_ms (byte_delay_ms);
+ tmp2 = isp_spi_tx (cmd[3]);
+ /* Test success. */
+ if (poll_index == 0
+ || (poll_index == 3 && tmp1 == poll_value)
+ || (poll_index != 3 && tmp2 == poll_value))
+ return ISP_OK;
+ /* Else, new try. */
+ isp_spi_sck_pulse ();
+ isp_delay_ms (20);
+ }
+ return ISP_FAILED;
+}
+
+/** Leave programming mode and disable SPI port.
+ * - pre_delay_ms: delay before disabling.
+ * - post_delay_ms: delay after disabling. */
+void
+isp_leave_progmode (uint8_t pre_delay_ms, uint8_t post_delay_ms)
+{
+ isp_delay_ms (pre_delay_ms);
+ isp_spi_disable ();
+ isp_delay_ms (post_delay_ms);
+}
+
+/** Load programing address.
+ * - addr: address to load, bit 31 means the device has more than 64k words
+ * and extended addressing should be used. */
+void
+isp_load_address (uint32_t addr)
+{
+ isp_global.addr = addr & 0xffff;
+ isp_global.ext_addr = (addr >> 16) & 0xff;
+ isp_global.last_ext_addr = 0xff;
+ isp_global.larger_than_64k = (addr & 0x80000000) ? 1 : 0;
+}
+
+/** Chip full erase.
+ * - erase_delay_ms: delay to ensure the erase is finished.
+ * - poll_method: use delay (0) or RDY/BSY polling (1).
+ * - cmd: chip erase command.
+ * - returns: ISP_OK or ISP_TIMEOUT if using polling and it timed-out. */
+uint8_t
+isp_chip_erase (uint8_t erase_delay_ms, uint8_t poll_method, uint8_t cmd[4])
+{
+ uint8_t tries;
+ isp_spi_tx (cmd[0]);
+ isp_spi_tx (cmd[1]);
+ isp_spi_tx (cmd[2]);
+ isp_spi_tx (cmd[3]);
+ if (poll_method == 0)
+ {
+ /* Use delay. */
+ isp_delay_ms (erase_delay_ms);
+ }
+ else
+ {
+ /* Use RDY/BSY command. */
+ tries = 150;
+ while ((isp_spi_tx_32 (0xf0000000) & 1) && tries)
+ tries--;
+ if (tries == 0)
+ return ISP_TIMEOUT;
+ }
+ return ISP_OK;
+}
+
+/** Start a program command. See context for parameters.
+ * - num_bytes: total number of bytes to program.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters.
+ * See context for other parameters meaning. */
+static uint8_t
+isp_program_begin (uint16_t num_bytes, uint8_t mode, uint8_t delay_ms,
+ uint8_t cmd_write_mem, uint8_t cmd_write_page,
+ uint8_t cmd_read_mem, uint8_t poll[2], uint8_t flash)
+{
+ /* Set delay bounds. */
+ if (delay_ms < 4)
+ delay_ms = 4;
+ if (delay_ms > 32)
+ delay_ms = 32;
+ /* Check data size. */
+ if (word_addr && (num_bytes & 1))
+ return ISP_FAILED;
+ /* Store parameters. */
+ isp_global.start_addr = isp_global.addr;
+ isp_global.bytes_left = num_bytes;
+ isp_global.mode = mode;
+ isp_global.delay_ms = delay_ms;
+ isp_global.cmd_write_mem = cmd_write_mem;
+ isp_global.cmd_write_page = cmd_write_page;
+ isp_global.cmd_read_mem = cmd_read_mem;
+ isp_global.poll[0] = poll[0];
+ isp_global.poll[1] = poll[1];
+ isp_global.pollable = 0;
+ isp_global.flash = flash;
+ return ISP_OK;
+}
+
+/** Start a flash memory program command.
+ * - num_bytes: total number of bytes to program.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters.
+ * See context for other parameters meaning. */
+uint8_t
+isp_program_flash_begin (uint16_t num_bytes, uint8_t mode, uint8_t delay_ms,
+ uint8_t cmd_write_mem, uint8_t cmd_write_page,
+ uint8_t cmd_read_mem, uint8_t poll[2])
+{
+ return isp_program_begin (num_bytes, mode, delay_ms, cmd_write_mem,
+ cmd_write_page, cmd_read_mem, poll, 1);
+}
+
+/** Start a EEPROM memory program command.
+ * - num_bytes: total number of bytes to program.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters.
+ * See context for other parameters meaning. */
+uint8_t
+isp_program_eeprom_begin (uint16_t num_bytes, uint8_t mode, uint8_t delay_ms,
+ uint8_t cmd_write_mem, uint8_t cmd_write_page,
+ uint8_t cmd_read_mem, uint8_t poll[2])
+{
+ return isp_program_begin (num_bytes, mode, delay_ms, cmd_write_mem,
+ cmd_write_page, cmd_read_mem, poll, 0);
+}
+
+/** Provide data for memory programming. Data should be given by even sized
+ * packs or loading of word addressed data will fail.
+ * - returns: ISP_OK, ISP_FAILED for bad parameters or ISP_TIMEOUT if using
+ * polling and it timed-out. */
+uint8_t
+isp_program_continue (uint8_t *data, uint16_t size)
+{
+ uint16_t i;
+ uint8_t tries, read;
+ /* Check size. */
+ if (size > isp_global.bytes_left
+ || (isp_global.word_addr && (size & 1)))
+ return ISP_FAILED;
+ isp_global.bytes_left -= size;
+ /* Loop on each input bytes. */
+ for (i = 0; i < size; i++)
+ {
+ /* Check for Load Extended Address. */
+ if (isp_global.larger_than_64k
+ && isp_global.last_ext_addr != isp_global.ext_addr)
+ {
+ isp_spi_tx (ISP_CMD_LOAD_EXTENDED_ADDRESS);
+ isp_spi_tx (0x00);
+ isp_spi_tx (isp_global.ext_addr);
+ isp_spi_tx (0x00);
+ isp_global.last_ext_addr = isp_global.ext_addr;
+ }
+ /* Write memory/load page, using bit 3 as byte selector. */
+ if (isp_global.word_addr && (i & 1))
+ isp_spi_tx (isp_global.cmd_write_mem | ISP_CMD_HIGH_BYTE);
+ else
+ isp_spi_tx (isp_global.cmd_write_mem);
+ isp_spi_tx_16 (isp_global.addr);
+ isp_spi_tx (data[i]);
+ /* EEPROM needs more delay. */
+ if (!isp_global.flash)
+ isp_delay_ms (ISP_EEPROM_DELAY_MS);
+ /* Poll. */
+ if (!(isp_global.mode & ISP_MODE_PAGE))
+ {
+ /* Poll right now. */
+ tries = 150;
+ read = isp_global.poll[0];
+ if ((isp_global.mode & ISP_MODE_WORD_VALUE)
+ && data[i] != read)
+ {
+ /* Poll by reading byte. */
+ while (read != data[i] && tries)
+ {
+ if (isp_global.word_addr && (i & 1))
+ isp_spi_tx (isp_global.cmd_read_mem
+ | ISP_CMD_HIGH_BYTE);
+ else
+ isp_spi_tx (isp_global.cmd_read_mem);
+ isp_spi_tx_16 (isp_global.addr);
+ read = isp_spi_tx (0x00);
+ tries--;
+ }
+ }
+ else if (isp_global.mode & ISP_MODE_WORD_RDY_BSY)
+ {
+ /* RDY/BSY polling. */
+ while ((isp_spi_tx_32 (0xf0000000) & 1) && tries)
+ tries--;
+ }
+ else
+ /* Simple delay. */
+ isp_delay_ms (isp_global.delay_ms);
+ if (tries == 0)
+ return ISP_TIMEOUT;
+ }
+ else
+ {
+ /* Check for poll method. */
+ if (!isp_global.pollable && data[i] != isp_global.poll[0])
+ {
+ isp_global.pollable = 0x02 | (i & 1);
+ isp_global.poll_addr = isp_global.addr;
+ }
+ }
+ /* Increment address. */
+ if (!isp_global.word_addr || (i & 1))
+ {
+ isp_global.addr++;
+ if (isp_global.addr == 0)
+ isp_global.ext_addr++;
+ }
+ }
+ return ISP_OK;
+}
+
+/** End program command.
+ * - returns: ISP_OK, ISP_FAILED if too early or ISP_TIMEOUT if using polling
+ * and it timed-out. */
+uint8_t
+isp_program_end (void)
+{
+ uint8_t tries, read;
+ /* Check size. */
+ if (isp_global.bytes_left != 0)
+ return ISP_FAILED;
+ /* Write page if requested. */
+ if ((isp_global.mode & (ISP_MODE_PAGE | ISP_MODE_PAGE_WRITE))
+ == (ISP_MODE_PAGE | ISP_MODE_PAGE_WRITE))
+ {
+ /* Write page. */
+ isp_spi_tx (isp_global.cmd_write_page);
+ isp_spi_tx_16 (isp_global.start_addr);
+ isp_spi_tx (0x00);
+ /* EEPROM needs more delay. */
+ if (!isp_global.flash)
+ isp_delay_ms (ISP_EEPROM_DELAY_MS);
+ /* Poll. */
+ tries = 150;
+ read = isp_global.poll[0];
+ if ((isp_global.mode & ISP_MODE_PAGE_VALUE)
+ && isp_global.pollable)
+ {
+ /* Poll by reading byte. */
+ while (read == isp_global.poll[0] && tries)
+ {
+ if (isp_global.word_addr && (isp_global.pollable & 1))
+ isp_spi_tx (isp_global.cmd_read_mem
+ | ISP_CMD_HIGH_BYTE);
+ else
+ isp_spi_tx (isp_global.cmd_read_mem);
+ isp_spi_tx_16 (isp_global.poll_addr);
+ read = isp_spi_tx (0x00);
+ tries--;
+ }
+ }
+ else if (isp_global.mode & ISP_MODE_PAGE_RDY_BSY)
+ {
+ /* RDY/BSY polling. */
+ while ((isp_spi_tx_32 (0xf0000000) & 1) && tries)
+ tries--;
+ }
+ else
+ /* Simple delay. */
+ isp_delay_ms (isp_global.delay_ms);
+ if (tries == 0)
+ return ISP_TIMEOUT;
+ }
+ return ISP_OK;
+}
+
+/** Start a read command.
+ * - num_bytes: total number of bytes to program.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters.
+ * See context for other parameters meaning. */
+static uint8_t
+isp_read_begin (uint16_t num_bytes, uint8_t cmd_read_mem, uint8_t flash)
+{
+ /* Check data size. */
+ if (word_addr && (num_bytes & 1))
+ return ISP_FAILED;
+ /* Store parameters. */
+ isp_global.bytes_left = num_bytes;
+ isp_global.cmd_read_mem = cmd_read_mem;
+ isp_global.flash = flash;
+ return ISP_OK;
+}
+
+/** Start a flash memory read command.
+ * - num_bytes: total number of bytes to program.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters.
+ * See context for other parameters meaning. */
+uint8_t
+isp_read_flash_begin (uint16_t num_bytes, uint8_t cmd_read_mem)
+{
+ return isp_read_begin (num_bytes, cmd_read_mem, 1);
+}
+
+/** Start a EEPROM memory read command.
+ * - num_bytes: total number of bytes to program.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters.
+ * See context for other parameters meaning. */
+uint8_t
+isp_read_eeprom_begin (uint16_t num_bytes, uint8_t cmd_read_mem)
+{
+ return isp_read_begin (num_bytes, cmd_read_mem, 0);
+}
+
+/** Get data from read memory. Data should be read by even sized packs or
+ * loading of word addressed data will fail.
+ * - returns: ISP_OK or ISP_FAILED for bad parameters. */
+uint8_t
+isp_read_continue (uint8_t *data, uint16_t size)
+{
+ uint16_t i;
+ /* Check size. */
+ if (size > isp_global.bytes_left
+ || (isp_global.word_addr && (size & 1)))
+ return ISP_FAILED;
+ isp_global.bytes_left -= size;
+ /* Loop on each bytes. */
+ for (i = 0; i < size; i++)
+ {
+ /* Check for Load Extended Address. */
+ if (isp_global.larger_than_64k
+ && isp_global.last_ext_addr != isp_global.ext_addr)
+ {
+ isp_spi_tx (ISP_CMD_LOAD_EXTENDED_ADDRESS);
+ isp_spi_tx (0x00);
+ isp_spi_tx (isp_global.ext_addr);
+ isp_spi_tx (0x00);
+ isp_global.last_ext_addr = isp_global.ext_addr;
+ }
+ /* Read memory, using bit 3 as byte selector. */
+ if (isp_global.word_addr && (i & 1))
+ isp_spi_tx (isp_global.cmd_read_mem | ISP_CMD_HIGH_BYTE);
+ else
+ isp_spi_tx (isp_global.cmd_read_mem);
+ isp_spi_tx_16 (isp_global.addr);
+ data[i] = isp_spi_tx (0x00);
+ /* Increment address. */
+ if (!isp_global.word_addr || (i & 1))
+ {
+ isp_global.addr++;
+ if (isp_global.addr == 0)
+ isp_global.ext_addr++;
+ }
+ }
+ return ISP_OK;
+}
+
+/** End read command.
+ * - returns: ISP_OK or ISP_FAILED if too early. */
+uint8_t
+isp_read_end (void)
+{
+ /* Check size. */
+ if (isp_global.bytes_left != 0)
+ return ISP_FAILED;
+ return ISP_OK;
+}
+
+/** Program miscellaneous memory (fuse, lock).
+ * - cmd: program command. */
+void
+isp_program_misc (uint8_t cmd[4])
+{
+ uint8_t i;
+ for (i = 0; i < 4; i++)
+ isp_spi_tx (cmd[i]);
+}
+
+/** Read miscellaneous memory (fuse, lock, signature, osccal).
+ * - ret_addr: transfer index at which the return value must be read.
+ * - cmd: read command. */
+uint8_t
+isp_read_misc (uint8_t ret_addr, uint8_t cmd[4])
+{
+ uint8_t i, read = 0, tmp;
+ for (i = 0; i < 4; i++)
+ {
+ tmp = isp_spi_tx (cmd[i]);
+ if (i == ret_addr)
+ read = tmp;
+ isp_delay_ms (ISP_MISC_READ_DELAY_MS);
+ }
+ return read;
+}
+
+/** Generic SPI access.
+ * - num_tx: number of bytes to transmit.
+ * - num_rx: number of bytes to receive.
+ * - rx_start: start reception after this number of transmitted bytes.
+ * - data: buffer to read sent bytes and write received bytes.
+ * Limitation: no support for doing this in several chunks as memory
+ * programing and reading. */
+void
+isp_multi (uint8_t num_tx, uint8_t num_rx, uint8_t rx_start, uint8_t *data)
+{
+ uint8_t in, *din, out;
+ const uint8_t *dout;
+ dout = din = data;
+ while (num_tx || num_rx)
+ {
+ out = 0;
+ if (num_tx)
+ {
+ out = *dout++;
+ num_tx--;
+ }
+ in = isp_spi_tx (out);
+ if (!rx_start)
+ rx_start--;
+ else if (num_rx)
+ {
+ *din++ = in;
+ num_rx--;
+ }
+ }
+}
+
diff --git a/digital/avr/modules/isp/isp.h b/digital/avr/modules/isp/isp.h
new file mode 100644
index 00000000..dc3a9f54
--- /dev/null
+++ b/digital/avr/modules/isp/isp.h
@@ -0,0 +1,115 @@
+#ifndef isp_h
+#define isp_h
+/* isp.h - ISP AVR programming. */
+/* avr.isp - Serial programming AVR module. {{{
+ *
+ * Copyright (C) 2009 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+
+/** Results returned by ISP functions. */
+enum isp_result_t
+{
+ /** Operation success. */
+ ISP_OK,
+ /** Operation failed. */
+ ISP_FAILED,
+ /** Operation failed on a timeout. */
+ ISP_TIMEOUT,
+};
+
+/** ISP Programming mode. */
+enum isp_mode_t
+{
+ /** Use page programming. */
+ ISP_MODE_PAGE = 1,
+ /** Use simple delay for word programming. */
+ ISP_MODE_WORD_DELAY = 2,
+ /** Use value polling if possible for word programming, fall back to delay
+ * if not possible. */
+ ISP_MODE_WORD_VALUE = 4,
+ /** Use RDY/BSY polling for word programming. */
+ ISP_MODE_WORD_RDY_BSY = 8,
+ /** Use simple delay for page programming. */
+ ISP_MODE_PAGE_DELAY = 16,
+ /** Use value polling if possible for page programming, fall back to delay
+ * if not possible. */
+ ISP_MODE_PAGE_VALUE = 32,
+ /** Use RDY/BSY polling for page programming. */
+ ISP_MODE_PAGE_RDY_BSY = 64,
+ /** Write page at end of transfer. Used for big pages which must be
+ * transfered in several packets. */
+ ISP_MODE_PAGE_WRITE = 128,
+};
+
+uint8_t
+isp_enter_progmode (uint8_t timeout_ms, uint8_t stab_delay_ms,
+ uint8_t cmd_exe_delay_ms, uint8_t synch_loops,
+ uint8_t byte_delay_ms, uint8_t poll_value,
+ uint8_t poll_index, uint8_t cmd[4]);
+
+void
+isp_leave_progmode (uint8_t pre_delay_ms, uint8_t post_delay_ms);
+
+void
+isp_load_address (uint32_t addr);
+
+uint8_t
+isp_chip_erase (uint8_t erase_delay_ms, uint8_t poll_method, uint8_t cmd[4]);
+
+uint8_t
+isp_program_flash_begin (uint16_t num_bytes, uint8_t mode, uint8_t delay_ms,
+ uint8_t cmd_write_mem, uint8_t cmd_write_page,
+ uint8_t cmd_read_mem, uint8_t poll[2]);
+
+uint8_t
+isp_program_eeprom_begin (uint16_t num_bytes, uint8_t mode, uint8_t delay_ms,
+ uint8_t cmd_write_mem, uint8_t cmd_write_page,
+ uint8_t cmd_read_mem, uint8_t poll[2]);
+
+uint8_t
+isp_program_continue (uint8_t *data, uint16_t size);
+
+uint8_t
+isp_program_end (void);
+
+uint8_t
+isp_read_flash_begin (uint16_t num_bytes, uint8_t cmd_read_mem);
+
+uint8_t
+isp_read_eeprom_begin (uint16_t num_bytes, uint8_t cmd_read_mem);
+
+uint8_t
+isp_read_continue (uint8_t *data, uint16_t size);
+
+uint8_t
+isp_read_end (void);
+
+void
+isp_program_misc (uint8_t cmd[4]);
+
+uint8_t
+isp_read_misc (uint8_t ret_addr, uint8_t cmd[4]);
+
+void
+isp_multi (uint8_t num_tx, uint8_t num_rx, uint8_t rx_start, uint8_t *data);
+
+#endif /* isp_h */
diff --git a/digital/avr/modules/isp/test/Makefile b/digital/avr/modules/isp/test/Makefile
new file mode 100644
index 00000000..c06fd358
--- /dev/null
+++ b/digital/avr/modules/isp/test/Makefile
@@ -0,0 +1,12 @@
+BASE = ../../..
+AVR_PROGS = test_isp
+test_isp_SOURCES = test_isp.c
+MODULES = isp utils
+CONFIGFILE = avrconfig.h
+# atmega8, atmega8535, atmega128...
+AVR_MCU = atmega8
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -O2
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/isp/test/avrconfig.h b/digital/avr/modules/isp/test/avrconfig.h
new file mode 100644
index 00000000..5c1538d3
--- /dev/null
+++ b/digital/avr/modules/isp/test/avrconfig.h
@@ -0,0 +1,28 @@
+#ifndef avrconfig_h
+#define avrconfig_h
+/* avrconfig.h */
+/* avr.isp - Serial programming AVR module. {{{
+ *
+ * Copyright (C) 2009 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+
+#endif /* avrconfig_h */
diff --git a/digital/avr/modules/isp/test/test_isp.c b/digital/avr/modules/isp/test/test_isp.c
new file mode 100644
index 00000000..ca0fd355
--- /dev/null
+++ b/digital/avr/modules/isp/test/test_isp.c
@@ -0,0 +1,35 @@
+/* test_isp.c */
+/* avr.isp - Serial programming AVR module. {{{
+ *
+ * Copyright (C) 2009 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+
+#include "modules/isp/isp.h"
+
+int
+main (void)
+{
+ /* Just testing compilation. */
+ return 0;
+}
+