Attached is a patch I made to allow me to program an AT tiny 2313
after setting its fuse bits to use the slower (100 kHz?) oscillator.
The normal Bus Pirate SPI mode only goes down to 30 kHz which isn’t
quite slow enough, but my Bus Pirate has another mode which also seems
to do SPI and can run at 5 kHz. Basically, I added an extended
parameter called “khz”, and the next lowest matching frequency is
chosen from the available normal SPI and “raw” mode frequencies.

The patch does not include any documentation changes. Also I used a
few C99 features that GCC allows in its default “gnu90” dialect.

I also made another simple change to reduce the Automake noise. Both
of the changes are at
https://github.com/vadmium/avrdude/compare/trunk...master

-Martin
From c57d1faebbb6766b412dc7d6efbfcb52882d0a20 Mon Sep 17 00:00:00 2001
From: Marty <->
Date: Mon, 2 Jan 2012 16:09:25 +1100
Subject: [PATCH] =?UTF-8?q?Use=20Bus=20Pirate=20=E2=80=9Craw-wire=E2=80=9D=20?=
 =?UTF-8?q?mode=20which=20can=20run=20down=20to=205=20kHz.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The frequency can be selected with a new Bus Pirate parameter “khz”, which
chooses the closest matching frequency from the possible SPI and raw-wire
frequencies.

This enables programming when the minimum 30 kHz SPI rate is not low enough.
---
 buspirate.c |  126 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 97 insertions(+), 29 deletions(-)

diff --git a/buspirate.c b/buspirate.c
index d2034aa..d010f65 100644
--- a/buspirate.c
+++ b/buspirate.c
@@ -50,6 +50,8 @@
 #include "pgm.h"
 #include "serial.h"
 
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a)[0])
+
 /* ====== Private data structure ====== */
 /* CS and AUX pin bitmasks in
  * 0100wxyz - Configure peripherals command */
@@ -60,16 +62,17 @@
 #define BP_FLAG_IN_BINMODE          (1<<0)
 #define BP_FLAG_XPARM_FORCE_ASCII   (1<<1)
 #define BP_FLAG_XPARM_RESET         (1<<2)
-#define BP_FLAG_XPARM_SPIFREQ       (1<<3)
+#define BP_FLAG_BIN_SPI       (1<<3)
+#define BP_FLAG_BIN_RAW       (1<<4)
 
 struct pdata
 {
 	char	hw_version[10];
 	int	fw_version;		/* = 100*fw_major + fw_minor */
 	int	binmode_version;
-	int	bin_spi_version;
+	int	submode_version;
 	int	current_peripherals_config;
-	int	spifreq;		/* 0..7 - see buspirate manual for what freq each value means */
+	int	speed;		/* Value for "set speed" bin mode commands */
 	int	reset;			/* See BP_RESET_* above */
 };
 #define PDATA(pgm) ((struct pdata *)(pgm->cookie))
@@ -309,8 +312,48 @@ buspirate_parseextparms(struct programmer_t *pgm, LISTID extparms)
 				fprintf(stderr, "BusPirate: see BusPirate manual for details.\n");
 				return -1;
 			}
