From 90943bf2bb058128e938b4b6a3661ddf60fbbc12 Mon Sep 17 00:00:00 2001 From: Thomas Fischl Date: Sat, 28 Feb 2009 13:10:47 +0000 Subject: [PATCH] Based on patch #6484 commited by Jurgis Brigmanis: * usbasp.c: added software control for ISP speed * usbasp.h: (Ditto.) git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@815 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrdude/ChangeLog | 6 +++ avrdude/usbasp.c | 95 +++++++++++++++++++++++++++++++++++++++++++++-- avrdude/usbasp.h | 27 +++++++++++++- 3 files changed, 123 insertions(+), 5 deletions(-) diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog index 9974b862..70abf712 100644 --- a/avrdude/ChangeLog +++ b/avrdude/ChangeLog @@ -1,3 +1,9 @@ +2009-02-28 Thomas Fischl + + Based on patch #6484 commited by Jurgis Brigmanis: + * usbasp.c: added software control for ISP speed + * usbasp.h: (Ditto.) + 2009-02-28 Joerg Wunsch * avr910.c (avr910_read_byte_flash): Eliminate a static variable that diff --git a/avrdude/usbasp.c b/avrdude/usbasp.c index b01a8762..dd0c1464 100644 --- a/avrdude/usbasp.c +++ b/avrdude/usbasp.c @@ -228,8 +228,14 @@ static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p) unsigned char temp[4]; memset(temp, 0, sizeof(temp)); + + /* set sck period */ + pgm->set_sck_period(pgm, pgm->bitclock); + + /* connect to target device */ usbasp_transmit(pgm, 1, USBASP_FUNC_CONNECT, temp, temp, sizeof(temp)); + /* wait, so device is ready to receive commands */ usleep(100000); return pgm->program_enable(pgm, p); @@ -350,8 +356,8 @@ static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[1] = address >> 8; cmd[2] = address >> 16; cmd[3] = address >> 24; - usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); - + usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); + /* send command with address (compatibility mode) - if firmware on usbasp doesn't support newmode, then they use address from this */ cmd[0] = address & 0xFF; @@ -416,10 +422,10 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[2] = address >> 16; cmd[3] = address >> 24; usbasp_transmit(pgm, 1, USBASP_FUNC_SETLONGADDRESS, cmd, temp, sizeof(temp)); - + /* normal command - firmware what support newmode - use address from previous command, firmware what doesn't support newmode - ignore previous command and use address from this command */ - + cmd[0] = address & 0xFF; cmd[1] = address >> 8; cmd[2] = page_size & 0xFF; @@ -444,6 +450,86 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, return n_bytes; } + +/* The list of SCK frequencies in kHz supported by USBasp */ +static struct sckoptions_t usbaspSCKoptions[] = { + { USBASP_ISP_SCK_1500, 1500 }, + { USBASP_ISP_SCK_750, 750 }, + { USBASP_ISP_SCK_375, 375 }, + { USBASP_ISP_SCK_187_5, 187.5 }, + { USBASP_ISP_SCK_93_75, 93.75 }, + { USBASP_ISP_SCK_32, 32 }, + { USBASP_ISP_SCK_16, 16 }, + { USBASP_ISP_SCK_8, 8 }, + { USBASP_ISP_SCK_4, 4 }, + { USBASP_ISP_SCK_2, 2 }, + { USBASP_ISP_SCK_1, 1 }, + { USBASP_ISP_SCK_0_5, 0.5 } +}; + + +/* + * Set sck period (in seconds) + * Find next possible sck period and write it to the programmer. + */ +static int usbasp_set_sck_period(PROGRAMMER *pgm, double sckperiod) +{ + char clockoption = USBASP_ISP_SCK_AUTO; + unsigned char res[4]; + unsigned char cmd[4]; + + memset(cmd, 0, sizeof(cmd)); + memset(res, 0, sizeof(res)); + + if (sckperiod == 0) { + /* auto sck set */ + + if (verbose >= 1) + fprintf(stderr, "%s: auto set sck period (because given equals null)\n", progname); + + } else { + + double sckfreq = 1 / sckperiod / 1000; /* sck in kHz */ + double usefreq = 0; + + if (verbose >= 2) + fprintf(stderr, "%s: try to set SCK period to %g s (= %g kHz)\n", progname, sckperiod, sckfreq); + + if (sckperiod >= 1500) { + clockoption = USBASP_ISP_SCK_1500; + usefreq = 1500; + + } else { + + /* find clock option next to given clock */ + int i; + for (i = 0; i < sizeof(usbaspSCKoptions) / sizeof(usbaspSCKoptions[0]); i++) { + if (sckfreq >= usbaspSCKoptions[i].frequency) { + clockoption = usbaspSCKoptions[i].id; + usefreq = usbaspSCKoptions[i].frequency; + break; + } + } + } + + fprintf(stderr, "%s: set SCK frequency to %g kHz\n", progname, usefreq); + } + + cmd[0] = clockoption; + + int nbytes = + usbasp_transmit(pgm, 1, USBASP_FUNC_SETISPSCK, cmd, res, sizeof(res)); + + if ((nbytes != 1) | (res[0] != 0)) { + fprintf(stderr, "%s: warning: cannot set sck period. please check for usbasp firmware update.\n", + progname); + return -1; + } + + return 0; +} + + void usbasp_initpgm(PROGRAMMER * pgm) { strcpy(pgm->type, "usbasp"); @@ -472,6 +558,7 @@ void usbasp_initpgm(PROGRAMMER * pgm) pgm->paged_load = usbasp_paged_load; pgm->setup = usbasp_setup; pgm->teardown = usbasp_teardown; + pgm->set_sck_period = usbasp_set_sck_period; } diff --git a/avrdude/usbasp.h b/avrdude/usbasp.h index 2da429bc..c0d4468f 100644 --- a/avrdude/usbasp.h +++ b/avrdude/usbasp.h @@ -24,13 +24,14 @@ #include "avrpart.h" - +/* USB identifiers */ #define USBASP_SHARED_VID 0x16C0 /* VOTI */ #define USBASP_SHARED_PID 0x05DC /* Obdev's free shared PID */ #define USBASP_OLD_VID 0x03EB /* ATMEL */ #define USBASP_OLD_PID 0xC7B4 /* (unoffical) USBasp */ +/* USB function call identifiers */ #define USBASP_FUNC_CONNECT 1 #define USBASP_FUNC_DISCONNECT 2 #define USBASP_FUNC_TRANSMIT 3 @@ -40,13 +41,37 @@ #define USBASP_FUNC_READEEPROM 7 #define USBASP_FUNC_WRITEEEPROM 8 #define USBASP_FUNC_SETLONGADDRESS 9 +#define USBASP_FUNC_SETISPSCK 10 +/* Block mode flags */ #define USBASP_BLOCKFLAG_FIRST 1 #define USBASP_BLOCKFLAG_LAST 2 +/* Block mode data size */ #define USBASP_READBLOCKSIZE 200 #define USBASP_WRITEBLOCKSIZE 200 +/* ISP SCK speed identifiers */ +#define USBASP_ISP_SCK_AUTO 0 +#define USBASP_ISP_SCK_0_5 1 /* 500 Hz */ +#define USBASP_ISP_SCK_1 2 /* 1 kHz */ +#define USBASP_ISP_SCK_2 3 /* 2 kHz */ +#define USBASP_ISP_SCK_4 4 /* 4 kHz */ +#define USBASP_ISP_SCK_8 5 /* 8 kHz */ +#define USBASP_ISP_SCK_16 6 /* 16 kHz */ +#define USBASP_ISP_SCK_32 7 /* 32 kHz */ +#define USBASP_ISP_SCK_93_75 8 /* 93.75 kHz */ +#define USBASP_ISP_SCK_187_5 9 /* 187.5 kHz */ +#define USBASP_ISP_SCK_375 10 /* 375 kHz */ +#define USBASP_ISP_SCK_750 11 /* 750 kHz */ +#define USBASP_ISP_SCK_1500 12 /* 1.5 MHz */ + +typedef struct sckoptions_t { + int id; + double frequency; +} CLOCKOPTIONS; + +/* USB error identifiers */ #define USB_ERROR_NOTFOUND 1 #define USB_ERROR_ACCESS 2 #define USB_ERROR_IO 3