summaryrefslogtreecommitdiffstats
path: root/pickit2_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'pickit2_spi.c')
-rw-r--r--pickit2_spi.c140
1 files changed, 80 insertions, 60 deletions
diff --git a/pickit2_spi.c b/pickit2_spi.c
index 0bc17afb8..a072a2059 100644
--- a/pickit2_spi.c
+++ b/pickit2_spi.c
@@ -32,8 +32,6 @@
* PICkit2 code: https://github.com/steve-m/avrdude/blob/master/pickit2.c
*/
-#include "platform.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -46,13 +44,15 @@
#include "programmer.h"
#include "spi.h"
-const struct dev_entry devs_pickit2_spi[] = {
+static const struct dev_entry devs_pickit2_spi[] = {
{0x04D8, 0x0033, OK, "Microchip", "PICkit 2"},
{0}
};
-static libusb_device_handle *pickit2_handle;
+struct pickit2_spi_data {
+ libusb_device_handle *pickit2_handle;
+};
/* Default USB transaction timeout in ms */
#define DFLT_TIMEOUT 10000
@@ -89,20 +89,25 @@ static libusb_device_handle *pickit2_handle;
#define SCR_VDD_OFF 0xFE
#define SCR_VDD_ON 0xFF
-static int pickit2_get_firmware_version(void)
+static int pickit2_interrupt_transfer(libusb_device_handle *handle, unsigned char endpoint, unsigned char *data)
+{
+ int transferred;
+ return libusb_interrupt_transfer(handle, endpoint, data, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+}
+
+static int pickit2_get_firmware_version(libusb_device_handle *pickit2_handle)
{
int ret;
uint8_t command[CMD_LENGTH] = {CMD_GET_VERSION, CMD_END_OF_BUFFER};
- int transferred;
- ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+ ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
if (ret != 0) {
msg_perr("Command Get Firmware Version failed!\n");
return 1;
}
- ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_IN, command, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+ ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_IN, command);
if (ret != 0) {
msg_perr("Command Get Firmware Version failed!\n");
@@ -113,7 +118,7 @@ static int pickit2_get_firmware_version(void)
return 0;
}
-static int pickit2_set_spi_voltage(int millivolt)
+static int pickit2_set_spi_voltage(libusb_device_handle *pickit2_handle, int millivolt)
{
double voltage_selector;
switch (millivolt) {
@@ -148,8 +153,7 @@ static int pickit2_set_spi_voltage(int millivolt)
voltage_selector * 13,
CMD_END_OF_BUFFER
};
- int transferred;
- int ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+ int ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
if (ret != 0) {
msg_perr("Command Set Voltage failed!\n");
@@ -172,7 +176,7 @@ static const struct pickit2_spispeeds spispeeds[] = {
{ NULL, 0x0 },
};
-static int pickit2_set_spi_speed(unsigned int spispeed_idx)
+static int pickit2_set_spi_speed(libusb_device_handle *pickit2_handle, unsigned int spispeed_idx)
{
msg_pdbg("SPI speed is %sHz\n", spispeeds[spispeed_idx].name);
@@ -184,8 +188,7 @@ static int pickit2_set_spi_speed(unsigned int spispeed_idx)
CMD_END_OF_BUFFER
};
- int transferred;
- int ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+ int ret = pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command);
if (ret != 0) {
msg_perr("Command Set SPI Speed failed!\n");
@@ -198,13 +201,15 @@ static int pickit2_set_spi_speed(unsigned int spispeed_idx)
static int pickit2_spi_send_command(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
+ struct pickit2_spi_data *pickit2_data = flash->mst->spi.data;
+ const unsigned int total_packetsize = writecnt + readcnt + 20;
/* Maximum number of bytes per transaction (including command overhead) is 64. Lets play it safe
* and always assume the worst case scenario of 20 bytes command overhead.
*/
- if (writecnt + readcnt + 20 > CMD_LENGTH) {
- msg_perr("\nTotal packetsize (%i) is greater than 64 supported, aborting.\n",
- writecnt + readcnt + 20);
+ if (total_packetsize > CMD_LENGTH) {
+ msg_perr("\nTotal packetsize (%i) is greater than %i supported, aborting.\n",
+ total_packetsize, CMD_LENGTH);
return 1;
}
@@ -254,8 +259,7 @@ static int pickit2_spi_send_command(const struct flashctx *flash, unsigned int w
buf[i++] = CMD_UPLOAD_DATA;
buf[i++] = CMD_END_OF_BUFFER;
- int transferred;
- int ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, buf, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+ int ret = pickit2_interrupt_transfer(pickit2_data->pickit2_handle, ENDPOINT_OUT, buf);
if (ret != 0) {
msg_perr("Send SPI failed!\n");
@@ -264,7 +268,8 @@ static int pickit2_spi_send_command(const struct flashctx *flash, unsigned int w
if (readcnt) {
int length = 0;
- ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_IN, buf, CMD_LENGTH, &length, DFLT_TIMEOUT);
+ ret = libusb_interrupt_transfer(pickit2_data->pickit2_handle,
+ ENDPOINT_IN, buf, CMD_LENGTH, &length, DFLT_TIMEOUT);
if (length == 0 || ret != 0) {
msg_perr("Receive SPI failed\n");
@@ -335,18 +340,10 @@ static int parse_voltage(char *voltage)
return millivolt;
}
-static const struct spi_master spi_master_pickit2 = {
- .max_data_read = 40,
- .max_data_write = 40,
- .command = pickit2_spi_send_command,
- .multicommand = default_spi_send_multicommand,
- .read = default_spi_read,
- .write_256 = default_spi_write_256,
- .write_aai = default_spi_write_aai,
-};
-
static int pickit2_shutdown(void *data)
{
+ struct pickit2_spi_data *pickit2_data = data;
+
/* Set all pins to float and turn voltages off */
uint8_t command[CMD_LENGTH] = {
CMD_EXEC_SCRIPT,
@@ -362,23 +359,33 @@ static int pickit2_shutdown(void *data)
CMD_END_OF_BUFFER
};
- int transferred;
- int ret = libusb_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, command, CMD_LENGTH, &transferred, DFLT_TIMEOUT);
+ int ret = pickit2_interrupt_transfer(pickit2_data->pickit2_handle, ENDPOINT_OUT, command);
if (ret != 0) {
msg_perr("Command Shutdown failed!\n");
ret = 1;
}
- if (libusb_release_interface(pickit2_handle, 0) != 0) {
+ if (libusb_release_interface(pickit2_data->pickit2_handle, 0) != 0) {
msg_perr("Could not release USB interface!\n");
ret = 1;
}
- libusb_close(pickit2_handle);
+ libusb_close(pickit2_data->pickit2_handle);
libusb_exit(NULL);
+
+ free(data);
return ret;
}
-int pickit2_spi_init(void)
+static const struct spi_master spi_master_pickit2 = {
+ .max_data_read = 40,
+ .max_data_write = 40,
+ .command = pickit2_spi_send_command,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+ .shutdown = pickit2_shutdown,
+};
+
+static int pickit2_spi_init(const struct programmer_cfg *cfg)
{
uint8_t buf[CMD_LENGTH] = {
CMD_EXEC_SCRIPT,
@@ -397,30 +404,33 @@ int pickit2_spi_init(void)
CMD_END_OF_BUFFER
};
-
+ libusb_device_handle *pickit2_handle;
+ struct pickit2_spi_data *pickit2_data;
int spispeed_idx = 0;
- char *spispeed = extract_programmer_param("spispeed");
- if (spispeed != NULL) {
+ char *param_str;
+
+ param_str = extract_programmer_param_str(cfg, "spispeed");
+ if (param_str != NULL) {
int i = 0;
for (; spispeeds[i].name; i++) {
- if (strcasecmp(spispeeds[i].name, spispeed) == 0) {
+ if (strcasecmp(spispeeds[i].name, param_str) == 0) {
spispeed_idx = i;
break;
}
}
if (spispeeds[i].name == NULL) {
msg_perr("Error: Invalid 'spispeed' value.\n");
- free(spispeed);
+ free(param_str);
return 1;
}
- free(spispeed);
+ free(param_str);
}
int millivolt = 3500;
- char *voltage = extract_programmer_param("voltage");
- if (voltage != NULL) {
- millivolt = parse_voltage(voltage);
- free(voltage);
+ param_str = extract_programmer_param_str(cfg, "voltage");
+ if (param_str != NULL) {
+ millivolt = parse_voltage(param_str);
+ free(param_str);
if (millivolt < 0)
return 1;
}
@@ -458,34 +468,44 @@ int pickit2_spi_init(void)
return 1;
}
- if (register_shutdown(pickit2_shutdown, NULL) != 0) {
+ pickit2_data = calloc(1, sizeof(*pickit2_data));
+ if (!pickit2_data) {
+ msg_perr("Unable to allocate space for SPI master data\n");
+ libusb_close(pickit2_handle);
+ libusb_exit(NULL);
return 1;
}
+ pickit2_data->pickit2_handle = pickit2_handle;
- if (pickit2_get_firmware_version()) {
- return 1;
- }
+ if (pickit2_get_firmware_version(pickit2_handle))
+ goto init_err_cleanup_exit;
/* Command Set SPI Speed */
- if (pickit2_set_spi_speed(spispeed_idx)) {
- return 1;
- }
+ if (pickit2_set_spi_speed(pickit2_handle, spispeed_idx))
+ goto init_err_cleanup_exit;
/* Command Set SPI Voltage */
msg_pdbg("Setting voltage to %i mV.\n", millivolt);
- if (pickit2_set_spi_voltage(millivolt) != 0) {
- return 1;
- }
+ if (pickit2_set_spi_voltage(pickit2_handle, millivolt) != 0)
+ goto init_err_cleanup_exit;
/* Perform basic setup.
* Configure pin directions and logic levels, turn Vdd on, turn busy LED on and clear buffers. */
- int transferred;
- if (libusb_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, buf, CMD_LENGTH, &transferred, DFLT_TIMEOUT) != 0) {
+ if (pickit2_interrupt_transfer(pickit2_handle, ENDPOINT_OUT, buf) != 0) {
msg_perr("Command Setup failed!\n");
- return 1;
+ goto init_err_cleanup_exit;
}
- register_spi_master(&spi_master_pickit2);
+ return register_spi_master(&spi_master_pickit2, pickit2_data);
- return 0;
+init_err_cleanup_exit:
+ pickit2_shutdown(pickit2_data);
+ return 1;
}
+
+const struct programmer_entry programmer_pickit2_spi = {
+ .name = "pickit2_spi",
+ .type = USB,
+ .devs.dev = devs_pickit2_spi,
+ .init = pickit2_spi_init,
+};