-			PDATA(pgm)->spifreq = spifreq;
-			pgm->flag |= BP_FLAG_XPARM_SPIFREQ;
+			pgm->flag |= BP_FLAG_BIN_SPI;
+			PDATA(pgm)->speed = spifreq;
+			continue;
+		}
+		
+		unsigned khz;
+		if (sscanf(extended_param, "khz=%u", &khz) == 1) {
+			static const struct
+			{unsigned khz; char flag; int speed;} freq_map[] = {
+				{.khz=8000, .flag=BP_FLAG_BIN_SPI, .speed=7},
+				{.khz=4000, .flag=BP_FLAG_BIN_SPI, .speed=6},
+				{.khz=2600, .flag=BP_FLAG_BIN_SPI, .speed=5},
+				{.khz=2000, .flag=BP_FLAG_BIN_SPI, .speed=4},
+				{.khz=1000, .flag=BP_FLAG_BIN_SPI, .speed=3},
+				{.khz=400, .flag=BP_FLAG_BIN_RAW, .speed=3},
+				{.khz=250, .flag=BP_FLAG_BIN_SPI, .speed=2},
+				{.khz=125, .flag=BP_FLAG_BIN_SPI, .speed=1},
+				{.khz=100, .flag=BP_FLAG_BIN_RAW, .speed=2},
+				{.khz=50, .flag=BP_FLAG_BIN_RAW, .speed=1},
+				{.khz=30, .flag=BP_FLAG_BIN_SPI, .speed=0},
+				{.khz=5, .flag=BP_FLAG_BIN_RAW, .speed=0},
+			};
+			
+			/* Find closest frequency <= requested frequency */
+			size_t i;
+			for (i = 0; i < ARRAY_SIZE(freq_map); ++i) {
+				if (freq_map[i].khz <= khz) {
+					break;
+				}
+			}
+			if (i >= ARRAY_SIZE(freq_map)) {
+				fprintf(stderr, "BusPirate: Requested "
+					"frequency too low: %d kHz\n", khz);
+				return -1;
+			}
+			if (khz != freq_map[i].khz) {
+				fprintf(stderr, "BusPirate: Closest "
+					"matching frequency: %d kHz\n",
+					freq_map[i].khz);
+			}
+			pgm->flag |= freq_map[i].flag;
+			PDATA(pgm)->speed = freq_map[i].speed;
 			continue;
 		}
 
@@ -358,8 +401,9 @@ buspirate_verifyconfig(struct programmer_t *pgm)
 		return -1;
 	}
 
-	if ((pgm->flag & BP_FLAG_XPARM_SPIFREQ) && buspirate_uses_ascii(pgm)) {
-		fprintf(stderr, "BusPirate: SPI speed selection is not supported in ASCII mode\n");
+	if (((pgm->flag & BP_FLAG_BIN_SPI) || (pgm->flag & BP_FLAG_BIN_RAW))
+	&& buspirate_uses_ascii(pgm)) {
+		fprintf(stderr, "BusPirate: speed selection is not supported in ASCII mode\n");
 		return -1;
 	}
 
@@ -424,8 +468,36 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
 		fprintf(stderr, "BusPirate is back in the text mode\n");
 }
 
-static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
-{
+static int buspirate_start_mode_bin(struct programmer_t *pgm)
+{
+	const struct submode {
+		const char* name; /* Name of mode for user messages */
+		char enter; /* Command to enter from base binary mode */
+		const char* entered_format; /* Response, for "scanf" */
+		char config; /* Command to setup submode parameters */
+	}* submode;
+	if (pgm->flag & BP_FLAG_BIN_RAW) {
+		submode = &(const struct submode){
+			.name = "Raw-wire",
+			.enter = 0x05,
+			.entered_format = "RAW%d",
+			.config = 0x8C,
+		};
+	} else {
+		submode = &(const struct submode){
+			.name = "SPI",
+			.enter = 0x01,
+			.entered_format = "SPI%d",
+			
+			/* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
+			 * we want: 3.3V(1), idle low(0), data change on
+			 *          trailing edge (1), sample in the middle
+			 *          of the pulse (0)
+			 *       => 0b10001010 = 0x8a */
+			.config = 0x8A,
+		};
+	}
+	
 	char buf[20] = { '\0' };
 
 	/* == Switch to binmode - send 20x '\0' == */
@@ -445,19 +517,21 @@ static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
 
 	pgm->flag |= BP_FLAG_IN_BINMODE;
 
-	/* == Enter SPI mode == */
-	buf[0] = 0x01;	/* Enter raw SPI mode */
+	/* == Set protocol sub-mode of binary mode == */
+	buf[0] = submode->enter;
 	buspirate_send_bin(pgm, buf, 1);
 	memset(buf, 0, sizeof(buf));
 	buspirate_recv_bin(pgm, buf, 4);
-	if (sscanf(buf, "SPI%d", &PDATA(pgm)->bin_spi_version) != 1) {
-		fprintf(stderr, "SPI mode not confirmed: '%s'\n", buf);
+	if (sscanf(buf, submode->entered_format,
+	&PDATA(pgm)->submode_version) != 1) {
+		fprintf(stderr, "%s mode not confirmed: '%s'\n",
+			submode->name, buf);
 		buspirate_reset_from_binmode(pgm);
 		return -1;
 	}
 	if (verbose)
-		fprintf(stderr, "BusPirate SPI version: %d\n",
-			PDATA(pgm)->bin_spi_version);
+		fprintf(stderr, "BusPirate %s version: %d\n",
+			submode->name, PDATA(pgm)->submode_version);
 
 	/* 0b0100wxyz - Configure peripherals w=power, x=pull-ups/aux2, y=AUX, z=CS
 	 * we want power (0x48) and all reset pins high. */
@@ -469,17 +543,11 @@ static int buspirate_start_spi_mode_bin(struct programmer_t *pgm)
 	buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01);
 	usleep(50000);	// sleep for 50ms after power up
 
-	/* 01100xxx -  SPI speed
-	 * xxx = 000=30kHz, 001=125kHz, 010=250kHz, 011=1MHz,
-	 *       100=2MHz, 101=2.6MHz, 110=4MHz, 111=8MHz
-	 * use 30kHz = 0x60 */
-	buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01);
+	/* 01100xxx -  Set speed */
+	buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->speed, 0x01);
 
