348 lines
7.1 KiB
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;
|
|
}
|
|
|