osd-contiki/tools/sensinode/nano_usb_programmer/main.c

348 lines
7.1 KiB
C

/*
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
Copyright (C) 2006-2007 Sensinode Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Address:
Sensinode Ltd.
Teknologiantie 6
90570 Oulu, Finland
E-mail:
info@sensinode.com
*/
/*
To build use the following gcc statement
(assuming you have the d2xx library in the /usr/local/lib directory).
gcc -o bitmode main.c -L. -lftd2xx -Wl,-rpath /usr/local/lib
*/
#include <unistd.h>
#include <getopt.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#endif
#include "prog.h"
#define PRG_VERSION "1.3"
typedef enum
{
USAGE,
VERSION,
SCAN,
WRITE,
READ,
WRITE_MAC,
READ_MAC,
ERASE
}mode_t;
typedef struct opts_t
{
int port;
mode_t mode;
uint8_t write_mac[8];
char *filename;
}opts_t;
opts_t opts;
void usage(char *prg_name)
{
printf("\nUsage: %s [-p port] [-h] [-v] [-f file] [-r] [-w] [-m] [-M <mac>]\n", prg_name);
printf("General options:\n");
printf(" -p/--port [port] Select FTDI device\n");
printf(" -f/--file [filename] File to read/write\n");
printf("Operating modes:\n");
printf(" -d/--devices Scan available devices\n");
printf(" -v/--version Print program version\n");
printf(" -r/--read Read program code into ihex file (see -f)\n");
printf(" -w/--write Program firmware from ihex file (see -f)\n");
printf(" -m/--read-mac Read device MAC address\n");
printf(" -M/--write-mac xx:xx:xx:xx:xx:xx:xx:xx Write device MAC address\n");
printf(" -e/--erase Erase flash (erases MAC address!)\n");
printf("Defaults:\n");
printf("mode = usage\n");
printf("port = undefined\n");
printf("file = stdout\n");
}
int main(int argc, char *argv[])
{
DWORD dwBytesInQueue = 0;
FT_STATUS ftStatus;
FT_HANDLE ftHandle;
unsigned char ucMode = 0x00;
int i=0;
unsigned char wr[1] = { 0x30 };
unsigned char rd[1];
uint16_t chip_id;
if (opts_parse(argc, argv) < 0)
{
usage(argv[0]);
return -1;
}
switch(opts.mode)
{
case VERSION:
printf("Sensinode Nano USB Programmer version %s\n", PRG_VERSION);
return 0;
case USAGE:
usage(argv[0]);
return 0;
case SCAN:
prog_scan();
return 0;
case ERASE:
case READ:
case WRITE:
case READ_MAC:
case WRITE_MAC:
break;
}
printf("Opening programmer.\n");
ftHandle = prog_open(opts.port);
if (ftHandle == 0)
{
return (-1);
}
cdi_start(&chip_id);
printf("Chip ID = %4.4hX.\n", chip_id);
if ((chip_id & 0xFF00) == 0x8500)
{
printf("CC2430 chip found.\n");
}
else if ((chip_id & 0xFF00) == 0x8900)
{
printf("CC2431 chip found.\n");
}
else
{
printf("Unknown chip found.\n");
opts.mode = USAGE;
}
switch(opts.mode)
{
case VERSION:
case USAGE:
break;
case ERASE:
printf("Erase.\n");
break;
case READ:
printf("Read Flash.\n");
cdi_set_address(0);
break;
case WRITE:
{
int rval;
unsigned char page_table[64];
unsigned char page_buffer[128*1024];
printf("Write Flash.\n");
if((rval = hexfile_build_tables(opts.filename, page_buffer, page_table)) == -1)
{
printf("Error\n");
return(-1);
}
else if(rval == 0)
{
printf(".ihex file OK but nothing to write...\n");
return(1);
}
hexfile_program(page_buffer, page_table);
break;
}
case READ_MAC:
printf("Read MAC: ");
cdi_set_address(0x1FFF8);
{
uint8_t mac[8];
cdi_flash_read(mac, 8);
for (i=0; i<8; i++)
{
if (i) printf(":");
printf("%2.2X", mac[i]);
}
printf("\n");
}
break;
case WRITE_MAC:
printf("Write MAC: ");
/* cdi_set_address(0x1F800);
{
uint8_t block[2048];
memset(block, 0xFF, 2048);
for (i=0; i<8; i++)
{
block[2040+i] = opts.write_mac[i];
}
cdi_flash_write(block, 2048);
printf("\n");
}*/
cdi_flash_write_mac(opts.write_mac);
printf("\n");
break;
default:
printf("Duh\n");
break;
}
printf("Closing programmer.\n");
prog_close();
}
static int option_index = 0;
int do_exit = 0;
#define OPTIONS_STRING "p:vdhf:rwmM:e"
/* long option list */
static struct option long_options[] =
{
{"port", 1, NULL, 'p'},
{"version", 0, NULL, 'v'},
{"devices", 0, NULL, 'd'},
{"help", 0, NULL, 'h'},
{"file", 1, NULL, 'f'},
{"read", 0, NULL, 'r'},
{"write", 0, NULL, 'w'},
{"read-mac", 0, NULL, 'm'},
{"write-mac", 1, NULL, 'M'},
{"erase", 0, NULL, 'e'},
{0, 0, 0, 0}
};
int opts_parse(int count, char* param[])
{
int opt;
int error=0;
opts.mode = USAGE;
opts.filename = 0;
while ((opt = getopt_long(count, param, OPTIONS_STRING,
long_options, &option_index)) != -1)
{
fflush(stdout);
switch(opt)
{
case 'p':
opts.port = 0;
if (sscanf(optarg, "%d", &(opts.port)) != 1)
{
if (sscanf(optarg, "/dev/ttyUSB%d", &(opts.port)) != 1)
{
printf("Invalid port.\n");
opts.mode = USAGE;
return 0;
}
}
printf("Port %d.\n", opts.port);
break;
case 'v':
opts.mode = VERSION;
return 0;
case 'd':
opts.mode = SCAN;
return 0;
case 'h':
opts.mode = USAGE;
return 0;
case 'e':
opts.mode = ERASE;
break;
case 'f':
printf("Filename: %s\n", optarg);
opts.filename = malloc(strlen(optarg)+1);
strcpy(opts.filename, optarg);
break;
case 'r':
opts.mode = READ;
break;
case 'w':
opts.mode = WRITE;
break;
case 'm':
opts.mode = READ_MAC;
break;
case 'M':
opts.mode = WRITE_MAC;
if (sscanf(optarg, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&opts.write_mac[0], &opts.write_mac[1],
&opts.write_mac[2], &opts.write_mac[3],
&opts.write_mac[4], &opts.write_mac[5],
&opts.write_mac[6], &opts.write_mac[7]) != 8)
{
printf("Invalid MAC.\n");
opts.mode = USAGE;
}
else
{
printf("MAC to write: %2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX:%2.2hhX\n",
opts.write_mac[0], opts.write_mac[1],
opts.write_mac[2], opts.write_mac[3],
opts.write_mac[4], opts.write_mac[5],
opts.write_mac[6], opts.write_mac[7]);
}
break;
case '?':
printf("Duh\n");
error = -1;
break;
}
}
return error;
}