-	/* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
-	 * we want: 3.3V(1), idle low(0), data change on trailing edge (1),
-	 *          sample in the middle of the pulse (0)
-	 *       => 0b10001010 = 0x8a */
-	buspirate_expect_bin_byte(pgm, 0x8A, 0x01);
+	/* Submode config */
+	buspirate_expect_bin_byte(pgm, submode->config, 0x01);
 
 	return 0;
 }
@@ -591,8 +659,8 @@ static void buspirate_enable(struct programmer_t *pgm)
 
 	if (PDATA(pgm)->fw_version >= FW_BINMODE_VER && !(pgm->flag & BP_FLAG_XPARM_FORCE_ASCII)) {
 		fprintf(stderr, "BusPirate: using BINARY mode\n");
-		if (buspirate_start_spi_mode_bin(pgm) < 0)
-			fprintf(stderr, "%s: Failed to start binary SPI mode\n", progname);
+		if (buspirate_start_mode_bin(pgm) < 0)
+			fprintf(stderr, "%s: Failed to start binary mode\n", progname);
 	}
 	if (!pgm->flag & BP_FLAG_IN_BINMODE) {
 		fprintf(stderr, "BusPirate: using ASCII mode\n");
@@ -622,7 +690,7 @@ static int buspirate_initialize(struct programmer_t *pgm, AVRPART * p)
 static void buspirate_powerup(struct programmer_t *pgm)
 {
 	if (pgm->flag & BP_FLAG_IN_BINMODE) {
-		/* Powerup in BinMode is handled in SPI init */
+		/* Powerup in BinMode is handled in binary mode init */
 		return;
 	} else
 		if (buspirate_expect(pgm, "W\n", "POWER SUPPLIES ON", 1))
@@ -650,7 +718,7 @@ static int buspirate_cmd_bin(struct programmer_t *pgm,
 				unsigned char cmd[4],
 				unsigned char res[4])
 {
-	/* 0001xxxx - Bulk SPI transfer, send/read 1-16 bytes (0=1byte!)
+	/* 0001xxxx - Bulk transfer, send/read 1-16 bytes (0=1byte!)
 	 * we are sending 4 bytes -> 0x13 */
 	if (!buspirate_expect_bin_byte(pgm, 0x13, 0x01))
 		return -1;
-- 
1.7.8

_______________________________________________
avrdude-dev mailing list
avrdude-dev@nongnu.org
https://lists.nongnu.org/mailman/listinfo/avrdude-dev

Reply via email to