From 9567713246b6008003f5c53b1da736817862a8f0 Mon Sep 17 00:00:00 2001 From: Thomas Fischl Date: Fri, 8 Jan 2010 18:33:23 +0000 Subject: [PATCH] bug #28520: Programming with USBasp with low clock speed fails * usbasp.c: Change blocksize depending on sck frequency to avoid usb transmition timeouts. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@897 81a1dc3b-b13d-400b-aceb-764788c761c2 --- ChangeLog | 6 +++++ usbasp.c | 80 +++++++++++++++++++++++++++++++++---------------------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b2a44e0..30b0789a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-01-08 Thomas Fischl + + bug #28520: Programming with USBasp with low clock speed fails + * usbasp.c: Change blocksize depending on sck frequency to + avoid usb transmition timeouts. + 2010-01-08 Joerg Wunsch bug #27505: serbb_posix does not cope with inverted pins diff --git a/usbasp.c b/usbasp.c index dd0c1464..ff7d71e2 100644 --- a/usbasp.c +++ b/usbasp.c @@ -48,6 +48,7 @@ struct pdata { usb_dev_handle *usbhandle; + int sckfreq_hz; }; #define PDATA(pgm) ((struct pdata *)(pgm->cookie)) @@ -340,14 +341,18 @@ static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, return -2; } + /* set blocksize depending on sck frequency */ + if ((PDATA(pgm)->sckfreq_hz > 0) && (PDATA(pgm)->sckfreq_hz < 10000)) { + blocksize = USBASP_READBLOCKSIZE / 10; + } else { + blocksize = USBASP_READBLOCKSIZE; + } + while (wbytes) { - if (wbytes > USBASP_READBLOCKSIZE) { - blocksize = USBASP_READBLOCKSIZE; - wbytes -= USBASP_READBLOCKSIZE; - } else { + if (wbytes <= blocksize) { blocksize = wbytes; - wbytes = 0; } + wbytes -= blocksize; /* set address (new mode) - if firmware on usbasp support newmode, then they use address from this command */ unsigned char temp[4]; @@ -403,15 +408,21 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, return -2; } + /* set blocksize depending on sck frequency */ + if ((PDATA(pgm)->sckfreq_hz > 0) && (PDATA(pgm)->sckfreq_hz < 10000)) { + blocksize = USBASP_WRITEBLOCKSIZE / 10; + } else { + blocksize = USBASP_WRITEBLOCKSIZE; + } + while (wbytes) { - if (wbytes > USBASP_WRITEBLOCKSIZE) { - blocksize = USBASP_WRITEBLOCKSIZE; - wbytes -= USBASP_WRITEBLOCKSIZE; - } else { + + if (wbytes <= blocksize) { blocksize = wbytes; - wbytes = 0; blockflags |= USBASP_BLOCKFLAG_LAST; } + wbytes -= blocksize; + /* set address (new mode) - if firmware on usbasp support newmode, then they use address from this command */ @@ -451,20 +462,20 @@ static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, } -/* The list of SCK frequencies in kHz supported by USBasp */ +/* The list of SCK frequencies in Hz 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 } + { USBASP_ISP_SCK_1500, 1500000 }, + { USBASP_ISP_SCK_750, 750000 }, + { USBASP_ISP_SCK_375, 375000 }, + { USBASP_ISP_SCK_187_5, 187500 }, + { USBASP_ISP_SCK_93_75, 93750 }, + { USBASP_ISP_SCK_32, 32000 }, + { USBASP_ISP_SCK_16, 16000 }, + { USBASP_ISP_SCK_8, 8000 }, + { USBASP_ISP_SCK_4, 4000 }, + { USBASP_ISP_SCK_2, 2000 }, + { USBASP_ISP_SCK_1, 1000 }, + { USBASP_ISP_SCK_0_5, 500 } }; @@ -481,6 +492,9 @@ static int usbasp_set_sck_period(PROGRAMMER *pgm, double sckperiod) memset(cmd, 0, sizeof(cmd)); memset(res, 0, sizeof(res)); + /* reset global sck frequency to auto */ + PDATA(pgm)->sckfreq_hz = 0; + if (sckperiod == 0) { /* auto sck set */ @@ -489,22 +503,21 @@ static int usbasp_set_sck_period(PROGRAMMER *pgm, double sckperiod) } else { - double sckfreq = 1 / sckperiod / 1000; /* sck in kHz */ - double usefreq = 0; + int sckfreq = 1 / sckperiod; /* sck in Hz */ + int 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; + fprintf(stderr, "%s: try to set SCK period to %g s (= %i Hz)\n", progname, sckperiod, sckfreq); + if (sckfreq >= usbaspSCKoptions[0].frequency) { + clockoption = usbaspSCKoptions[0].id; + usefreq = usbaspSCKoptions[0].frequency; } 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) { + if (sckfreq >= usbaspSCKoptions[i].frequency - 1) { /* subtract 1 to compensate round errors */ clockoption = usbaspSCKoptions[i].id; usefreq = usbaspSCKoptions[i].frequency; break; @@ -512,7 +525,10 @@ static int usbasp_set_sck_period(PROGRAMMER *pgm, double sckperiod) } } - fprintf(stderr, "%s: set SCK frequency to %g kHz\n", progname, usefreq); + /* save used sck frequency */ + PDATA(pgm)->sckfreq_hz = usefreq; + + fprintf(stderr, "%s: set SCK frequency to %i Hz\n", progname, usefreq); } cmd[0] = clockoption;