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