Commit 1899112d authored by Valentin Dudouyt's avatar Valentin Dudouyt

AVR & PIC fuses support

parent e79818a9
COMMON_OBJECTS=byte_utils.o database.o minipro.o
COMMON_OBJECTS=byte_utils.o database.o minipro.o fuses.o easyconfig.o
OBJECTS=$(COMMON_OBJECTS) main.o minipro-query-db.o
PROGS=minipro minipro-query-db
MINIPRO=minipro
......
#ifndef __DATABASE_H
#define __DATABASE_H
#include "fuses.h"
typedef struct device {
const char *name;
unsigned int protocol_id;
......@@ -11,7 +13,7 @@ typedef struct device {
enum { BYTE, WORD, BIT } word_size;
unsigned int code_memory_size; // Presenting for every device
unsigned int data_memory_size; // Usually MCU's EEPROM
unsigned int data_memory_size;
unsigned int data_memory2_size;
unsigned int chip_id; // A vendor-specific chip ID (i.e. 0x1E9502 for ATMEGA48)
unsigned int chip_id_bytes_count : 3;
......@@ -21,7 +23,8 @@ typedef struct device {
unsigned int opts4;
unsigned int package_details; // pins count or image ID for some devices
unsigned int write_unlock;
void *config;
fuse_decl_t *fuses; // Configuration bytes that's presenting in some architectures
} device_t;
#define WORD_SIZE(device) (((device)->opts4 & 0xFF000000) == 0x01000000 ? 2 : 1)
......
......@@ -6,6 +6,9 @@
#include "main.h"
#include "minipro.h"
#include "database.h"
#include "byte_utils.h"
#include "fuses.h"
#include "easyconfig.h"
#include "error.h"
struct {
......@@ -204,6 +207,79 @@ void write_page_file(minipro_handle_t *handle, const char *filename, unsigned in
free(buf);
}
void read_fuses(minipro_handle_t *handle, const char *filename, fuse_decl_t *fuses) {
printf("Reading fuses... ");
fflush(stdout);
if(Config_init(filename)) {
PERROR("Couldn't create config");
}
minipro_begin_transaction(handle);
int i, d;
char data_length = 0, opcode = fuses[0].minipro_cmd;
char buf[11];
for(i = 0; fuses[i].name; i++) {
data_length += fuses[i].length;
if(fuses[i].minipro_cmd < opcode) {
ERROR("fuse_decls are not sorted");
}
if(fuses[i+1].name == NULL || fuses[i+1].minipro_cmd > opcode) {
minipro_read_fuses(handle, opcode, data_length, buf);
// Unpacking received buf[] accordingly to fuse_decls with same minipro_cmd
for(d = 0; fuses[d].name; d++) {
if(fuses[d].minipro_cmd != opcode) {
continue;
}
int value = load_int(&(buf[fuses[d].offset]), fuses[d].length, MP_LITTLE_ENDIAN);
Config_set_int(fuses[d].name, value);
}
opcode = fuses[i+1].minipro_cmd;
data_length = 0;
}
}
minipro_end_transaction(handle);
Config_close();
printf("OK\n");
}
void write_fuses(minipro_handle_t *handle, const char *filename, fuse_decl_t *fuses) {
printf("Writing fuses... ");
fflush(stdout);
if(Config_open(filename)) {
PERROR("Couldn't open config");
}
minipro_begin_transaction(handle);
int i, d;
char data_length = 0, opcode = fuses[0].minipro_cmd;
char buf[11];
for(i = 0; fuses[i].name; i++) {
data_length += fuses[i].length;
if(fuses[i].minipro_cmd < opcode) {
ERROR("fuse_decls are not sorted");
}
if(fuses[i+1].name == NULL || fuses[i+1].minipro_cmd > opcode) {
for(d = 0; fuses[d].name; d++) {
if(fuses[d].minipro_cmd != opcode) {
continue;
}
int value = Config_get_int(fuses[d].name);
format_int(&(buf[fuses[d].offset]), value, fuses[d].length, MP_LITTLE_ENDIAN);
}
minipro_write_fuses(handle, opcode, data_length, buf);
opcode = fuses[i+1].minipro_cmd;
data_length = 0;
}
}
minipro_end_transaction(handle);
Config_close();
printf("OK\n");
}
void verify_page_file(minipro_handle_t *handle, const char *filename, unsigned int type, const char *name, int size) {
FILE *file = fopen(filename, "r");
if(file == NULL) {
......@@ -241,12 +317,15 @@ void verify_page_file(minipro_handle_t *handle, const char *filename, unsigned i
void action_read(const char *filename, minipro_handle_t *handle, device_t *device) {
char *code_filename = (char*) filename;
char *data_filename = (char*) filename;
char *config_filename = (char*) filename;
char default_data_filename[] = "eeprom.bin";
char default_config_filename[] = "fuses.conf";
minipro_begin_transaction(handle); // Prevent device from hanging
switch(cmdopts.page) {
case UNSPECIFIED:
data_filename = default_data_filename;
config_filename = default_config_filename;
case CODE:
read_page_file(handle, code_filename, MP_READ_CODE, "Code", device->code_memory_size);
if(cmdopts.page) break;
......@@ -254,6 +333,11 @@ void action_read(const char *filename, minipro_handle_t *handle, device_t *devic
if(device->data_memory_size) {
read_page_file(handle, data_filename, MP_READ_DATA, "Data", device->data_memory_size);
}
if(cmdopts.page) break;
case CONFIG:
if(device->fuses) {
read_fuses(handle, config_filename, device->fuses);
}
break;
}
minipro_end_transaction(handle); // Let prepare_writing() to make an effect
......@@ -280,6 +364,11 @@ void action_write(const char *filename, minipro_handle_t *handle, device_t *devi
write_page_file(handle, filename, MP_WRITE_DATA, "Data", device->data_memory_size);
verify_page_file(handle, filename, MP_READ_DATA, "Data", device->data_memory_size);
break;
case CONFIG:
if(device->fuses) {
write_fuses(handle, filename, device->fuses);
}
break;
}
minipro_end_transaction(handle); // Let prepare_writing() to make an effect
}
......@@ -313,6 +402,17 @@ int main(int argc, char **argv) {
minipro_end_transaction(handle);
}
/* TODO: put in devices.h and remove this stub */
switch(device->protocol_id) {
case 0x71:
device->fuses = avr_fuses;
break;
case 0x63:
case 0x65:
device->fuses = pic_fuses;
break;
}
cmdopts.action(cmdopts.filename, handle, device);
minipro_close(handle);
......
......@@ -52,7 +52,7 @@ static void msg_init(char *out_buf, char cmd, device_t *device) {
static unsigned int msg_transfer(minipro_handle_t *handle, char *buf, unsigned int length, int direction) {
int bytes_transferred;
libusb_bulk_transfer(handle->usb_handle, (1 | direction), buf, length, &bytes_transferred, 0);
if(bytes_transferred != length) ERROR("IO error");
if(bytes_transferred != length) ERROR2("IO error: expected %d bytes but %d bytes transferred\n", length, bytes_transferred);
return bytes_transferred;
}
......@@ -116,6 +116,46 @@ int minipro_get_chip_id(minipro_handle_t *handle) {
return(load_int(&(msg[2]), handle->device->chip_id_bytes_count, MP_BIG_ENDIAN));
}
void minipro_read_fuses(minipro_handle_t *handle, unsigned int type, unsigned int length, char *buf) {
msg_init(msg, type, handle->device);
msg[2] = 0x01;
msg[5] = 0x10;
msg_send(handle, msg, 18);
msg_recv(handle, msg, 7 + length);
memcpy(buf, &(msg[7]), length);
}
void minipro_write_fuses(minipro_handle_t *handle, unsigned int type, unsigned int length, char *buf) {
// Perform actual writing
switch(type & 0xf0) {
case 0x10:
msg_init(msg, type + 1, handle->device);
msg[2] = 0x01;
msg[4] = 0xc8;
msg[5] = 0x0f;
msg[6] = 0x00;
memcpy(&(msg[7]), buf, length);
msg_send(handle, msg, 64);
break;
case 0x40:
msg_init(msg, type - 1, handle->device);
memcpy(&(msg[7]), buf, length);
msg_send(handle, msg, 10);
break;
}
// The device waits us to get the status now
msg_init(msg, type, handle->device);
msg[2] = 0x01;
memcpy(&(msg[7]), buf, length);
msg_send(handle, msg, 18);
msg_recv(handle, msg, 7 + length);
if(memcmp(buf, &(msg[7]), length)) {
ERROR("Failed while writing config bytes");
}
}
int minipro_get_system_info(minipro_handle_t *handle, minipro_system_info_t *out) {
char buf[40];
memset(msg, 0x0, 5);
......
......@@ -21,6 +21,8 @@
#define MP_WRITE_CODE 0x20
#define MP_WRITE_DATA 0x31
#define MP_PREPARE_WRITING 0x22
#define MP_READ_CFG 0x12
#define MP_WRITE_CFG 0x13
#define MAX_READ_BUFFER_SIZE 0x400
#define MAX_WRITE_BUFFER_SIZE 0x210
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment