diff --git a/ChangeLog b/ChangeLog index 9d108810..015c01fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -45,7 +45,13 @@ * avrftdi_tpi.c: Do all I/O in terms of pgm->cmd_tpi()-calls instead of avrftdi_tpi_[read,write]_byte(). Remove unnecessary set_pin call to set MOSI high, speeds up I/O. + Removes SKEY array, moves it to tpi.h. * avr.c: Adds avr_tpi_chip_erase() generic TPI chip erase function. + Adds avr_tpi_program_enable() - generic TPI external programming enable + function. Sets guard time, reads identification register, sends SKEY command + and key, checks NVMEN bit. The required guard time has to be passed as + parameter. + * tpi.h: Adds SKEY array including CMD_SKEY in "correct" order. 2013-05-02 Hannes Weisbach diff --git a/avr.c b/avr.c index 07ab8e03..990ab5e2 100644 --- a/avr.c +++ b/avr.c @@ -103,6 +103,56 @@ int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p) } } +/* TPI program enable sequence */ +int avr_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p, unsigned char guard_time) +{ + int err, retry; + unsigned char cmd[2]; + unsigned char response; + + if(p->flags & AVRPART_HAS_TPI) { + /* set guard time */ + cmd[0] = (TPI_CMD_SSTCS | TPI_REG_TPIPCR); + cmd[1] = guard_time; + + err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0); + if(err) + return err; + + /* read TPI ident reg */ + cmd[0] = (TPI_CMD_SLDCS | TPI_REG_TPIIR); + err = pgm->cmd_tpi(pgm, cmd, 1, &response, sizeof(response)); + if (err || response != TPI_IDENT_CODE) { + fprintf(stderr, "TPIIR not correct\n"); + return -1; + } + + /* send SKEY command + SKEY */ + err = pgm->cmd_tpi(pgm, tpi_skey_cmd, sizeof(tpi_skey_cmd), NULL, 0); + if(err) + return err; + + /* check if device is ready */ + for(retry = 0; retry < 10; retry++) + { + cmd[0] = (TPI_CMD_SLDCS | TPI_REG_TPISR); + err = pgm->cmd_tpi(pgm, cmd, 1, &response, sizeof(response)); + if(err || !(response & TPI_REG_TPISR_NVMEN)) + continue; + + return 0; + } + + fprintf(stderr, "Error enabling TPI external programming mode:"); + fprintf(stderr, "Target does not reply\n"); + return -1; + + } else { + fprintf(stderr, "%s called for a part that has no TPI\n", __func__); + return -1; + } +} + /* TPI: setup NVMCMD register and pointer register (PR) for read/write/erase */ static int avr_tpi_setup_rw(PROGRAMMER * pgm, AVRMEM * mem, unsigned long addr, unsigned char nvmcmd) diff --git a/avr.h b/avr.h index b70ce93c..cf9e690b 100644 --- a/avr.h +++ b/avr.h @@ -37,6 +37,8 @@ extern "C" { #endif int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm); +int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p); +int avr_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p, unsigned char guard_time); int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsigned long addr, unsigned char * value); diff --git a/avrftdi_tpi.c b/avrftdi_tpi.c index cdcc8631..7b34e213 100644 --- a/avrftdi_tpi.c +++ b/avrftdi_tpi.c @@ -23,8 +23,6 @@ static void avrftdi_tpi_disable(PROGRAMMER *); -static const unsigned char tpi_skey_cmd[] = { TPI_CMD_SKEY, 0xff, 0x88, 0xd8, 0xcd, 0x45, 0xab, 0x89, 0x12 }; - static void avrftdi_debug_frame(uint16_t frame) { diff --git a/tpi.h b/tpi.h index f6b9fd3b..89d438d8 100644 --- a/tpi.h +++ b/tpi.h @@ -66,6 +66,8 @@ static const unsigned char tpi_skey[] = { 0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x #define TPI_NVMCMD_SECTION_ERASE 0x14 #define TPI_NVMCMD_WORD_WRITE 0x1D +static const unsigned char tpi_skey_cmd[] = { TPI_CMD_SKEY, 0xff, 0x88, 0xd8, 0xcd, 0x45, 0xab, 0x89, 0x12 }; + #ifdef __cplusplus } #endif