From 33c5f3798a9a21b0b3a0c7f77b0994eedcc4642d Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Fri, 13 Sep 2013 21:32:00 +0000 Subject: [PATCH] * stk500v2.c (stk500v2_set_sck_period): Revamp this to match the description/pseudo-code in appnote AVR068. git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@1229 81a1dc3b-b13d-400b-aceb-764788c761c2 --- avrdude/ChangeLog | 5 ++++ avrdude/NEWS | 1 + avrdude/stk500v2.c | 72 ++++++++++++++++++++++++++++++---------------- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog index ac7a93a1..0e61c8c2 100644 --- a/avrdude/ChangeLog +++ b/avrdude/ChangeLog @@ -1,3 +1,8 @@ +2013-09-13 Joerg Wunsch + + * stk500v2.c (stk500v2_set_sck_period): Revamp this to match the + description/pseudo-code in appnote AVR068. + 2013-09-13 Joerg Wunsch Submitted by Stephen Roe: diff --git a/avrdude/NEWS b/avrdude/NEWS index c2808a1f..1983dc58 100644 --- a/avrdude/NEWS +++ b/avrdude/NEWS @@ -112,6 +112,7 @@ Current: - patch #7657: Add ATmega406 support for avrdude using DRAGON + JTAG - bug #35474: Feature request: print fuse values in safemode output. - patch #7710: usb_libusb: Check VID/PID before opening device + - [no-id]: Fix SCK period adjustment for STK500v2 * Keep track of input file contents diff --git a/avrdude/stk500v2.c b/avrdude/stk500v2.c index 9ee51132..bdae5ef6 100644 --- a/avrdude/stk500v2.c +++ b/avrdude/stk500v2.c @@ -281,6 +281,7 @@ static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize); +static double stk500v2_sck_to_us(PROGRAMMER * pgm, unsigned char dur); static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v); static int stk600_set_sck_period(PROGRAMMER * pgm, double v); @@ -2860,37 +2861,60 @@ static unsigned int stk500v2_mode_for_pagesize(unsigned int pagesize) exit(1); } -/* This code assumes that each count of the SCK duration parameter - represents 8/f, where f is the clock frequency of the STK500V2 master - processors (not the target). This number comes from Atmel - application note AVR061. It appears that the STK500V2 bit bangs SCK. - For small duration values, the actual SCK width is larger than - expected. As the duration value increases, the SCK width error - diminishes. */ +/* + * See pseudo-code in AVR068 + * + * This algorithm only fits for the STK500 itself. For the (old) + * AVRISP, the resulting ISP clock is only half. While this would be + * easy to fix in the algorithm, we'd need to add another + * configuration flag for this to the config file. Given the old + * AVRISP devices are virtually no longer around (and the AVRISPmkII + * uses a different algorithm below), it's probably not worth the + * hassle. + */ static int stk500v2_set_sck_period(PROGRAMMER * pgm, double v) { + unsigned int d; unsigned char dur; - double min, max; + double f = 1 / v; - min = 8.0 / STK500V2_XTAL; - max = 255 * min; - dur = v / min + 0.5; - - if (v < min) { - dur = 1; - fprintf(stderr, - "%s: stk500v2_set_sck_period(): p = %.1f us too small, using %.1f us\n", - progname, v / 1e-6, dur * min / 1e-6); - } else if (v > max) { - dur = 255; - fprintf(stderr, - "%s: stk500v2_set_sck_period(): p = %.1f us too large, using %.1f us\n", - progname, v / 1e-6, dur * min / 1e-6); - } + if (f >= 1.8432E6) + d = 0; + else if (f > 460.8E3) + d = 1; + else if (f > 115.2E3) + d = 2; + else if (f > 57.6E3) + d = 3; + else + d = (unsigned int)ceil(1 / (24 * f / (double)STK500V2_XTAL) - 10.0 / 12.0); + if (d >= 255) + d = 254; + dur = d; return stk500v2_setparm(pgm, PARAM_SCK_DURATION, dur); } +static double stk500v2_sck_to_us(PROGRAMMER * pgm, unsigned char dur) +{ + double x; + + if (dur == 0) + return 0.5425; + if (dur == 1) + return 2.17; + if (dur == 2) + return 8.68; + if (dur == 3) + return 17.36; + + x = (double)dur + 10.0 / 12.0; + x = 1.0 / x; + x /= 24.0; + x *= (double)STK500V2_XTAL; + return 1E6 / x; +} + static int stk600_set_vtarget(PROGRAMMER * pgm, double v) { @@ -3255,7 +3279,7 @@ static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p) stk500v2_getparm(pgm, PARAM_OSC_PSCALE, &osc_pscale); stk500v2_getparm(pgm, PARAM_OSC_CMATCH, &osc_cmatch); fprintf(stderr, "%sSCK period : %.1f us\n", p, - sck_duration * 8.0e6 / STK500V2_XTAL + 0.05); + stk500v2_sck_to_us(pgm, sck_duration)); fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0); fprintf(stderr, "%sOscillator : ", p); if (osc_pscale == 0)