- Added the Sensinode platform programming tools to /tools

This commit is contained in:
zdshelby 2009-09-09 09:48:16 +00:00
parent 83988ef554
commit fc237101be
24 changed files with 5847 additions and 0 deletions

View file

@ -0,0 +1,43 @@
EXE_MAKE=$(notdir $(shell which "make.exe" 2>/dev/null))
ifeq "$(EXE_MAKE)" "make.exe"
PLATFORM=windows
else
PLATFORM=linux
endif
OBJECTS = ihex.o $(PLATFORM)/port.o programmer.o cdi_program.o
SUBDIRS =
ifeq "$(PLATFORM)" "linux"
CFLAGS = -Wall -D_REENTRANT -I.
LDFLAGS = -L. -D_REENTRANT -lpthread
SUFFIX=
else
CFLAGS=-I. -I../nano_usb_programmer/ftdi_win32
CFLAGS+= -L. -L../nano_usb_programmer/ftdi_win32 -DPLATFORM_WINDOWS
CFLAGS+= -mwin32
LDFLAGS=../nano_usb_programmer/ftdi_win32/ftd2xx.lib -lkernel32
SUFFIX=.exe
endif
TARGET = nano_programmer$(SUFFIX)
all: binary
binary: $(TARGET)
strip $(TARGET)
$(TARGET): $(OBJECTS)
gcc -o $(TARGET) $(OBJECTS) $(LDFLAGS)
.c.o:
gcc -c -o $(<:.c=.o) -O2 -Wall $(CFLAGS) $<
platform-test:
@echo $(PLATFORM)
old-strip:
if [ -x $(TARGET).exe ]; then $(PLATFORM)strip $(TARGET).exe; else $(PLATFORM)strip $(TARGET); fi
clean:
rm -f $(TARGET) $(OBJECTS)

View file

@ -0,0 +1,34 @@
Nano Programmer
Programming tool for the Sensinode Nano series using Dxxx development boards.
Copyright 2007-2008 Sensinode Ltd.
1a - Installation (Linux)
No external libraries required.
1b - Installation (Windows/Cygwin)
Installation procedure:
See the nano_usb_programmer README file on how to install FTDI library
for nano_usb_programmer. The nano_programmer build system will fetch
the library from there.
2 - Usage
Usage info for the Nano Programmer is available with command
./nano_programmer --help. Note that use might require root/administrator privileges
depending on system configuration.
3 - Known problems
Occasional timing failures resulting in "Reinit failed."-messages do come
up in some PC configurations. If you experience programming failures (the programmer
is not able to recover), please report your system configuration to Sensinode.
On Linux, it is known that the "brltty" program causes problems with the FTDI
serial driver. Uninstalling brltty resolves the problem.
4 - README Version
v1.3 2008-01-31 Martti Huttunen Multi-platform build and created instructions

View file

@ -0,0 +1,607 @@
/*
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
*/
#include <unistd.h>
#include <getopt.h>
#include <strings.h>
#include "port.h"
#include "programmer.h"
#include "ihex.h"
#include <stdio.h>
extern void crc_add(unsigned char *crc, unsigned char byte);
int cdi_page_write(port_t *port, unsigned long page_addr, unsigned char *page_buffer);
int cdi_write(port_t *port, conf_opts_t *conf, FILE *ihex);
int cdi_programmer(conf_opts_t *conf, char *filename)
{
int error = 0;
port_t *port = 0;
unsigned char buffer[256];
int length = 0;
FILE *ihex = 0;
error = programmer_init(conf->device, &port);
if (error < 0)
{
return error;
}
if((!error) && (conf->action != 'b'))
{
length = port_write_echo(port, "CDI\r");
bzero(buffer, sizeof(buffer));
if (length >= 4)
{
length = port_readline(port, buffer, sizeof(buffer), 100);
}
else length = 0;
if(memcmp(buffer, "OK", 2) == 0)
{
error = 0;
}
else
{
printf("Programming mode selection failed.\n");
error = -1;
}
}
if((!error) && (conf->action != 'b'))
{
printf("Initialize.\n");
// Succesfully in mode 1
sleep(1);
port_write_echo(port, "i\r");
bzero(buffer, 256);
length = port_readline(port, buffer, sizeof(buffer), 100);
if(memcmp(buffer, "85", 2) == 0)
{ /*Found CC2430 device*/
printf("Found CC2430 device revision %c%c.\n", buffer[2], buffer[3]);
}
else if (memcmp(buffer, "89", 2) == 0)
{
printf("Found CC2431 device revision %c%c.\n", buffer[2], buffer[3]);
}
else
{
printf("CC2430 not found.\n");
error = -1;
}
}
if (error) conf->action = ' ';
switch(conf->action)
{
case 'e':
// Erase programming
port_write_echo(port, "e\r");
bzero(buffer, 256);
length = port_readline(port, buffer, sizeof(buffer), 100);
if(memcmp(buffer, "OK", 2) == 0)
{
// Erase successful
printf("Erase successful.\n");
error = 0;
}
else
{
// Erase failed
printf("Erase failed: %s.\n", buffer);
error = -1;
}
if ((conf->action != 'P') || error)
break;
case 'P':
case 'w':
ihex = fopen(conf->ihex_file, "rb");
if(ihex == NULL)
{
printf("Failed to open ihex file %s.\n", conf->ihex_file);
error = -1;
}
else error = 0;
if (!error)
{
error = cdi_write(port, conf, ihex);
if (error) printf("Programming failed.\n");
}
if (ihex != NULL) fclose(ihex);
break;
case 'b':
length = port_write_echo(port, "V\r");
bzero(buffer, sizeof(buffer));
if (length >= 2)
{
length = port_readline(port, buffer, sizeof(buffer), 100);
}
else length = 0;
if(length > 4)
{
buffer[length] = 0;
printf("BIOS: %s\n", buffer);
error = 0;
}
else
{
printf("Failed to get BIOS version. Upgrade recommended.\n");
error = -1;
}
break;
case 'v':
break;
case 'r':
ihex = fopen(conf->ihex_file, "wb");
if(ihex == NULL)
{
printf("Failed to open ihex file %s.\n", conf->ihex_file);
error = -1;
}
else
{
port_write_echo(port, "a000000\r");
bzero(buffer, sizeof(buffer));
length = port_readline(port, buffer, sizeof(buffer), 200);
if (length <0) length = 0;
if(memcmp(buffer, "OK", 2) == 0)
{
uint32_t address = 0;
uint8_t check = 0;
for (address = 0; address < 128*1024; address += 64)
{
uint8_t i;
if ((address) && ((address & 0xFFFF)==0))
{
fprintf(ihex, ":02000004%4.4X%2.2X\r\n",
(int)(address>>16), (int)(0xFA-(address>>16)));
}
port_write_echo(port, "r\r");
bzero(buffer, 256);
length = 0;
while (length < 64)
{
length += port_readline(port, &buffer[length], sizeof(buffer)-length, 100);
}
for (i=0; i<64; i++)
{
if ((i & 0x0F) == 0)
{
check = 0;
check -= 0x10;
check -= (uint8_t) (address >> 8);
check -= (uint8_t) (address + i);
printf("%4.4X", (int) address + i);
fprintf(ihex, ":10%4.4X00", (int) (address + i) & 0xFFFF);
}
fprintf(ihex, "%2.2X", buffer[i]);
check -= buffer[i];
if ((i & 0x0F) == 0x0F)
{
fprintf(ihex, "%2.2X\r\n", check);
if (i > 0x30) printf("\n");
else printf(" ");
}
}
}
fprintf(ihex, ":00000001FF\r\n");
}
else
{
printf("Failed to set read address.\n");
error = -1;
}
fclose(ihex);
}
break;
/*skip for error case*/
case ' ':
break;
case 'm':
port_write_echo(port, "a01F800\r");
bzero(buffer, sizeof(buffer));
length = port_readline(port, buffer, sizeof(buffer), 200);
if (length <0) length = 0;
if(memcmp(buffer, "OK", 2) == 0)
{
uint8_t i;
uint32_t address = 0;
for (address = 0x01F800; address < 128*1024; address += 64)
{
port_write_echo(port, "r\r");
bzero(buffer, 256);
length = 0;
while (length < 64)
{
length += port_readline(port, &buffer[length], sizeof(buffer)-length, 100);
}
if ((address & 0xff) == 0)
{ printf(".");
fflush(stdout);
}
}
printf("\nDevice MAC: ");
for (i=56; i<64; i++)
{
if (i != 56) printf(":");
printf("%2.2X", buffer[i]);
}
printf("\n");
}
break;
case 'Q':
port_write_echo(port, "a01F800\r");
bzero(buffer, sizeof(buffer));
length = port_readline(port, buffer, sizeof(buffer), 200);
if (length <0) length = 0;
if(memcmp(buffer, "OK", 2) == 0)
{
uint8_t p_buffer[2048];
int error;
memset(p_buffer, 0xff, sizeof(p_buffer));
memcpy(&p_buffer[2040], conf->write_mac, 8);
printf("\rWriting MAC: ");
error = cdi_page_write(port, 0x01F800, p_buffer);
if (!error)
{
printf("Write complete.\n");
}
else
{
printf("Write failed.\n");
}
}
break;
default:
printf("Unknown CDI action.\n");
break;
}
printf("Close programmer.\n");
usleep(100000);
port_write_echo(port, "q\r");
programmer_close(port);
return error;
}
int cdi_write(port_t *port, conf_opts_t *conf, FILE *ihex)
{
int error = 0;
unsigned char buffer[256];
int length;
int i;
int pages;
unsigned long ext_addr=0;
unsigned short int addr=0;
unsigned char page_buffer[128*1024];
unsigned char page_table[64];
bzero(buffer, sizeof(buffer));
/*initialize page data*/
memset(page_table, 0, 64);
memset(page_buffer, 0xFF, sizeof(page_buffer));
pages = 0;
error = 0;
if (conf->page_mode == PAGE_UNDEFINED)
{
int retval;
while((!error) && ((retval = fscanf(ihex, "%s", buffer)) == 1) )
{
unsigned char data_len = 0;
if (memcmp(&buffer[7], "00", 2) == 0)
{ /*Data record*/
}
else if (memcmp(&buffer[7], "01", 2) == 0)
{ /*end file*/
printf("\nFile read complete.\n");
break;
}
else if (memcmp(&buffer[7], "04", 2) == 0)
{
sscanf((char *)&(buffer[3]),"%4hx", &addr);
sscanf((char *)&(buffer[9]),"%4lx", &ext_addr);
if (ext_addr >= 0x0002)
{
conf->page_mode = PAGE_SDCC;
}
else
{
if (conf->page_mode == PAGE_UNDEFINED) conf->page_mode = PAGE_LINEAR;
}
}
}
if (retval == -1)
{
printf("Read error\n");
return -1;
}
rewind(ihex);
retval = 0;
error = 0;
}
switch (conf->page_mode)
{
case PAGE_SDCC:
printf("SDCC banked file.\n");
break;
case PAGE_LINEAR:
printf("Linear banked file.\n");
break;
case PAGE_UNDEFINED:
printf("Non-banked file, assuming linear.\n");
conf->page_mode = PAGE_LINEAR;
break;
}
while( (fscanf(ihex, "%s", buffer) == 1) && !error)
{
unsigned char data_len = 0;
if (memcmp(&buffer[7], "00", 2) == 0)
{ /*Data record*/
i=0;
sscanf((char *)&buffer[1], "%2hhx", &data_len);
sscanf((char *)&(buffer[3]),"%4hx", &addr);
while(i<data_len)
{
uint32_t absolute_address = ext_addr+addr+i;
if (page_table[absolute_address/2048] == 0)
{
page_table[absolute_address/2048] = 1;
pages++;
}
sscanf((char *)&buffer[2*i+9], "%2hhx", &page_buffer[absolute_address]);
i++;
}
}
else if (memcmp(&buffer[7], "01", 2) == 0)
{ /*end file*/
printf("\nFile read complete.\n");
printf("Writing %d pages.\n", pages);
break;
}
else if (memcmp(&buffer[7], "04", 2) == 0)
{
sscanf((char *)&(buffer[3]),"%4hx", &addr);
sscanf((char *)&(buffer[9]),"%4lx", &ext_addr);
if (conf->page_mode == PAGE_SDCC)
{
if (ext_addr) ext_addr--;
ext_addr *= 0x8000;
}
else
{
ext_addr *= 0x10000;
}
printf("\rExtended page address: 0x%8.8lX\r", ext_addr);
}
}
if (pages)
{
int retry = 0;
// Successfully in mode 3 (programming)
printf("Starting programming.\n");
error = 0;
for (i=0; i<64; i++)
{
if (page_table[i] != 0)
{
ext_addr = 2048*i;
bzero(buffer, sizeof(buffer));
// Write the start address and check return
usleep(3000);
sprintf((char *)buffer, "a%6.6lX\r", ext_addr);
port_write_echo(port, (char *)buffer);
if((length = port_readline(port, buffer, sizeof(buffer), 200)) < 0)
{
printf("Read from serial timed out without data.\n");
error = -1;
break;
}
else
{
if(strncmp((char *)buffer, "OK\r\n", 4) == 0)
{
printf("\r \r");
printf("\rWriting @ 0x%6.6lX: ", ext_addr);
fflush(stdout);
error = cdi_page_write(port, ext_addr, &page_buffer[ext_addr]);
if (error)
{
usleep(20000);
port_write_echo(port, "i\r");
bzero(buffer, 256);
length = port_readline(port, buffer, sizeof(buffer), 100);
if(memcmp(buffer, "85", 2) == 0)
{ /*Found CC2430 device*/
}
else
{
printf("Reinit failed.\n");
error = -1;
}
if (retry++ < 3)
{
error = 0;
i--;
}
}
else retry = 0;
fflush(stdout);
usleep(20000);
}
else
{
printf("Failed to set CDI programming start address.\n");
error = -1;
break;
}
}
}
if (error) break;
}
usleep(200000);
printf("\n");
}
return error;
}
int cdi_page_write(port_t *port, unsigned long page_addr, unsigned char *page_buffer)
{
int error = 0;
unsigned char buffer[80];
unsigned char cmd[16];
unsigned char block, i;
int length;
int retry = 0;
// Write page
port_write_echo(port, "w\r");
usleep(10000);
for (block=0; block<(2048/64); block++)
{
sprintf((char *)cmd, "%6.6lX", page_addr + (64*block));
bzero(buffer, sizeof(buffer));
length = port_readline(port, buffer, sizeof(buffer), 2000);
if (length <0)
{ length = 0;
printf("l!");fflush(stdout);
}
buffer[length] = 0;
if (block & 1)
{
}
if(memcmp(buffer, cmd, 6) == 0)
{
#define WRITE_SIZE 64
for (i=0; i<64; i+=WRITE_SIZE)
{
port_write(port, &page_buffer[(unsigned int)(block*64)+i], WRITE_SIZE);
usleep(1250);
}
bzero(buffer, sizeof(buffer));
printf(".");
fflush(stdout);
length = port_readline(port, buffer, sizeof(buffer), 200);
if(memcmp(buffer, "OK", 2) == 0)
{
retry = 0;
}
else
{
block--;
if (retry++ >= 8)
{
error = -1;
break;
}
else
{
buffer[length] = 0;
printf("%s",buffer);
port_rts_clear(port);
usleep(300000);
port_rts_set(port);
bzero(buffer, sizeof(buffer));
length = port_readline(port, buffer, sizeof(buffer), 800);
if(memcmp(buffer, "CDI", 3) == 0)
{
printf("R");
}
}
}
}
else
{
error = -1;
break;
}
}
if (!error)
{
printf("w"); fflush(stdout);
bzero(buffer, sizeof(buffer));
length = port_readline(port, buffer, sizeof(buffer), 800);
if(memcmp(buffer, "WROK", 4) == 0)
{
error = 0;
}
else
{
printf("%c%c", buffer[0], buffer[1]);
error = -1;
}
}
if (!error) printf("OK\r");
return error;
}

View file

@ -0,0 +1,99 @@
/*
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
*/
#include <unistd.h>
#include <strings.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
int hexfile_parse(char *line, unsigned int *type, unsigned int *addr, unsigned char *buffer)
{
unsigned int row_len = 0;
unsigned int row_index = 7;
unsigned int i;
int tmp;
uint8_t cksum = 0;
int retval = 0;
retval = sscanf(line, ":%2x%4x%2x", &row_len, addr, type);
cksum += row_len;
cksum += *addr >> 8;
cksum += *addr & 0xFF;
cksum += *type;
i = 0;
if (retval == 3)
{
while(i < row_len)
{
if (sscanf(&line[row_index], "%2x", &tmp) == 1)
{
cksum += tmp;
buffer[i++] = (unsigned char) tmp;
row_index += 2;
}
else return -1;
}
if (sscanf(&line[row_index], "%2x", &tmp) == 1)
{
if ((cksum + (uint8_t) tmp) == 0) return row_len;
}
}
return -1;
}
int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes)
{
uint8_t cksum = 0;
uint8_t i = 0;
char tmp[8];
sprintf(line, ":%2.2X%4.4X%2.2X", bytes, address, type);
cksum -= bytes;
cksum -= address >> 8;
cksum -= address & 0xFF;
cksum -= type;
for (i=0; i<bytes; i++)
{
sprintf(tmp, "%2.2X", data[i]);
strcat(line, tmp);
cksum -= data[i];
}
sprintf(tmp, "%2.2X\r\n", cksum);
strcat(line, tmp);
return strlen(line);
}

View file

@ -0,0 +1,36 @@
/*
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
*/
#ifndef _IHEX_H
#define _IHEX_H
extern int hexfile_parse(char *line, unsigned char *type, unsigned int *addr, char *buffer);
extern int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes);
#endif /*_IHEX_H*/

View file

@ -0,0 +1,371 @@
/*
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
*/
#include <sys/poll.h>
#include "port.h"
int port_open(port_t **port, char *device)
{
port_t *new_port = (port_t *) malloc(sizeof(port_t));
char err_string[128];
*port = new_port;
new_port->device = 0;
new_port->handle = 0;
new_port->handle = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (new_port->handle <= 0)
{
strerror_r(errno, err_string, 128);
printf("Serial port open failed with error message: %s.\n", err_string);
return(-1);
}
else
{
tcgetattr(new_port->handle, &(new_port->old_params));
fcntl(new_port->handle, F_SETFL, FASYNC);
printf("Serial port %s opened succesfully.\n", device);
return(0);
}
}
int port_close(port_t *port)
{
if (!port)
return(-1);
if ((port->handle) > 0)
{
tcflush(port->handle, TCIFLUSH);
tcsetattr(port->handle,TCSANOW,&(port->old_params));
close(port->handle);
port->handle = 0;
}
if (port->device) free(port->device);
port->device = 0;
free(port);
return(1);
}
/** @todo port_write() function probably needs mutexes -mjs */
int port_write(port_t *port, unsigned char *buffer, size_t buflen)
{
int i=0;
if (!port) return -1;
/** @todo The write to serial port is at the moment done one octet at a time with 10ms interval between each write operation due to some minor problems in MCU interrupts. -mjs */
while(i < buflen)
{
write(port->handle, &(buffer[i]), 1);
tcflush(port->handle, TCIFLUSH);
i++;
}
/* write(port->handle, &(buffer[i]), buflen);*/
tcflush(port->handle, TCIFLUSH);
return(0);
}
int port_read(port_t *port, unsigned char *buffer, size_t buflen)
{
unsigned int l = 0;
l = read(port->handle, buffer, buflen);
return(l);
}
int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts)
{
int rate = B115200;
struct termios newtio;
if (!port) return -1;
switch (speed)
{
case 230400:
rate = B230400;
break;
case 0:
case 115200:
rate = B115200;
break;
case 57600:
rate = B57600;
break;
case 38400:
rate = B38400;
break;
case 19200:
rate = B19200;
break;
case 9600:
rate = B9600;
break;
default:
return -1;
}
bzero(&newtio, sizeof(newtio));
if (speed == 9600)
{
newtio.c_cflag |= CS8 | CSTOPB | CLOCAL | CREAD;
}
else
{
newtio.c_cflag |= CS8 | CLOCAL | CREAD;
}
if (rtscts)
{
newtio.c_cflag |= CRTSCTS;
}
newtio.c_iflag = IGNPAR;
cfsetispeed(&newtio, rate);
cfsetospeed(&newtio, rate);
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
#if 0
newtio.c_cflag = rate | CS8 | CLOCAL | CREAD | CSTOPB;
/* if (rts_cts) newtio.c_cflag |= CRTSCTS;*/
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
#endif
tcflush(port->handle, TCIFLUSH);
tcsetattr(port->handle,TCSANOW,&newtio);
return(0);
}
int port_dtr_set(port_t *port)
{
int port_state = TIOCM_DTR;
if (!port) return(-1);
/* error = ioctl(port->handle, TIOCMGET, &port_state);
port_state |= TIOCM_RTS;
ioctl(port->handle, TIOCMSET, &port_state);*/
ioctl(port->handle, TIOCMBIS, &port_state);
return 0;
}
int port_dtr_clear(port_t *port)
{
int port_state = TIOCM_DTR;
if (!port) return(-1);
ioctl(port->handle, TIOCMBIC, &port_state);
return 0;
}
int port_rts_set(port_t *port)
{
int port_state = TIOCM_RTS;
if (!port) return(-1);
ioctl(port->handle, TIOCMBIS, &port_state);
return 0;
}
int port_rts_clear(port_t *port)
{
int port_state = TIOCM_RTS;
if (!port) return(-1);
ioctl(port->handle, TIOCMBIC, &port_state);
return 0;
}
int port_get(port_t *port, unsigned char *buffer, int timeout)
{
struct pollfd pfds;
unsigned int nfds = 1;
int bytes = 0;
int rval;
pfds.fd = (int)(port->handle);
pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
rval = poll(&pfds, nfds, timeout);
if((rval & POLLIN) != POLLIN)
{
return(-1);
}
else
{
bytes = port_read(port, buffer, 1);
}
return bytes;
}
int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout)
{
int length = 0;
struct pollfd pfds;
unsigned int nfds = 1;
int bytes = 0;
int rval;
pfds.fd = (int)(port->handle);
pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
do
{
rval = poll(&pfds, nfds, timeout);
if((rval & POLLIN) != POLLIN)
{
return(length);
}
else
{
bytes = port_read(port, &(buffer[length]), 1);
if (buffer[length] == '\n')
{
buf_size = length;
}
length += bytes;
}
}while(length < buf_size);
buffer[length] = 0;
if(length != 0)
return length;
else
return(-1);
}
int port_write_echo(port_t *port, char *string)
{
int length = 0;
int retry = 0;
unsigned char byte;
while( (string[length]) && (retry < 100) )
{
port_write(port, (unsigned char *) &string[length], 1);
while (retry++ < 100)
{
if (port_read(port, &byte, 1) == 1)
{
/* printf("%c",byte);*/
if (byte == string[length])
{
retry = 0;
length++;
break;
}
else retry = 100;
}
else usleep(1000);
}
}
if ((string[strlen(string)-1] == '\r') && (retry < 100) )
{ /*wait for \n*/
retry = 0;
while (retry++ < 100)
{
if (port_read(port, &byte, 1) == 1)
{
/* printf("%c",byte);*/
break;
}
else usleep(1000);
}
}
if (retry >= 100) return 0;
else return length;
}
int port_write_8byte_no_echo(port_t *port, int dlen, char *string)
{
int length = 0;
int total_len;
int wrbytes = 4;
total_len = dlen;
/* printf("total: %d, length: %d, dlen: %d.\n", total_len, length, dlen); */
while(total_len > length)
{
if((total_len - length) >= wrbytes)
{
port_write(port, (unsigned char *)&string[length], wrbytes);
length += wrbytes;
}
else
{
port_write(port, (unsigned char *)&string[length], total_len - length);
length += total_len - length;
}
usleep(1250);
}
return(length);
}

Binary file not shown.

View file

@ -0,0 +1,94 @@
/*
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
*/
#ifndef _PORT_H
#define _PORT_H
#ifndef PLATFORM_WINDOWS
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>
#else
#include "windows.h"
#include <stdint.h>
#include "ftd2xx.h"
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef PLATFORM_WINDOWS
typedef struct
{
int handle;
char *device;
struct termios old_params;
}port_t;
extern int port_open(port_t **port, char *device);
#else
typedef struct port_t
{
FT_HANDLE handle;
int device;
HANDLE event_handle;
}port_t;
extern int port_open(port_t **port, int device);
#endif
extern int port_close(port_t *port);
extern int port_write(port_t *port, unsigned char *buffer, size_t buflen);
extern int port_read(port_t *port, unsigned char *buffer, size_t buflen);
extern int port_get(port_t *port, unsigned char *buffer, int timeout);
extern int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts);
extern int port_dtr_set(port_t *port);
extern int port_dtr_clear(port_t *port);
extern int port_rts_set(port_t *port);
extern int port_rts_clear(port_t *port);
extern int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout);
extern int port_write_echo(port_t *port, char *string);
extern int port_write_8byte_no_echo(port_t *port, int dlen, char *string);
#ifdef __cplusplus
}
#endif
#endif /* _PORT_H */

View file

@ -0,0 +1,440 @@
/*
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
*/
#include <unistd.h>
#include <getopt.h>
#include <strings.h>
#include "port.h"
#include "programmer.h"
#include <stdio.h>
extern int cdi_programmer(conf_opts_t *conf, char *filename);
void usage(char *prg_name)
{
printf("\nUsage: %s [-d device]\n", prg_name);
printf("General options:\n");
printf(" -V/--version Get programmer version\n");
printf(" -1/--d100 Use D100 board (default D200)\n");
printf("Operating modes:\n");
printf(" -b/--bios to get programmer BIOS version\n");
printf(" -P/--program [ihex file] Do a complete programming sequence (write and verify)\n");
printf(" -v/--verify [ihex file] Verify against ihex file\n");
printf(" -r/--read [ihex file] Read program code into ihex file\n");
printf(" -m/--mac Read device MAC address\n");
printf(" -Q/--write-mac [MAC address] Write device MAC address\n");
printf(" -e/--erase Erase flash (erases MAC address!)\n");
printf("Programming options:\n");
printf(" -l/--linear Force linear model for extended addresses (not SDCC file)\n");
printf(" -s/--sdcc Force SDCC model for extended addresses (SDCC file)\n");
printf("Defaults:\n");
#ifndef PLATFORM_WINDOWS
printf("device /dev/ttyUSB0\n");
#else
printf("device 0\n");
#endif
}
conf_opts_t conf_opts;
static int option_index = 0;
int do_exit = 0;
#define OPTIONS_STRING "d:ec1lsmVbP:v:r:Q:"
/* long option list */
static struct option long_options[] =
{
{"device", 1, NULL, 'd'},
{"psoc", 0, NULL, 'p'},
{"d100", 0, NULL, '1'},
{"erase", 0, NULL, 'e'},
{"mac", 0, NULL, 'm'},
{"linear", 0, NULL, 'l'},
{"sdcc", 0, NULL, 's'},
{"cdi", 0, NULL, 'c'},
{"version", 0, NULL, 'V'},
{"bios", 0, NULL, 'b'},
{"program", 1, NULL, 'P'},
{"verify", 1, NULL, 'v'},
{"read", 1, NULL, 'r'},
{"write-mac", 1, NULL, 'Q'},
{0, 0, 0, 0}
};
int parse_opts(int count, char* param[])
{
int opt;
int error=0;
conf_opts.target_type = CDI;
while ((opt = getopt_long(count, param, OPTIONS_STRING,
long_options, &option_index)) != -1)
{
switch(opt)
{
case 'V':
conf_opts.target_type = VERSION;
break;
case '1':
conf_opts.prg_type = 1;
break;
case 'c':
conf_opts.target_type = CDI;
break;
case 'd':
#ifdef PLATFORM_WINDOWS
if (sscanf(optarg, "%d", &conf_opts.device) != 1)
{
printf("Device ID must be a positive integer.\n");
conf_opts.action = ' ';
}
#else
printf("device:%s\n", optarg);
strcpy(conf_opts.device, optarg);
#endif
break;
case 'P':
printf("Programming mode.\n");
conf_opts.action = 'P';
strcpy(conf_opts.ihex_file, optarg);
break;
case 's':
if (conf_opts.page_mode == PAGE_UNDEFINED)
{
conf_opts.page_mode = PAGE_SDCC;
}
else
{
printf("Only one paging option allowed.\n");
error = -1;
}
break;
case 'l':
if (conf_opts.page_mode == PAGE_UNDEFINED)
{
conf_opts.page_mode = PAGE_LINEAR;
}
else
{
printf("Only one paging option allowed.\n");
error = -1;
}
break;
case 'e':
printf("Erase.\n");
conf_opts.action = 'e';
break;
case 'm':
printf("Get MAC.\n");
conf_opts.action = 'm';
break;
case 'b':
printf("Get BIOS version\n");
conf_opts.action = 'b';
break;
case 'Q':
printf("Write MAC.\n");
conf_opts.action = 'Q';
if (sscanf(optarg, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&conf_opts.write_mac[0], &conf_opts.write_mac[1],
&conf_opts.write_mac[2], &conf_opts.write_mac[3],
&conf_opts.write_mac[4], &conf_opts.write_mac[5],
&conf_opts.write_mac[6], &conf_opts.write_mac[7]) != 8)
{
printf("Invalid MAC.\n");
conf_opts.action = ' ';
}
break;
case 'v':
printf("Verify by comparing to ihex file:%s\n", optarg);
conf_opts.action = 'v';
strcpy(conf_opts.ihex_file, optarg);
break;
case 'r':
printf("Read program to ihex file:%s\n", optarg);
conf_opts.action = 'r';
strcpy(conf_opts.ihex_file, optarg);
break;
case '?':
printf("Duh\n");
error = -1;
break;
}
}
if (!error && (conf_opts.target_type == CDI) )
{
#ifdef PLATFORM_WINDOWS
printf("Setup: Device %d.\n", conf_opts.device);
#else
printf("Setup: Device %s.\n", conf_opts.device);
#endif
}
return error;
}
/*
int port_write_8byte_echo(port_t *port, char *string)
{
int length = 0;
int total_len;
int i, j;
struct pollfd pfds;
unsigned int nfds = 1;
int rval = 0;
int wrbytes = 2;
unsigned char byte8[wrbytes];
pfds.fd = (int)(port->handle);
pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
total_len = strlen(string);
while(total_len > length)
{
if(total_len - length >= wrbytes)
{
i=0;
port_write(port, (unsigned char *)&string[length], wrbytes);
if((rval = poll(&pfds, nfds, 100)) == 0)
{
printf("Timed out...\n");
return(-1);
}
else
{
while(i<wrbytes)
{
i += port_read(port, &byte8[i], wrbytes);
}
if(i != wrbytes || memcmp(byte8, &string[length], wrbytes) != 0)
{
printf("Got wrong length (%d) or wrong bytes back.\n", i);
for(j=0;j<wrbytes;j++)
{
printf("%.2x <-> %.2x\n", string[length+j], byte8[j]);
}
return(-1);
}
else
{
printf("8Bwok - ");
fflush(stdout);
length += wrbytes;
}
}
}
else
{
i=0;
port_write(port, (unsigned char *)&string[length], total_len - length);
if((rval = poll(&pfds, nfds, 100)) == 0)
{
printf("Timed out...\n");
return(-1);
}
else
{
while(i<(total_len-length))
{
i = port_read(port, &byte8[i], total_len - length);
}
if(i != total_len - length || memcmp(byte8, &string[length], total_len - length) != 0)
{
printf("Got wrong length or wrong bytes back.\n");
for(j=0;j<total_len - length;j++)
{
printf("%.2x <-> %.2x\n", string[length+j], byte8[j]);
}
return(-1);
}
else
{
printf("<8Bwok - \n");
fflush(stdout);
length += (total_len - length);
}
}
}
usleep(5000);
}
return(length);
}
*/
#ifdef PLATFORM_WINDOWS
int programmer_init(int device, port_t **port)
#else
int programmer_init(char *device, port_t **port)
#endif
{
int error = port_open(port, device);
uint8_t buffer[8];
buffer[0] = 0;
if (error >= 0)
{
if (conf_opts.prg_type == 1)
{
int retry = 0;
port_set_params(*port, 9600, 0);
// Activate programming...
port_dtr_clear(*port);
port_rts_clear(*port);
sleep(1);
printf("Select D100.\n");
port_rts_set(*port);
sleep(1);
buffer[0] = '\r';
while (retry++ < 3)
{
int length;
port_write_echo(*port, "q\r");
length = port_readline(*port, buffer, sizeof(buffer), 800);
if (length)
{
if (*buffer == '!')
{
printf("D100 found.\n");
return 0;
}
}
}
printf("No programmer found.\n");
return -1;
}
else
{
port_set_params(*port, 57600, 0);
// Activate programming...
port_dtr_clear(*port);
port_rts_clear(*port);
usleep(300000);
printf("Select D200.\n");
port_rts_set(*port);
usleep(200000);
port_set_params(*port, 57600, 1);
port_write(*port, (uint8_t *)"\r", 1);
usleep(100000);
if ((port_get(*port, buffer, 500) >= 1) && (buffer[0] == '!'))
{
printf("D200 found.\n");
return 0;
}
printf("No programmer found.\n");
return -1;
}
}
return error;
}
void programmer_close(port_t *port)
{
if (port)
{
port_rts_clear(port);
port_dtr_set(port);
sleep(1);
port_close(port);
printf("Port closed.\n");
}
}
int main(int argc, char *argv[])
{
int error = 0;
conf_opts.target_type = 0;
conf_opts.action = 0;
conf_opts.prg_type = 2;
#ifndef PLATFORM_WINDOWS
strncpy(conf_opts.device, "/dev/ttyUSB0", 12);
/* Install a new handler for SIGIO.
*
* According to man 7 signal this signal is by default ignored by most systems.
* It seems that pre FC7 this was true for Fedoras also. We have noticed that at least
* on some FC7 installations the default action has changed. We avoid abnormal program
* exits by defining the SIGIO as SIG_IGN (ignore). - mjs
*/
if(signal(SIGIO, SIG_IGN) == SIG_ERR)
{
printf("%s error: failed to install SIGIO handler. Exit.\n", argv[0]);
exit(EXIT_FAILURE);
}
#else
conf_opts.device = 0;
#endif
conf_opts.page_mode = PAGE_UNDEFINED;
if ( (argc <= 1) || (error = parse_opts(argc, argv)) )
{
usage(argv[0]);
if (error < 0) return error;
else return 0;
}
if(conf_opts.target_type == CDI)
{ /*CDI*/
error = cdi_programmer(&conf_opts, conf_opts.ihex_file);
}
else
{
printf("\nSensinode Nano series programmer "PROGRAMMER_VERSION "\n");
}
return error;
}

View file

@ -0,0 +1,62 @@
/*
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
*/
#define PROGRAMMER_VERSION "v1.3"
typedef enum
{
PAGE_SDCC,
PAGE_LINEAR,
PAGE_UNDEFINED
}page_mode_t;
typedef struct {
#ifdef PLATFORM_WINDOWS
int device;
#else
char device[128];
#endif
int target_type;
int prg_type;
int action;
char ihex_file[128];
unsigned char write_mac[8];
page_mode_t page_mode;
}conf_opts_t;
enum target { UNDEFINED, VERSION, CDI };
#ifdef PLATFORM_WINDOWS
extern int programmer_init(int device, port_t **port);
#else
extern int programmer_init(char *device, port_t **port);
#endif
extern void programmer_close(port_t *port);

View file

@ -0,0 +1,383 @@
/*
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
*/
#include "port.h"
#include <stdio.h>
int port_open(port_t **port, int device)
{
port_t *new_port = (port_t *) malloc(sizeof(port_t));
FT_STATUS status;
*port = new_port;
new_port->device = device;
new_port->handle = 0;
status = FT_Open(device, &(new_port->handle));
if (status != FT_OK)
{
new_port->handle = 0;
printf("Serial port open failed with error message: %d.\n", (int)status);
return(-1);
}
else
{
DWORD mask;
new_port->event_handle = CreateEvent(NULL, TRUE, FALSE, "SN_USB_UART_EVENTS");
if (new_port->event_handle == NULL)
{
printf("Event handle creation failed.\n");
FT_Close(new_port->handle);
new_port->handle = 0;
return(-1);
}
mask = FT_EVENT_RXCHAR | FT_EVENT_MODEM_STATUS;
status = FT_SetEventNotification(new_port->handle,mask,new_port->event_handle);
if (status != FT_OK)
{
printf("Setting event notification failed.\n");
}
FT_SetTimeouts(new_port->handle,400,0);
return(0);
}
}
int port_close(port_t *port)
{
if (!port)
return(-1);
if ((port->event_handle) != NULL)
{
CloseHandle(port->event_handle);
port->event_handle = NULL;
FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX);
FT_Close(port->handle);
port->handle = 0;
}
port->device = 0;
free(port);
return(1);
}
int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts)
{
FT_STATUS status;
if (!port) return -1;
status = FT_SetBaudRate (port->handle, speed);
if (status != FT_OK) return -1;
if (speed == 9600)
{
status = FT_SetDataCharacteristics(port->handle, FT_BITS_8, FT_STOP_BITS_2, FT_PARITY_NONE);
}
else
{
status = FT_SetDataCharacteristics(port->handle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
}
if (status != FT_OK) return -1;
if (rtscts)
{
status = FT_SetFlowControl(port->handle, FT_FLOW_RTS_CTS, 0, 0);
}
else
{
status = FT_SetFlowControl(port->handle, FT_FLOW_NONE, 0, 0);
}
if (status != FT_OK) return -1;
FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX);
return(0);
}
int port_dtr_set(port_t *port)
{
FT_STATUS status;
if (!port) return(-1);
status = FT_SetDtr(port->handle);
if (status != FT_OK)
{
printf("Control failed.\n");
return -1;
}
return 0;
}
int port_dtr_clear(port_t *port)
{
FT_STATUS status;
if (!port) return(-1);
status = FT_ClrDtr(port->handle);
if (status != FT_OK)
{
printf("Control failed.\n");
return -1;
}
return 0;
}
int port_rts_set(port_t *port)
{
FT_STATUS status;
if (!port) return(-1);
status = FT_SetRts(port->handle);
if (status != FT_OK)
{
printf("Control failed.\n");
return -1;
}
return 0;
}
int port_rts_clear(port_t *port)
{
FT_STATUS status;
if (!port) return(-1);
status = FT_ClrRts(port->handle);
if (status != FT_OK)
{
printf("Control failed.\n");
return -1;
}
return 0;
}
int port_write(port_t *port, unsigned char *buffer, size_t buflen)
{
FT_STATUS status;
DWORD bytes_out;
if (!port) return -1;
// FT_Purge(port->handle, FT_PURGE_RX);
status = FT_Write (port->handle, (LPVOID) buffer, (DWORD) buflen,&bytes_out);
if (status != FT_OK) return -1;
return 0;
}
int port_read(port_t *port, unsigned char *buffer, size_t buflen)
{
DWORD l = 0;
FT_STATUS status;
status = FT_Read(port->handle, buffer, buflen, &l);
return((int) l);
}
int port_get(port_t *port, unsigned char *buffer, int timeout)
{
DWORD bytes = 0;
FT_STATUS status;
FT_SetTimeouts(port->handle, timeout, 0);
status = FT_Read(port->handle, buffer, 1, &bytes);
if (status != FT_OK)
{
return(-1);
}
return bytes;
}
int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout)
{
int length = 0;
DWORD bytes = 0;
FT_STATUS status;
FT_SetTimeouts(port->handle, timeout, 0);
do
{
status = FT_Read(port->handle, &buffer[length], 1, &bytes);
length += bytes;
if ((status != FT_OK) || (bytes == 0))
{
return(length);
}
else
{
if (buffer[length-1] == '\n')
{
buf_size = length;
}
}
}while(length < buf_size);
buffer[length] = 0;
if(length != 0)
return length;
else
return(-1);
}
int port_write_echo(port_t *port, char *string)
{
int length = 0;
int retry = 0;
unsigned char byte;
DWORD bytes_out;
FT_STATUS status;
FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX);
while( (string[length]) && (retry < 100) )
{
retry = 0;
while (retry++ < 100)
{
status = FT_Write (port->handle, (LPVOID) &string[length], (DWORD) 1,&bytes_out);
if (status != FT_OK) return -1;
if (port_get(port, &byte, 1000) == 1)
{
/* printf("%c",byte);*/
if (byte == string[length])
{
retry = 0;
length++;
break;
}
else retry = 100;
}
else usleep(500);
}
}
if ((string[strlen(string)-1] == '\r') && (retry < 100) )
{ /*wait for \n*/
retry = 0;
while (retry++ < 100)
{
if (port_get(port, &byte, 1000) == 1)
{
/* printf("%c",byte);*/
break;
}
else usleep(500);
}
}
if (retry >= 100) return 0;
else return length;
}
#if 0
int port_write_echo(port_t *port, char *string)
{
int length = 0;
int retry = 0;
unsigned char byte;
while( (string[length]) && (retry < 100) )
{
port_write(port, (unsigned char *) &string[length], 1);
while (retry++ < 100)
{
if (port_read(port, &byte, 1) == 1)
{
/* printf("%c",byte);*/
if (byte == string[length])
{
retry = 0;
length++;
break;
}
else retry = 100;
}
else usleep(1000);
}
}
if ((string[strlen(string)-1] == '\r') && (retry < 100) )
{ /*wait for \n*/
retry = 0;
while (retry++ < 100)
{
if (port_read(port, &byte, 1) == 1)
{
/* printf("%c",byte);*/
break;
}
else usleep(1000);
}
}
if (retry >= 100) return 0;
else return length;
}
int port_write_8byte_no_echo(port_t *port, int dlen, char *string)
{
int length = 0;
int total_len;
int wrbytes = 4;
total_len = dlen;
/* printf("total: %d, length: %d, dlen: %d.\n", total_len, length, dlen); */
while(total_len > length)
{
if((total_len - length) >= wrbytes)
{
port_write(port, (unsigned char *)&string[length], wrbytes);
length += wrbytes;
}
else
{
port_write(port, (unsigned char *)&string[length], total_len - length);
length += total_len - length;
}
usleep(1250);
}
return(length);
}
#endif

View file

@ -0,0 +1,32 @@
EXE_MAKE=$(notdir $(shell which "make.exe"))
ifeq "$(EXE_MAKE)" "make.exe"
PLATFORM=windows
else
PLATFORM=linux
endif
include Rules.make
APP = nano_usb_programmer$(SUFFIX)
OBJS = $(SOURCES:.c=.o)
all: $(APP)
$(APP): $(OBJS) Makefile $(SOURCES)
$(CC) -o $(APP) $(CFLAGS) $(OBJS) $(LDFLAGS)
platform-test:
@echo $(PLATFORM)
clean:
rm -f *.o ; rm -f $(APP)
.c.o:
$(CC) -c -o $(<:.c=.o) $(CFLAGS) $<
ftd2xx.def:
echo EXPORTS > ftd2xx.def
nm ftd2xx.lib | grep ' T _' | sed 's/.* T _//' >> ftd2xx.def
ftd2xx.dll.a: ftd2xx.def
dlltool --def ftd2xx.def --dllname ftd2xx.dll --output-lib ftd2xx.dll.a

View file

@ -0,0 +1,56 @@
Nano USB Programmer
An USB programmer for the Sensinode NanoRouter N600.
Copyright 2007-2008 Sensinode Ltd.
1a - Installation (Linux)
The installation is quite simple but requires the user to obtain the FTDI
development library. The installation also requires root privileges in
some phases (the ldconfig command to be more specific). Running the
Nano_USB_Programmer executable might also require root privileges.
-unpack the Nano_USB_Programmer-v[xxx].zip to a directory
-get the FTDI development library from
http://www.ftdichip.com/Drivers/D2XX/Linux/libftd2xx0.4.13.tar.gz
-unpack the ftdi archive
-copy the library static_lib/libftd2xx.a.[version] into /usr/lib
-copy the library libftd2xx.so.[version] into /usr/lib
-make a symbolic link to the library, for example:
ln -s /usr/lib/libftd2xx.so.0.4.13 /usr/lib/libftd2xx.so
-run ldconfig
-copy the header files (*.h) into the nano_usb_programmer/ftdi_linux/ directory
-go to the programmer directory and run make
1b - Installation (Windows/Cygwin)
Installation procedure:
-The FTDI library can be downloaded at:
http://www.ftdichip.com/Drivers/CDM/CDM%202.02.04%20WHQL%20Certified.zip
-Copy header files (ftd2xx.h), ftd2xx.lib and ftd2xx.dll to nano_usb_programmer/ftdi_win32
-Copy the ftd2xx.dll to your windows system32 directory
2 - Usage
Usage info for the Nano_USB_Programmer is available with command
./nano_usb_programmer --help. Note that use might require root/administrator privileges
depending on system configuration.
3 - Known problems (Linux)
There's one known problem at the moment. The N600 must be unplugged and
plugged in again after it has been programmed or the MAC address has been
read from it before it can respond to the programmer again. The reason for
this is the FTDI library is not perfectly integrated with the Linux
serial driver.
4 - README Version
v1.0 2007-11-14 Mikko Saarnivala Initial release
v1.1 2007-11-15 Mikko Saarnivala A small error in the instructions fixed
v1.2 2007-11-19 Mikko Saarnivala Added the FTDI CBUS2 value handling
v1.3 2008-01-31 Martti Huttunen Multi-platform build and updated instructions

View file

@ -0,0 +1,14 @@
ifeq "$(PLATFORM)" "linux"
CC=gcc
CFLAGS= -I. -I./ftdi_linux -L. -L./ftdi_linux -DPLATFORM_LINUX
LDFLAGS= -lftd2xx -Wl,-rpath /usr/local/lib
SOURCES=main.c prog.c cdi.c ihex.c
SUFFIX=
else
CC=gcc
CFLAGS=-I. -I./ftdi_win32 -L. -L./ftdi_win32 -DPLATFORM_WINDOWS
CFLAGS+= -mwin32
LDFLAGS=ftdi_win32/ftd2xx.lib -lkernel32
SOURCES=main.c prog.c cdi.c ihex.c
SUFFIX=.exe
endif

View file

@ -0,0 +1,506 @@
/*
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
*/
#include <stdio.h>
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#endif
#include "cdi.h"
/*read none/8*/
#define CDI_CHIP_ERASE 0x10
#define CDI_WR_CONFIG 0x19
#define CDI_SET_HW_BRKPNT 0x3B
/*read 8*/
#define CDI_RD_CONFIG 0x24
#define CDI_READ_STATUS 0x34
#define CDI_HALT 0x44
#define CDI_RESUME 0x4C
#define CDI_STEP_INSTR 0x5C
/*variable len, add data length to command byte*/
#define CDI_DBGINSTR 0x54
#define CDI_STEP_REPLACE 0x64
/*response = 16 bits*/
#define CDI_GET_PC 0x28
#define CDI_GET_CHIP_ID 0x68
/* internals */
void cdi_command_push(uint8_t *byte, uint8_t bytes_out, uint16_t *retval, uint8_t return_bits);
void cdi_flash_bank(uint8_t bank, uint8_t unif_mode);
void cdi_dptr_write(uint16_t value);
uint8_t cdi_reg_read(uint8_t reg_addr);
void cdi_reg_write(uint8_t reg_addr, uint8_t value);
void cdi_xdata_write(uint8_t value);
uint8_t cdi_xdata_read(void);
void cdi_flash_init(void);
void cdi_flash_write_page(void);
uint32_t cdi_addr = 0;
#define pause_ms(x) usleep(x*1000)
#define pause_us(x) usleep(x)
void cdi_command_push(uint8_t *byte, uint8_t bytes_out, uint16_t *retval, uint8_t return_bits)
{
uint8_t i, val;
for (i=0; i<bytes_out; i++)
{
prog_write(*byte);
byte++;
}
return_bits >>= 3;
for (i=0; i<return_bits; i++)
{
*retval <<= 8;
prog_read(&val);
*retval += val;
}
}
void cdi_reg_write(uint8_t reg_addr, uint8_t value)
{
uint8_t out[4];
uint16_t retval;
out[0] = CDI_DBGINSTR + 3; /*command length 3 bytes*/
out[1] = 0x75; /*mov sfr, #immediate*/
out[2] = reg_addr; /*sfr = reg_addr*/
out[3] = value; /*immediate*/
cdi_command_push(out, 4, &retval, 8);
}
void cdi_xdata_write(uint8_t value)
{
uint8_t out[3];
uint16_t retval;
out[0] = CDI_DBGINSTR + 2; /*command length 3 bytes*/
out[1] = 0x74; /*mov a, #immediate*/
out[2] = value; /*immediate*/
cdi_command_push(out, 3, &retval, 8);
out[0] = CDI_DBGINSTR + 1; /*command length 3 bytes*/
out[1] = 0xF0; /*movx @dptr, a*/
cdi_command_push(out, 2, &retval, 8);
out[0] = CDI_DBGINSTR + 1; /*command length 1 byte*/
out[1] = 0xA3; /*inc DPTR*/
cdi_command_push(out, 2, &retval, 8);
}
uint8_t cdi_xdata_read(void)
{
uint8_t out[2];
uint16_t retval;
uint8_t retval8;
out[0] = CDI_DBGINSTR + 1; /*command length 3 bytes*/
out[1] = 0xE0; /*movx a, @dptr*/
cdi_command_push(out, 2, &retval, 8);
retval8 = retval;
out[0] = CDI_DBGINSTR + 1; /*command length 1 byte*/
out[1] = 0xA3; /*inc DPTR*/
cdi_command_push(out, 2, &retval, 8);
return retval8;
}
void cdi_dptr_write(uint16_t value)
{
uint8_t out[4];
uint16_t retval;
/*set DPTR to address*/
out[0] = CDI_DBGINSTR + 3; /*command length 3 bytes*/
out[1] = 0x90; /*mov DPTR, #immediate16*/
out[2] = (value >> 8); /*immediateh*/
out[3] = value; /*immediatel*/
cdi_command_push(out, 4, &retval, 8);
}
uint8_t cdi_reg_read(uint8_t reg_addr)
{
uint8_t out[3];
uint16_t retval;
out[0] = CDI_DBGINSTR + 2; /*command length 2 bytes*/
out[1] = 0xE5; /*mov a, sfr*/
out[2] = reg_addr; /*sfr = reg_addr*/
cdi_command_push(out, 3, &retval, 8);
return (uint8_t) retval;
}
void cdi_flash_bank(uint8_t bank, uint8_t unif_mode)
{
uint8_t out;
out = (bank << 4) + 1;
out &= 0x31;
if (unif_mode) out |= 0x40; /*set unified memory model*/
cdi_reg_write(0xC7, out);
}
void cdi_flash_read(uint8_t *ptr, uint16_t bytes)
{
uint16_t i;
uint8_t out[4];
uint16_t retval;
cdi_flash_bank((cdi_addr >> 15), 0);
cdi_dptr_write(cdi_addr | 0x8000);
for (i=0; i<bytes; i++)
{
out[0] = CDI_DBGINSTR + 1; /*command length 1 byte*/
out[1] = 0xE4; /*clr a*/
cdi_command_push(out, 2, &retval, 8);
out[0] = CDI_DBGINSTR + 1; /*command length 1 byte*/
out[1] = 0x93; /*movc a, @A+DPTR*/
cdi_command_push(out, 2, &retval, 8);
*ptr++ = retval;
out[0] = CDI_DBGINSTR + 1; /*command length 1 byte*/
out[1] = 0xA3; /*inc DPTR*/
cdi_command_push(out, 2, &retval, 8);
}
cdi_addr += bytes;
}
const uint8_t cdi_ram_code[] =
{
0x7E, 0x00, /*mov r6, #0*/
0x7D, 0x04, /*mov r5, #4*/
/*C0:*/
0xE5, 0xAE, /*MOV A,_FCTL*/
0x20, 0xE7, 0xFB, /*JB ACC.7,C0*/
0x75, 0xAE, 0x02, /*mov _FCTL,#0x02*/
/*C1:*/
0xE0, /*movx a, @DPTR*/
0xF5, 0xAF, /*MOV _FWDATA, a*/
0xA3, /*inc DPTR*/
0xE0, /*movx a, @DPTR*/
0xF5, 0xAF, /*MOV _FWDATA, a*/
0xA3, /*inc DPTR*/
0xE0, /*movx a, @DPTR*/
0xF5, 0xAF, /*MOV _FWDATA, a*/
0xA3, /*inc DPTR*/
0xE0, /*movx a, @DPTR*/
0xF5, 0xAF, /*MOV _FWDATA, a*/
0xA3, /*inc DPTR*/
/*C2:*/
0xE5, 0xAE, /*MOV A,_FCTL*/
0x20, 0xE6, 0xFB, /*JB ACC.6,C2*/
0x1E, /*dec r6*/
0xDE, 0xE8, /*djnz r6,C1*/
0xDD, 0xE6, /*djnz r5,C1*/
/*C3:*/
0xE5, 0xAE, /*MOV A,_FCTL*/
0x20, 0xE7, 0xFB, /*JB ACC.7,C3*/
0x00, /*nop*/
0x00, /*nop*/
/*C4:*/
0x80, 0xFE /*sjmp C4*/
};
void cdi_flash_init(void)
{
uint8_t i;
/*set clock*/
cdi_reg_write(0xC6, 0xC9); /*sfr = CLKCON*/
/*set timing*/
cdi_reg_write(0xAB, 0x15); /*sfr = FWT*/
/*copy code to ram*/
cdi_dptr_write(0xE000);
for (i=0; i<sizeof(cdi_ram_code); i++)
{
cdi_xdata_write(cdi_ram_code[i]);
}
}
void cdi_flash_write_page(void)
{
uint16_t retval;
uint8_t out[4];
/*set unified memory model*/
cdi_flash_bank(0, 1);
/*set FADDR to page start*/
cdi_reg_write(0xAD, (cdi_addr >> 10) & 0x7F); /*sfr = FADDRH*/
cdi_reg_write(0xAC, (cdi_addr >> 2)); /*sfr = FADDRL*/
/*erase page*/
cdi_reg_write(0xAE, 0x01);
pause_ms(40);
/*set program counter*/
out[0] = CDI_DBGINSTR + 3; /*command length 3 bytes*/
out[1] = 0x02; /*ljmp immediate16*/
out[2] = 0xE0; /*immediateh*/
out[3] = 0x00; /*immediatel*/
cdi_command_push(out, 4, &retval, 8);
/*set breakpoint*/
out[0] = CDI_SET_HW_BRKPNT; /*command length 3 bytes*/
out[1] = 0x04;
out[2] = 0xE0; /*immediateh*/
out[3] = sizeof(cdi_ram_code)-2; /*immediatel*/
cdi_command_push(out, 4, &retval, 0);
cdi_dptr_write(0xE800); /*data area, set your page data here*/
/*execute*/
out[0] = CDI_RESUME; /*command length 3 bytes*/
cdi_command_push(out, 1, &retval, 8);
pause_ms(30);
out[3]= 0;
do
{
pause_ms(20);
out[0] = CDI_READ_STATUS;
cdi_command_push(out, 1, &retval, 8);
printf("-");
fflush(stdout);
}while( ((retval & 0x20) == 0) && (out[3]++ < 200) );
}
int cdi_flash_write(uint8_t *ptr, uint16_t length)
{
uint16_t i, retval;
uint8_t out[3];
if (length > 2048) return -1;
cdi_addr &= 0x1F800; /*make sure address is on page boundary*/
printf("0x%6.6X: ", cdi_addr);
fflush(stdout);
cdi_dptr_write(0xE800); /*our page data buffer is here*/
for (i=0; i< length; i++)
{
cdi_xdata_write(*ptr++);
if ((i & 0x3F) == 0)
{
printf(".");
}
if ((i & 0x0F) == 0x00)
{
printf("\bo");
}
if ((i & 0x0F) == 0x08)
{
printf("\b.");
}
fflush(stdout);
}
while(i<2048)
{
cdi_xdata_write(0xFF);
if ((i & 0x3F) == 0)
{
printf(".");
}
if ((i & 0x0F) == 0x00)
{
printf("\bo");
}
if ((i & 0x0F) == 0x08)
{
printf("\b.");
}
fflush(stdout);
i++;
}
out[0] = CDI_HALT;
cdi_command_push(out, 1, &retval, 8);
out[0] = CDI_READ_STATUS;
retval = 0;
cdi_command_push(out, 1, &retval, 8);
if ((retval & 0xFF) == 0xB2)
{
/*restore config*/
out[0] = CDI_WR_CONFIG; /*command length 3 bytes*/
out[1] = 0x0E; /*write flash area*/
cdi_command_push(out, 2, &retval, 0);
/*set flash timings and copy code to ram*/
cdi_flash_init();
/*write page*/
cdi_flash_write_page();
cdi_addr += 2048; /*increment page address*/
pause_ms(10);
}
else
{
return -1;
}
return 0;
}
int cdi_flash_write_mac(uint8_t *ptr)
{
uint16_t i, retval;
uint8_t out[3];
cdi_addr = 0x1F800; /*last page*/
printf("0x%6.6X", cdi_addr);
fflush(stdout);
cdi_dptr_write(0xEFF8); /*our page data buffer is here*/
for (i=0; i<8; i++)
{
cdi_xdata_write(*ptr++);
if ((i & 0x0F) == 0)
{
printf(".");
fflush(stdout);
}
}
out[0] = CDI_HALT;
cdi_command_push(out, 1, &retval, 8);
out[0] = CDI_READ_STATUS;
retval = 0;
cdi_command_push(out, 1, &retval, 8);
if ((retval & 0xFF) == 0xB2)
{
/*restore config*/
out[0] = CDI_WR_CONFIG; /*command length 3 bytes*/
out[1] = 0x0E; /*write flash area*/
cdi_command_push(out, 2, &retval, 0);
/*set flash timings and copy code to ram*/
cdi_flash_init();
/*write page*/
cdi_flash_write_page();
cdi_addr += 2048; /*increment page address*/
pause_ms(10);
}
else
{
return -1;
}
return 0;
}
int cdi_start(uint16_t *chip_id)
{
uint8_t out[3];
uint16_t retval;
prog_start(); /*do the CDI startup sequence*/
out[0] = CDI_READ_STATUS;
cdi_command_push(out, 1, &retval, 8);
printf("Status: %2.2X.\n", retval & 0xFF);
out[0] = CDI_GET_CHIP_ID;
cdi_command_push(out, 1, &retval, 16);
*chip_id = retval;
out[0] = CDI_HALT;
cdi_command_push(out, 1, &retval, 8);
pause_ms(100);
out[0] = CDI_WR_CONFIG; /*command length 3 bytes*/
out[1] = 0x0E; /*write flash area*/
cdi_command_push(out, 2, &retval, 0);
pause_ms(10);
cdi_reg_write(0xC6, 0xC9); /*sfr = CLKCON*/
pause_ms(10);
cdi_reg_write(0xAB, 0x15); /*sfr = FWT*/
cdi_addr = 0;
return 0;
}
int cdi_erase(void)
{
uint8_t out[3];
uint16_t retval;
uint8_t i;
out[0] = CDI_WR_CONFIG;
out[1] = 0x0E;
cdi_command_push(out, 2, &retval, 0);
out[0] = CDI_CHIP_ERASE;
cdi_command_push(out, 1, &retval, 0);
retval = 0;
i = 0;
do
{
pause_ms(30);
out[0] = CDI_READ_STATUS;
cdi_command_push(out, 1, &retval, 8);
}while( ((retval & 0x84) != 0x80) && (i++ < 100) );
cdi_addr = 0;
if (i >= 100)
{
return -1;
}
return 0;
}
void cdi_set_address(uint32_t address)
{
cdi_addr = address;
}

View file

@ -0,0 +1,44 @@
/*
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
*/
#ifndef _CDI_H
#define _CDI_H
#include "prog.h"
/* export these */
extern int cdi_start(uint16_t *chip_id);
extern int cdi_erase(void);
extern void cdi_set_address(uint32_t address);
extern void cdi_flash_read(uint8_t *ptr, uint16_t bytes);
extern int cdi_flash_write(uint8_t *ptr, uint16_t length);
#endif

View file

@ -0,0 +1,116 @@
/*
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
*/
#ifndef __WINDOWS_TYPES__
#define __WINDOWS_TYPES__
#define MAX_NUM_DEVICES 50
#include <sys/time.h>
typedef unsigned long DWORD;
typedef unsigned long ULONG;
typedef unsigned short USHORT;
typedef short SHORT;
typedef unsigned char UCHAR;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef unsigned char *LPBYTE;
typedef int BOOL;
typedef char BOOLEAN;
typedef char CHAR;
typedef int *LPBOOL;
typedef unsigned char *PUCHAR;
typedef const char *LPCSTR;
typedef char *PCHAR;
typedef void *PVOID;
typedef void *HANDLE;
typedef long LONG;
typedef int INT;
typedef unsigned int UINT;
typedef char *LPSTR;
typedef char *LPTSTR;
typedef DWORD *LPDWORD;
typedef WORD *LPWORD;
typedef ULONG *PULONG;
typedef PVOID LPVOID;
typedef void VOID;
typedef unsigned long long int ULONGLONG;
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES;
typedef struct timeval SYSTEMTIME;
typedef struct timeval FILETIME;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
//
// Modem Status Flags
//
#define MS_CTS_ON ((DWORD)0x0010)
#define MS_DSR_ON ((DWORD)0x0020)
#define MS_RING_ON ((DWORD)0x0040)
#define MS_RLSD_ON ((DWORD)0x0080)
//
// Error Flags
//
#define CE_RXOVER 0x0001 // Receive Queue overflow
#define CE_OVERRUN 0x0002 // Receive Overrun Error
#define CE_RXPARITY 0x0004 // Receive Parity Error
#define CE_FRAME 0x0008 // Receive Framing error
#define CE_BREAK 0x0010 // Break Detected
#define CE_TXFULL 0x0100 // TX Queue is full
#define CE_PTO 0x0200 // LPTx Timeout
#define CE_IOE 0x0400 // LPTx I/O Error
#define CE_DNS 0x0800 // LPTx Device not selected
#define CE_OOP 0x1000 // LPTx Out-Of-Paper
#define CE_MODE 0x8000 // Requested mode unsupported
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE 0xFFFFFFFF
#endif
#endif

View file

@ -0,0 +1,975 @@
/*
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
*/
/*++
Copyright (c) 2001-2006 Future Technology Devices International Ltd.
Module Name:
ftd2xx.h
Abstract:
Native USB interface for FTDI FT8U232/245/2232C
FTD2XX library definitions
Environment:
kernel & user mode
Revision History:
13/03/01 awm Created.
13/01/03 awm Added device information support.
19/03/03 awm Added FT_W32_CancelIo.
12/06/03 awm Added FT_StopInTask and FT_RestartInTask.
18/09/03 awm Added FT_SetResetPipeRetryCount.
10/10/03 awm Added FT_ResetPort.
/03/04 st modified for linux users
12/10/04 st added FT_SetVIDPID
--*/
#ifndef FTD2XX_H
#define FTD2XX_H
#ifndef _WINDOWS
#include <pthread.h>
#define WINAPI
#endif
// The following ifdef block is the standard way of creating macros
// which make exporting from a DLL simpler. All files within this DLL
// are compiled with the FTD2XX_EXPORTS symbol defined on the command line.
// This symbol should not be defined on any project that uses this DLL.
// This way any other project whose source files include this file see
// FTD2XX_API functions as being imported from a DLL, whereas this DLL
// sees symbols defined with this macro as being exported.
#ifdef FTD2XX_EXPORTS
#define FTD2XX_API __declspec(dllexport)
#else
#define FTD2XX_API __declspec(dllimport)
#endif
#ifndef _WINDOWS
#include "WinTypes.h"
#ifdef FTD2XX_API
#undef FTD2XX_API
#define FTD2XX_API
#endif
#endif
typedef struct _EVENT_HANDLE{
pthread_cond_t eCondVar;
pthread_mutex_t eMutex;
int iVar;
} EVENT_HANDLE;
typedef DWORD *FT_HANDLE;
typedef ULONG FT_STATUS;
//
// Device status
//
enum {
FT_OK,
FT_INVALID_HANDLE,
FT_DEVICE_NOT_FOUND,
FT_DEVICE_NOT_OPENED,
FT_IO_ERROR,
FT_INSUFFICIENT_RESOURCES,
FT_INVALID_PARAMETER,
FT_INVALID_BAUD_RATE, //7
FT_DEVICE_NOT_OPENED_FOR_ERASE,
FT_DEVICE_NOT_OPENED_FOR_WRITE,
FT_FAILED_TO_WRITE_DEVICE,
FT_EEPROM_READ_FAILED,
FT_EEPROM_WRITE_FAILED,
FT_EEPROM_ERASE_FAILED,
FT_EEPROM_NOT_PRESENT,
FT_EEPROM_NOT_PROGRAMMED,
FT_INVALID_ARGS,
FT_NOT_SUPPORTED,
FT_OTHER_ERROR
};
#define FT_SUCCESS(status) ((status) == FT_OK)
//
// FT_OpenEx Flags
//
#define FT_OPEN_BY_SERIAL_NUMBER 1
#define FT_OPEN_BY_DESCRIPTION 2
//
// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags
//
#define FT_LIST_NUMBER_ONLY 0x80000000
#define FT_LIST_BY_INDEX 0x40000000
#define FT_LIST_ALL 0x20000000
#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL)
//
// Baud Rates
//
#define FT_BAUD_300 300
#define FT_BAUD_600 600
#define FT_BAUD_1200 1200
#define FT_BAUD_2400 2400
#define FT_BAUD_4800 4800
#define FT_BAUD_9600 9600
#define FT_BAUD_14400 14400
#define FT_BAUD_19200 19200
#define FT_BAUD_38400 38400
#define FT_BAUD_57600 57600
#define FT_BAUD_115200 115200
#define FT_BAUD_230400 230400
#define FT_BAUD_460800 460800
#define FT_BAUD_921600 921600
//
// Word Lengths
//
#define FT_BITS_8 (UCHAR) 8
#define FT_BITS_7 (UCHAR) 7
#define FT_BITS_6 (UCHAR) 6
#define FT_BITS_5 (UCHAR) 5
//
// Stop Bits
//
#define FT_STOP_BITS_1 (UCHAR) 0
#define FT_STOP_BITS_1_5 (UCHAR) 1
#define FT_STOP_BITS_2 (UCHAR) 2
//
// Parity
//
#define FT_PARITY_NONE (UCHAR) 0
#define FT_PARITY_ODD (UCHAR) 1
#define FT_PARITY_EVEN (UCHAR) 2
#define FT_PARITY_MARK (UCHAR) 3
#define FT_PARITY_SPACE (UCHAR) 4
//
// Flow Control
//
#define FT_FLOW_NONE 0x0000
#define FT_FLOW_RTS_CTS 0x0100
#define FT_FLOW_DTR_DSR 0x0200
#define FT_FLOW_XON_XOFF 0x0400
//
// Purge rx and tx buffers
//
#define FT_PURGE_RX 1
#define FT_PURGE_TX 2
//
// Events
//
typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD);
#define FT_EVENT_RXCHAR 1
#define FT_EVENT_MODEM_STATUS 2
//
// Timeouts
//
#define FT_DEFAULT_RX_TIMEOUT 300
#define FT_DEFAULT_TX_TIMEOUT 300
//
// Device types
//
typedef ULONG FT_DEVICE;
enum {
FT_DEVICE_BM,
FT_DEVICE_AM,
FT_DEVICE_100AX,
FT_DEVICE_UNKNOWN,
FT_DEVICE_2232C,
FT_DEVICE_232R
};
#ifdef __cplusplus
extern "C" {
#endif
FTD2XX_API
FT_STATUS WINAPI FT_Open(
int deviceNumber,
FT_HANDLE *pHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_OpenEx(
PVOID pArg1,
DWORD Flags,
FT_HANDLE *pHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ListDevices(
PVOID pArg1,
PVOID pArg2,
DWORD Flags
);
FTD2XX_API
FT_STATUS FT_SetVIDPID(
DWORD dwVID,
DWORD dwPID
);
FTD2XX_API
FT_STATUS FT_GetVIDPID(
DWORD * pdwVID,
DWORD * pdwPID
);
FTD2XX_API
FT_STATUS WINAPI FT_Close(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_Read(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesReturned
);
FTD2XX_API
FT_STATUS WINAPI FT_Write(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesWritten
);
FTD2XX_API
FT_STATUS WINAPI FT_IoCtl( // Linux, OS X: Not supported
FT_HANDLE ftHandle,
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBaudRate(
FT_HANDLE ftHandle,
ULONG BaudRate
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDivisor(
FT_HANDLE ftHandle,
USHORT Divisor
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDataCharacteristics(
FT_HANDLE ftHandle,
UCHAR WordLength,
UCHAR StopBits,
UCHAR Parity
);
FTD2XX_API
FT_STATUS WINAPI FT_SetFlowControl(
FT_HANDLE ftHandle,
USHORT FlowControl,
UCHAR XonChar,
UCHAR XoffChar
);
FTD2XX_API
FT_STATUS WINAPI FT_ResetDevice(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDtr(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ClrDtr(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetRts(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ClrRts(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_GetModemStatus(
FT_HANDLE ftHandle,
ULONG *pModemStatus
);
FTD2XX_API
FT_STATUS WINAPI FT_SetChars(
FT_HANDLE ftHandle,
UCHAR EventChar,
UCHAR EventCharEnabled,
UCHAR ErrorChar,
UCHAR ErrorCharEnabled
);
FTD2XX_API
FT_STATUS WINAPI FT_Purge(
FT_HANDLE ftHandle,
ULONG Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_SetTimeouts(
FT_HANDLE ftHandle,
ULONG ReadTimeout,
ULONG WriteTimeout
);
FTD2XX_API
FT_STATUS WINAPI FT_GetQueueStatus(
FT_HANDLE ftHandle,
DWORD *dwRxBytes
);
FTD2XX_API
FT_STATUS WINAPI FT_SetEventNotification(
FT_HANDLE ftHandle,
DWORD Mask,
PVOID Param
);
FTD2XX_API
FT_STATUS WINAPI FT_GetStatus(
FT_HANDLE ftHandle,
DWORD *dwRxBytes,
DWORD *dwTxBytes,
DWORD *dwEventDWord
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBreakOn(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBreakOff(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetWaitMask( // Linux, OS X: Not supported
FT_HANDLE ftHandle,
DWORD Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_WaitOnMask( // Linux, OS X: Not supported
FT_HANDLE ftHandle,
DWORD *Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_GetEventStatus(
FT_HANDLE ftHandle,
DWORD *dwEventDWord
);
FTD2XX_API
FT_STATUS WINAPI FT_ReadEE(
FT_HANDLE ftHandle,
DWORD dwWordOffset,
LPWORD lpwValue
);
FTD2XX_API
FT_STATUS WINAPI FT_WriteEE(
FT_HANDLE ftHandle,
DWORD dwWordOffset,
WORD wValue
);
FTD2XX_API
FT_STATUS WINAPI FT_EraseEE(
FT_HANDLE ftHandle
);
//
// structure to hold program data for FT_Program function
//
typedef struct ft_program_data {
DWORD Signature1; // Header - must be 0x00000000
DWORD Signature2; // Header - must be 0xffffffff
DWORD Version; // Header - FT_PROGRAM_DATA version
// 0 = original
// 1 = FT2232C extensions
// 2 = FT232R extensions
WORD VendorId; // 0x0403
WORD ProductId; // 0x6001
char *Manufacturer; // "FTDI"
char *ManufacturerId; // "FT"
char *Description; // "USB HS Serial Converter"
char *SerialNumber; // "FT000001" if fixed, or NULL
WORD MaxPower; // 0 < MaxPower <= 500
WORD PnP; // 0 = disabled, 1 = enabled
WORD SelfPowered; // 0 = bus powered, 1 = self powered
WORD RemoteWakeup; // 0 = not capable, 1 = capable
//
// Rev4 extensions
//
UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise
UCHAR IsoIn; // non-zero if in endpoint is isochronous
UCHAR IsoOut; // non-zero if out endpoint is isochronous
UCHAR PullDownEnable; // non-zero if pull down enabled
UCHAR SerNumEnable; // non-zero if serial number to be used
UCHAR USBVersionEnable; // non-zero if chip uses USBVersion
WORD USBVersion; // BCD (0x0200 => USB2)
//
// FT2232C extensions
//
UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise
UCHAR IsoInA; // non-zero if in endpoint is isochronous
UCHAR IsoInB; // non-zero if in endpoint is isochronous
UCHAR IsoOutA; // non-zero if out endpoint is isochronous
UCHAR IsoOutB; // non-zero if out endpoint is isochronous
UCHAR PullDownEnable5; // non-zero if pull down enabled
UCHAR SerNumEnable5; // non-zero if serial number to be used
UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion
WORD USBVersion5; // BCD (0x0200 => USB2)
UCHAR AIsHighCurrent; // non-zero if interface is high current
UCHAR BIsHighCurrent; // non-zero if interface is high current
UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO
UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target
UCHAR IFAIsFastSer; // non-zero if interface is Fast serial
UCHAR AIsVCP; // non-zero if interface is to use VCP drivers
UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO
UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target
UCHAR IFBIsFastSer; // non-zero if interface is Fast serial
UCHAR BIsVCP; // non-zero if interface is to use VCP drivers
//
// FT232R extensions
//
UCHAR UseExtOsc; // Use External Oscillator
UCHAR HighDriveIOs; // High Drive I/Os
UCHAR EndpointSize; // Endpoint size
UCHAR PullDownEnableR; // non-zero if pull down enabled
UCHAR SerNumEnableR; // non-zero if serial number to be used
UCHAR InvertTXD; // non-zero if invert TXD
UCHAR InvertRXD; // non-zero if invert RXD
UCHAR InvertRTS; // non-zero if invert RTS
UCHAR InvertCTS; // non-zero if invert CTS
UCHAR InvertDTR; // non-zero if invert DTR
UCHAR InvertDSR; // non-zero if invert DSR
UCHAR InvertDCD; // non-zero if invert DCD
UCHAR InvertRI; // non-zero if invert RI
UCHAR Cbus0; // Cbus Mux control
UCHAR Cbus1; // Cbus Mux control
UCHAR Cbus2; // Cbus Mux control
UCHAR Cbus3; // Cbus Mux control
UCHAR Cbus4; // Cbus Mux control
UCHAR RIsVCP; // zero if using VCP drivers
} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA;
FTD2XX_API
FT_STATUS WINAPI FT_EE_Program(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_ProgramEx(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA lpData,
char *Manufacturer,
char *ManufacturerId,
char *Description,
char *SerialNumber
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_Read(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_ReadEx(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA lpData,
char *Manufacturer,
char *ManufacturerId,
char *Description,
char *SerialNumber
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UASize(
FT_HANDLE ftHandle,
LPDWORD lpdwSize
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UAWrite(
FT_HANDLE ftHandle,
PUCHAR pucData,
DWORD dwDataLen
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UARead(
FT_HANDLE ftHandle,
PUCHAR pucData,
DWORD dwDataLen,
LPDWORD lpdwBytesRead
);
FTD2XX_API
FT_STATUS WINAPI FT_SetLatencyTimer(
FT_HANDLE ftHandle,
UCHAR ucLatency
);
FTD2XX_API
FT_STATUS WINAPI FT_GetLatencyTimer(
FT_HANDLE ftHandle,
PUCHAR pucLatency
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBitMode(
FT_HANDLE ftHandle,
UCHAR ucMask,
UCHAR ucEnable
);
FTD2XX_API
FT_STATUS WINAPI FT_GetBitMode(
FT_HANDLE ftHandle,
PUCHAR pucMode
);
FTD2XX_API
FT_STATUS WINAPI FT_SetUSBParameters(
FT_HANDLE ftHandle,
ULONG ulInTransferSize,
ULONG ulOutTransferSize
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDeadmanTimeout(
FT_HANDLE ftHandle,
ULONG ulDeadmanTimeout
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfo(
FT_HANDLE ftHandle,
FT_DEVICE *lpftDevice,
LPDWORD lpdwID,
PCHAR SerialNumber,
PCHAR Description,
LPVOID Dummy
);
FTD2XX_API
FT_STATUS WINAPI FT_StopInTask(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_RestartInTask(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetResetPipeRetryCount( // Linux, OS X: Not supported
FT_HANDLE ftHandle,
DWORD dwCount
);
FTD2XX_API
FT_STATUS WINAPI FT_ResetPort( // Linux, OS X: Not supported
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_CyclePort( // Linux, OS X: Not supported
FT_HANDLE ftHandle
);
//
// Win32-type functions
//
FTD2XX_API
FT_HANDLE WINAPI FT_W32_CreateFile(
LPCSTR lpszName,
DWORD dwAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreate,
DWORD dwAttrsAndFlags,
HANDLE hTemplate
);
FTD2XX_API
BOOL WINAPI FT_W32_CloseHandle(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_ReadFile(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
BOOL WINAPI FT_W32_WriteFile(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesWritten,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
DWORD WINAPI FT_W32_GetLastError(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_GetOverlappedResult( // Linux, OS X: Not supported
FT_HANDLE ftHandle,
LPOVERLAPPED lpOverlapped,
LPDWORD lpdwBytesTransferred,
BOOL bWait
);
FTD2XX_API
BOOL WINAPI FT_W32_CancelIo( // Linux, OS X: Not supported
FT_HANDLE ftHandle
);
//
// Win32 COMM API type functions
//
typedef struct _FTCOMSTAT {
DWORD fCtsHold : 1;
DWORD fDsrHold : 1;
DWORD fRlsdHold : 1;
DWORD fXoffHold : 1;
DWORD fXoffSent : 1;
DWORD fEof : 1;
DWORD fTxim : 1;
DWORD fReserved : 25;
DWORD cbInQue;
DWORD cbOutQue;
} FTCOMSTAT, *LPFTCOMSTAT;
typedef struct _FTDCB {
DWORD DCBlength; /* sizeof(FTDCB) */
DWORD BaudRate; /* Baudrate at which running */
DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
DWORD fParity: 1; /* Enable parity checking */
DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
DWORD fDtrControl:2; /* DTR Flow control */
DWORD fDsrSensitivity:1; /* DSR Sensitivity */
DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
DWORD fInX: 1; /* Enable input X-ON/X-OFF */
DWORD fErrorChar: 1; /* Enable Err Replacement */
DWORD fNull: 1; /* Enable Null stripping */
DWORD fRtsControl:2; /* Rts Flow control */
DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
DWORD fDummy2:17; /* Reserved */
WORD wReserved; /* Not currently used */
WORD XonLim; /* Transmit X-ON threshold */
WORD XoffLim; /* Transmit X-OFF threshold */
BYTE ByteSize; /* Number of bits/byte, 4-8 */
BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */
BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */
char XonChar; /* Tx and Rx X-ON character */
char XoffChar; /* Tx and Rx X-OFF character */
char ErrorChar; /* Error replacement char */
char EofChar; /* End of Input character */
char EvtChar; /* Received Event character */
WORD wReserved1; /* Fill for now. */
} FTDCB, *LPFTDCB;
typedef struct _FTTIMEOUTS {
DWORD ReadIntervalTimeout; /* Maximum time between read chars. */
DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */
DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */
DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */
DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */
} FTTIMEOUTS,*LPFTTIMEOUTS;
FTD2XX_API
BOOL WINAPI FT_W32_ClearCommBreak(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_ClearCommError(
FT_HANDLE ftHandle,
LPDWORD lpdwErrors,
LPFTCOMSTAT lpftComstat
);
FTD2XX_API
BOOL WINAPI FT_W32_EscapeCommFunction(
FT_HANDLE ftHandle,
DWORD dwFunc
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommModemStatus(
FT_HANDLE ftHandle,
LPDWORD lpdwModemStatus
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommState(
FT_HANDLE ftHandle,
LPFTDCB lpftDcb
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommTimeouts(
FT_HANDLE ftHandle,
FTTIMEOUTS *pTimeouts
);
FTD2XX_API
BOOL WINAPI FT_W32_PurgeComm(
FT_HANDLE ftHandle,
DWORD dwMask
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommBreak(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommMask(
FT_HANDLE ftHandle,
ULONG ulEventMask
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommState(
FT_HANDLE ftHandle,
LPFTDCB lpftDcb
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommTimeouts(
FT_HANDLE ftHandle,
FTTIMEOUTS *pTimeouts
);
FTD2XX_API
BOOL WINAPI FT_W32_SetupComm(
FT_HANDLE ftHandle,
DWORD dwReadBufferSize,
DWORD dwWriteBufferSize
);
FTD2XX_API
BOOL WINAPI FT_W32_WaitCommEvent(
FT_HANDLE ftHandle,
PULONG pulEvent,
LPOVERLAPPED lpOverlapped
);
//
// Device information
//
typedef struct _ft_device_list_info_node {
ULONG Flags;
ULONG Type;
ULONG ID;
DWORD LocId;
char SerialNumber[16];
char Description[64];
FT_HANDLE ftHandle;
} FT_DEVICE_LIST_INFO_NODE;
FTD2XX_API
FT_STATUS WINAPI FT_CreateDeviceInfoList(
LPDWORD lpdwNumDevs
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfoList(
FT_DEVICE_LIST_INFO_NODE *pDest,
LPDWORD lpdwNumDevs
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfoDetail(
DWORD dwIndex,
LPDWORD lpdwFlags,
LPDWORD lpdwType,
LPDWORD lpdwID,
LPDWORD lpdwLocId,
LPVOID lpSerialNumber,
LPVOID lpDescription,
FT_HANDLE *pftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDriverVersion(
FT_HANDLE ftHandle,
LPDWORD lpdwVersion
);
FTD2XX_API
FT_STATUS WINAPI FT_GetLibraryVersion(
LPDWORD lpdwVersion
);
//
// Events
//
#define EV_RXCHAR 0x0001 // Any Character received
#define EV_RXFLAG 0x0002 // Received certain character
#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty
#define EV_CTS 0x0008 // CTS changed state
#define EV_DSR 0x0010 // DSR changed state
#define EV_RLSD 0x0020 // RLSD changed state
#define EV_BREAK 0x0040 // BREAK received
#define EV_ERR 0x0080 // Line status error occurred
#define EV_RING 0x0100 // Ring signal detected
#define EV_PERR 0x0200 // Printer error occured
#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full
#define EV_EVENT1 0x0800 // Provider specific event 1
#define EV_EVENT2 0x1000 // Provider specific event 2
//
// Escape Functions
//
#define SETXOFF 1 // Simulate XOFF received
#define SETXON 2 // Simulate XON received
#define SETRTS 3 // Set RTS high
#define CLRRTS 4 // Set RTS low
#define SETDTR 5 // Set DTR high
#define CLRDTR 6 // Set DTR low
#define RESETDEV 7 // Reset device if possible
#define SETBREAK 8 // Set the device break line.
#define CLRBREAK 9 // Clear the device break line.
//
// PURGE function flags.
//
#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port.
#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port.
#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there.
#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there.
#ifdef __cplusplus
}
#endif
#endif /* FTD2XX_H */

View file

@ -0,0 +1,923 @@
/*
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
*/
/*++
Copyright (c) 2001-2006 Future Technology Devices International Ltd.
Module Name:
ftd2xx.h
Abstract:
Native USB device driver for FTDI FT8U232/245
FTD2XX library definitions
Environment:
kernel & user mode
Revision History:
13/03/01 awm Created.
13/01/03 awm Added device information support.
19/03/03 awm Added FT_W32_CancelIo.
12/06/03 awm Added FT_StopInTask and FT_RestartInTask.
18/09/03 awm Added FT_SetResetPipeRetryCount.
10/10/03 awm Added FT_ResetPort.
23/01/04 awm Added support for open-by-location.
16/03/04 awm Added support for FT2232C.
23/09/04 awm Added support for FT232R.
20/10/04 awm Added FT_CyclePort.
18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type.
11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE.
25/08/05 awm Added FT_SetDeadmanTimeout.
02/12/05 awm Removed obsolete references.
05/12/05 awm Added FT_GetVersion, FT_GetVersionEx.
08/09/06 awm Added FT_W32_GetCommMask.
11/09/06 awm Added FT_Rescan.
--*/
#ifndef FTD2XX_H
#define FTD2XX_H
// The following ifdef block is the standard way of creating macros
// which make exporting from a DLL simpler. All files within this DLL
// are compiled with the FTD2XX_EXPORTS symbol defined on the command line.
// This symbol should not be defined on any project that uses this DLL.
// This way any other project whose source files include this file see
// FTD2XX_API functions as being imported from a DLL, whereas this DLL
// sees symbols defined with this macro as being exported.
#ifdef FTD2XX_EXPORTS
#define FTD2XX_API __declspec(dllexport)
#else
#define FTD2XX_API __declspec(dllimport)
#endif
typedef PVOID FT_HANDLE;
typedef ULONG FT_STATUS;
//
// Device status
//
enum {
FT_OK,
FT_INVALID_HANDLE,
FT_DEVICE_NOT_FOUND,
FT_DEVICE_NOT_OPENED,
FT_IO_ERROR,
FT_INSUFFICIENT_RESOURCES,
FT_INVALID_PARAMETER,
FT_INVALID_BAUD_RATE,
FT_DEVICE_NOT_OPENED_FOR_ERASE,
FT_DEVICE_NOT_OPENED_FOR_WRITE,
FT_FAILED_TO_WRITE_DEVICE,
FT_EEPROM_READ_FAILED,
FT_EEPROM_WRITE_FAILED,
FT_EEPROM_ERASE_FAILED,
FT_EEPROM_NOT_PRESENT,
FT_EEPROM_NOT_PROGRAMMED,
FT_INVALID_ARGS,
FT_NOT_SUPPORTED,
FT_OTHER_ERROR,
FT_DEVICE_LIST_NOT_READY,
};
#define FT_SUCCESS(status) ((status) == FT_OK)
//
// FT_OpenEx Flags
//
#define FT_OPEN_BY_SERIAL_NUMBER 1
#define FT_OPEN_BY_DESCRIPTION 2
#define FT_OPEN_BY_LOCATION 4
//
// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags
//
#define FT_LIST_NUMBER_ONLY 0x80000000
#define FT_LIST_BY_INDEX 0x40000000
#define FT_LIST_ALL 0x20000000
#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL)
//
// Baud Rates
//
#define FT_BAUD_300 300
#define FT_BAUD_600 600
#define FT_BAUD_1200 1200
#define FT_BAUD_2400 2400
#define FT_BAUD_4800 4800
#define FT_BAUD_9600 9600
#define FT_BAUD_14400 14400
#define FT_BAUD_19200 19200
#define FT_BAUD_38400 38400
#define FT_BAUD_57600 57600
#define FT_BAUD_115200 115200
#define FT_BAUD_230400 230400
#define FT_BAUD_460800 460800
#define FT_BAUD_921600 921600
//
// Word Lengths
//
#define FT_BITS_8 (UCHAR) 8
#define FT_BITS_7 (UCHAR) 7
#define FT_BITS_6 (UCHAR) 6
#define FT_BITS_5 (UCHAR) 5
//
// Stop Bits
//
#define FT_STOP_BITS_1 (UCHAR) 0
#define FT_STOP_BITS_1_5 (UCHAR) 1
#define FT_STOP_BITS_2 (UCHAR) 2
//
// Parity
//
#define FT_PARITY_NONE (UCHAR) 0
#define FT_PARITY_ODD (UCHAR) 1
#define FT_PARITY_EVEN (UCHAR) 2
#define FT_PARITY_MARK (UCHAR) 3
#define FT_PARITY_SPACE (UCHAR) 4
//
// Flow Control
//
#define FT_FLOW_NONE 0x0000
#define FT_FLOW_RTS_CTS 0x0100
#define FT_FLOW_DTR_DSR 0x0200
#define FT_FLOW_XON_XOFF 0x0400
//
// Purge rx and tx buffers
//
#define FT_PURGE_RX 1
#define FT_PURGE_TX 2
//
// Events
//
typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD);
#define FT_EVENT_RXCHAR 1
#define FT_EVENT_MODEM_STATUS 2
//
// Timeouts
//
#define FT_DEFAULT_RX_TIMEOUT 300
#define FT_DEFAULT_TX_TIMEOUT 300
//
// Device types
//
typedef ULONG FT_DEVICE;
enum {
FT_DEVICE_BM,
FT_DEVICE_AM,
FT_DEVICE_100AX,
FT_DEVICE_UNKNOWN,
FT_DEVICE_2232C,
FT_DEVICE_232R
};
#ifdef __cplusplus
extern "C" {
#endif
FTD2XX_API
FT_STATUS WINAPI FT_Open(
int deviceNumber,
FT_HANDLE *pHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_OpenEx(
PVOID pArg1,
DWORD Flags,
FT_HANDLE *pHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ListDevices(
PVOID pArg1,
PVOID pArg2,
DWORD Flags
);
FTD2XX_API
FT_STATUS WINAPI FT_Close(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_Read(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesReturned
);
FTD2XX_API
FT_STATUS WINAPI FT_Write(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesWritten
);
FTD2XX_API
FT_STATUS WINAPI FT_IoCtl(
FT_HANDLE ftHandle,
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBaudRate(
FT_HANDLE ftHandle,
ULONG BaudRate
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDivisor(
FT_HANDLE ftHandle,
USHORT Divisor
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDataCharacteristics(
FT_HANDLE ftHandle,
UCHAR WordLength,
UCHAR StopBits,
UCHAR Parity
);
FTD2XX_API
FT_STATUS WINAPI FT_SetFlowControl(
FT_HANDLE ftHandle,
USHORT FlowControl,
UCHAR XonChar,
UCHAR XoffChar
);
FTD2XX_API
FT_STATUS WINAPI FT_ResetDevice(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDtr(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ClrDtr(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetRts(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ClrRts(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_GetModemStatus(
FT_HANDLE ftHandle,
ULONG *pModemStatus
);
FTD2XX_API
FT_STATUS WINAPI FT_SetChars(
FT_HANDLE ftHandle,
UCHAR EventChar,
UCHAR EventCharEnabled,
UCHAR ErrorChar,
UCHAR ErrorCharEnabled
);
FTD2XX_API
FT_STATUS WINAPI FT_Purge(
FT_HANDLE ftHandle,
ULONG Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_SetTimeouts(
FT_HANDLE ftHandle,
ULONG ReadTimeout,
ULONG WriteTimeout
);
FTD2XX_API
FT_STATUS WINAPI FT_GetQueueStatus(
FT_HANDLE ftHandle,
DWORD *dwRxBytes
);
FTD2XX_API
FT_STATUS WINAPI FT_SetEventNotification(
FT_HANDLE ftHandle,
DWORD Mask,
PVOID Param
);
FTD2XX_API
FT_STATUS WINAPI FT_GetStatus(
FT_HANDLE ftHandle,
DWORD *dwRxBytes,
DWORD *dwTxBytes,
DWORD *dwEventDWord
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBreakOn(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBreakOff(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetWaitMask(
FT_HANDLE ftHandle,
DWORD Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_WaitOnMask(
FT_HANDLE ftHandle,
DWORD *Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_GetEventStatus(
FT_HANDLE ftHandle,
DWORD *dwEventDWord
);
FTD2XX_API
FT_STATUS WINAPI FT_ReadEE(
FT_HANDLE ftHandle,
DWORD dwWordOffset,
LPWORD lpwValue
);
FTD2XX_API
FT_STATUS WINAPI FT_WriteEE(
FT_HANDLE ftHandle,
DWORD dwWordOffset,
WORD wValue
);
FTD2XX_API
FT_STATUS WINAPI FT_EraseEE(
FT_HANDLE ftHandle
);
//
// structure to hold program data for FT_Program function
//
typedef struct ft_program_data {
DWORD Signature1; // Header - must be 0x00000000
DWORD Signature2; // Header - must be 0xffffffff
DWORD Version; // Header - FT_PROGRAM_DATA version
// 0 = original
// 1 = FT2232C extensions
// 2 = FT232R extensions
WORD VendorId; // 0x0403
WORD ProductId; // 0x6001
char *Manufacturer; // "FTDI"
char *ManufacturerId; // "FT"
char *Description; // "USB HS Serial Converter"
char *SerialNumber; // "FT000001" if fixed, or NULL
WORD MaxPower; // 0 < MaxPower <= 500
WORD PnP; // 0 = disabled, 1 = enabled
WORD SelfPowered; // 0 = bus powered, 1 = self powered
WORD RemoteWakeup; // 0 = not capable, 1 = capable
//
// Rev4 extensions
//
UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise
UCHAR IsoIn; // non-zero if in endpoint is isochronous
UCHAR IsoOut; // non-zero if out endpoint is isochronous
UCHAR PullDownEnable; // non-zero if pull down enabled
UCHAR SerNumEnable; // non-zero if serial number to be used
UCHAR USBVersionEnable; // non-zero if chip uses USBVersion
WORD USBVersion; // BCD (0x0200 => USB2)
//
// FT2232C extensions
//
UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise
UCHAR IsoInA; // non-zero if in endpoint is isochronous
UCHAR IsoInB; // non-zero if in endpoint is isochronous
UCHAR IsoOutA; // non-zero if out endpoint is isochronous
UCHAR IsoOutB; // non-zero if out endpoint is isochronous
UCHAR PullDownEnable5; // non-zero if pull down enabled
UCHAR SerNumEnable5; // non-zero if serial number to be used
UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion
WORD USBVersion5; // BCD (0x0200 => USB2)
UCHAR AIsHighCurrent; // non-zero if interface is high current
UCHAR BIsHighCurrent; // non-zero if interface is high current
UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO
UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target
UCHAR IFAIsFastSer; // non-zero if interface is Fast serial
UCHAR AIsVCP; // non-zero if interface is to use VCP drivers
UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO
UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target
UCHAR IFBIsFastSer; // non-zero if interface is Fast serial
UCHAR BIsVCP; // non-zero if interface is to use VCP drivers
//
// FT232R extensions
//
UCHAR UseExtOsc; // Use External Oscillator
UCHAR HighDriveIOs; // High Drive I/Os
UCHAR EndpointSize; // Endpoint size
UCHAR PullDownEnableR; // non-zero if pull down enabled
UCHAR SerNumEnableR; // non-zero if serial number to be used
UCHAR InvertTXD; // non-zero if invert TXD
UCHAR InvertRXD; // non-zero if invert RXD
UCHAR InvertRTS; // non-zero if invert RTS
UCHAR InvertCTS; // non-zero if invert CTS
UCHAR InvertDTR; // non-zero if invert DTR
UCHAR InvertDSR; // non-zero if invert DSR
UCHAR InvertDCD; // non-zero if invert DCD
UCHAR InvertRI; // non-zero if invert RI
UCHAR Cbus0; // Cbus Mux control
UCHAR Cbus1; // Cbus Mux control
UCHAR Cbus2; // Cbus Mux control
UCHAR Cbus3; // Cbus Mux control
UCHAR Cbus4; // Cbus Mux control
UCHAR RIsD2XX; // non-zero if using D2XX driver
} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA;
FTD2XX_API
FT_STATUS WINAPI FT_EE_Program(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_ProgramEx(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData,
char *Manufacturer,
char *ManufacturerId,
char *Description,
char *SerialNumber
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_Read(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_ReadEx(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData,
char *Manufacturer,
char *ManufacturerId,
char *Description,
char *SerialNumber
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UASize(
FT_HANDLE ftHandle,
LPDWORD lpdwSize
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UAWrite(
FT_HANDLE ftHandle,
PUCHAR pucData,
DWORD dwDataLen
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UARead(
FT_HANDLE ftHandle,
PUCHAR pucData,
DWORD dwDataLen,
LPDWORD lpdwBytesRead
);
FTD2XX_API
FT_STATUS WINAPI FT_SetLatencyTimer(
FT_HANDLE ftHandle,
UCHAR ucLatency
);
FTD2XX_API
FT_STATUS WINAPI FT_GetLatencyTimer(
FT_HANDLE ftHandle,
PUCHAR pucLatency
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBitMode(
FT_HANDLE ftHandle,
UCHAR ucMask,
UCHAR ucEnable
);
FTD2XX_API
FT_STATUS WINAPI FT_GetBitMode(
FT_HANDLE ftHandle,
PUCHAR pucMode
);
FTD2XX_API
FT_STATUS WINAPI FT_SetUSBParameters(
FT_HANDLE ftHandle,
ULONG ulInTransferSize,
ULONG ulOutTransferSize
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDeadmanTimeout(
FT_HANDLE ftHandle,
ULONG ulDeadmanTimeout
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfo(
FT_HANDLE ftHandle,
FT_DEVICE *lpftDevice,
LPDWORD lpdwID,
PCHAR SerialNumber,
PCHAR Description,
LPVOID Dummy
);
FTD2XX_API
FT_STATUS WINAPI FT_StopInTask(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_RestartInTask(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetResetPipeRetryCount(
FT_HANDLE ftHandle,
DWORD dwCount
);
FTD2XX_API
FT_STATUS WINAPI FT_ResetPort(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_CyclePort(
FT_HANDLE ftHandle
);
//
// Win32-type functions
//
FTD2XX_API
FT_HANDLE WINAPI FT_W32_CreateFile(
LPCTSTR lpszName,
DWORD dwAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreate,
DWORD dwAttrsAndFlags,
HANDLE hTemplate
);
FTD2XX_API
BOOL WINAPI FT_W32_CloseHandle(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_ReadFile(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
BOOL WINAPI FT_W32_WriteFile(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesWritten,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
DWORD WINAPI FT_W32_GetLastError(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_GetOverlappedResult(
FT_HANDLE ftHandle,
LPOVERLAPPED lpOverlapped,
LPDWORD lpdwBytesTransferred,
BOOL bWait
);
FTD2XX_API
BOOL WINAPI FT_W32_CancelIo(
FT_HANDLE ftHandle
);
//
// Win32 COMM API type functions
//
typedef struct _FTCOMSTAT {
DWORD fCtsHold : 1;
DWORD fDsrHold : 1;
DWORD fRlsdHold : 1;
DWORD fXoffHold : 1;
DWORD fXoffSent : 1;
DWORD fEof : 1;
DWORD fTxim : 1;
DWORD fReserved : 25;
DWORD cbInQue;
DWORD cbOutQue;
} FTCOMSTAT, *LPFTCOMSTAT;
typedef struct _FTDCB {
DWORD DCBlength; /* sizeof(FTDCB) */
DWORD BaudRate; /* Baudrate at which running */
DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
DWORD fParity: 1; /* Enable parity checking */
DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
DWORD fDtrControl:2; /* DTR Flow control */
DWORD fDsrSensitivity:1; /* DSR Sensitivity */
DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
DWORD fInX: 1; /* Enable input X-ON/X-OFF */
DWORD fErrorChar: 1; /* Enable Err Replacement */
DWORD fNull: 1; /* Enable Null stripping */
DWORD fRtsControl:2; /* Rts Flow control */
DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
DWORD fDummy2:17; /* Reserved */
WORD wReserved; /* Not currently used */
WORD XonLim; /* Transmit X-ON threshold */
WORD XoffLim; /* Transmit X-OFF threshold */
BYTE ByteSize; /* Number of bits/byte, 4-8 */
BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */
BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */
char XonChar; /* Tx and Rx X-ON character */
char XoffChar; /* Tx and Rx X-OFF character */
char ErrorChar; /* Error replacement char */
char EofChar; /* End of Input character */
char EvtChar; /* Received Event character */
WORD wReserved1; /* Fill for now. */
} FTDCB, *LPFTDCB;
typedef struct _FTTIMEOUTS {
DWORD ReadIntervalTimeout; /* Maximum time between read chars. */
DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */
DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */
DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */
DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */
} FTTIMEOUTS,*LPFTTIMEOUTS;
FTD2XX_API
BOOL WINAPI FT_W32_ClearCommBreak(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_ClearCommError(
FT_HANDLE ftHandle,
LPDWORD lpdwErrors,
LPFTCOMSTAT lpftComstat
);
FTD2XX_API
BOOL WINAPI FT_W32_EscapeCommFunction(
FT_HANDLE ftHandle,
DWORD dwFunc
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommModemStatus(
FT_HANDLE ftHandle,
LPDWORD lpdwModemStatus
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommState(
FT_HANDLE ftHandle,
LPFTDCB lpftDcb
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommTimeouts(
FT_HANDLE ftHandle,
FTTIMEOUTS *pTimeouts
);
FTD2XX_API
BOOL WINAPI FT_W32_PurgeComm(
FT_HANDLE ftHandle,
DWORD dwMask
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommBreak(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommMask(
FT_HANDLE ftHandle,
ULONG ulEventMask
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommMask(
FT_HANDLE ftHandle,
LPDWORD lpdwEventMask
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommState(
FT_HANDLE ftHandle,
LPFTDCB lpftDcb
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommTimeouts(
FT_HANDLE ftHandle,
FTTIMEOUTS *pTimeouts
);
FTD2XX_API
BOOL WINAPI FT_W32_SetupComm(
FT_HANDLE ftHandle,
DWORD dwReadBufferSize,
DWORD dwWriteBufferSize
);
FTD2XX_API
BOOL WINAPI FT_W32_WaitCommEvent(
FT_HANDLE ftHandle,
PULONG pulEvent,
LPOVERLAPPED lpOverlapped
);
//
// Device information
//
typedef struct _ft_device_list_info_node {
ULONG Flags;
ULONG Type;
ULONG ID;
DWORD LocId;
char SerialNumber[16];
char Description[64];
FT_HANDLE ftHandle;
} FT_DEVICE_LIST_INFO_NODE;
FTD2XX_API
FT_STATUS WINAPI FT_CreateDeviceInfoList(
LPDWORD lpdwNumDevs
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfoList(
FT_DEVICE_LIST_INFO_NODE *pDest,
LPDWORD lpdwNumDevs
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfoDetail(
DWORD dwIndex,
LPDWORD lpdwFlags,
LPDWORD lpdwType,
LPDWORD lpdwID,
LPDWORD lpdwLocId,
LPVOID lpSerialNumber,
LPVOID lpDescription,
FT_HANDLE *pftHandle
);
//
// Version information
//
FTD2XX_API
FT_STATUS WINAPI FT_GetDriverVersion(
FT_HANDLE ftHandle,
LPDWORD lpdwVersion
);
FTD2XX_API
FT_STATUS WINAPI FT_GetLibraryVersion(
LPDWORD lpdwVersion
);
FTD2XX_API
FT_STATUS WINAPI FT_Rescan(
void
);
FTD2XX_API
FT_STATUS WINAPI FT_Reload(
WORD wVid,
WORD wPid
);
#ifdef __cplusplus
}
#endif
#endif /* FTD2XX_H */

View file

@ -0,0 +1,210 @@
/*
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
*/
#include <unistd.h>
#include <strings.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
int hexfile_build_tables(char *ihexfile, unsigned char *page_buffer, unsigned char *page_table)
{
unsigned char buffer[256];
int length;
int i;
int pages;
unsigned long ext_addr=0;
unsigned short int addr=0;
FILE *ihex_fp;
if((ihex_fp = (FILE *)fopen(ihexfile, "r")) == NULL)
{
printf("Failed to open .ihex file %s\n", ihexfile);
return(-1);
}
else
{
printf(".ihex file ok.\n");
}
bzero(buffer, sizeof(buffer));
/*initialize page data*/
memset(page_table, 0, 64);
memset(page_buffer, 0xFF, sizeof(page_buffer));
pages = 0;
while((fscanf(ihex_fp, "%s", buffer) == 1))
{
unsigned char data_len = 0;
if (memcmp(&buffer[7], "00", 2) == 0)
{ /*Data record*/
i=0;
sscanf((char *)&buffer[1], "%2hhx", &data_len);
sscanf((char *)&(buffer[3]),"%4hx", &addr);
while(i<data_len)
{
uint32_t absolute_address = ext_addr+addr+i;
if (page_table[absolute_address/2048] == 0)
{
page_table[absolute_address/2048] = 1;
printf("Writing %d pages.\r", ++pages);
}
sscanf((char *)&buffer[2*i+9], "%2hhx", &page_buffer[absolute_address]);
i++;
}
}
else if (memcmp(&buffer[7], "01", 2) == 0)
{ /*end file*/
printf("\nFile read complete.\n");
break;
}
else if (memcmp(&buffer[7], "04", 2) == 0)
{
sscanf((char *)&(buffer[3]),"%4hx", &addr);
sscanf((char *)&(buffer[9]),"%4lx", &ext_addr);
printf("\nExtended page address: 0x%8.8lX\n", ext_addr*0x8000 );
if (ext_addr) ext_addr--;
ext_addr *= 0x8000;
}
}
fclose(ihex_fp);
return(pages);
}
int hexfile_program(unsigned char *page_buffer, unsigned char *page_table)
{
int retry = 0;
int error = 0;
unsigned char buffer[256];
int length;
int i;
int pages;
unsigned long ext_addr=0;
unsigned short int addr=0;
printf("Starting programming.\n");
error = 0;
for (i=0; i<64; i++)
{
if (page_table[i] != 0)
{
ext_addr = 2048*i;
bzero(buffer, sizeof(buffer));
// Write the start address and check return
usleep(3000);
cdi_set_address(ext_addr);
printf("\r \r");
fflush(stdout);
cdi_flash_write(&page_buffer[ext_addr], 2048);
usleep(20000);
}
}
return(1);
}
int hexfile_parse(char *line, unsigned int *type, unsigned int *addr, unsigned char *buffer)
{
unsigned int row_len = 0;
unsigned int row_index = 7;
unsigned int i;
int tmp;
uint8_t cksum = 0;
int retval = 0;
retval = sscanf(line, ":%2x%4x%2x", &row_len, addr, type);
cksum += row_len;
cksum += *addr >> 8;
cksum += *addr & 0xFF;
cksum += *type;
i = 0;
if (retval == 3)
{
while(i < row_len)
{
if (sscanf(&line[row_index], "%2x", &tmp) == 1)
{
cksum += tmp;
buffer[i++] = (unsigned char) tmp;
row_index += 2;
}
else return -1;
}
if (sscanf(&line[row_index], "%2x", &tmp) == 1)
{
if ((cksum + (uint8_t) tmp) == 0) return row_len;
}
}
return -1;
}
int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes)
{
uint8_t cksum = 0;
uint8_t i = 0;
char tmp[8];
sprintf(line, ":%2.2X%4.4X%2.2X", bytes, address, type);
cksum -= bytes;
cksum -= address >> 8;
cksum -= address & 0xFF;
cksum -= type;
for (i=0; i<bytes; i++)
{
sprintf(tmp, "%2.2X", data[i]);
strcat(line, tmp);
cksum -= data[i];
}
sprintf(tmp, "%2.2X\r\n", cksum);
strcat(line, tmp);
return strlen(line);
}

View file

@ -0,0 +1,36 @@
/*
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
*/
#ifndef _IHEX_H
#define _IHEX_H
extern int hexfile_parse(char *line, unsigned char *type, unsigned int *addr, char *buffer);
extern int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes);
#endif /*_IHEX_H*/

View file

@ -0,0 +1,348 @@
/*
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;
}

View file

@ -0,0 +1,372 @@
/*
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
*/
#include <stdio.h>
#include <inttypes.h>
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#endif
#include <ftd2xx.h>
FT_HANDLE curr_handle = 0;
uint8_t curr_mode = 0; /* 0 = in, 1=out */
/*
* This function checks if the CBUS2 ise set to SLEEP and modifies it if necessary.
* The CBUS2 must be set to sleep in order the programming to succeed.
*/
int check_cbus2(FT_HANDLE fthandle)
{
FT_PROGRAM_DATA eeprom_data;
char manufacturer_buf[32];
char manufacturer_id[16];
char description_buf[64];
char serialnumber_buf[16];
eeprom_data.Signature1 = 0x00000000; // This is a given value from the FT232R programming guide
eeprom_data.Signature2 = 0xffffffff; // This is a given value from the FT232R programming guide
eeprom_data.Version = 0x00000002; // This is a given value from the FT232R programming guide
eeprom_data.Manufacturer = manufacturer_buf;
eeprom_data.ManufacturerId = manufacturer_id;
eeprom_data.Description = description_buf;
eeprom_data.SerialNumber = serialnumber_buf;
if(FT_EE_Read(fthandle, &eeprom_data) != FT_OK)
{
printf("FTDI EEPROM read failed.\n");
return(-1);
}
if(eeprom_data.Cbus2 != 0x05)
{
printf("Need to re-program the CBUS2 to 0x05\n");
eeprom_data.Cbus2 = 0x05;
if(FT_EE_Program(fthandle, &eeprom_data) != FT_OK)
{
printf("FTDI EEPROM program error.\n");
return(-1);
}
else
{
printf("FTDI EEPROM program ok\n");
return(1);
}
}
else
{
return(1);
}
return(1);
}
void prog_scan(void)
{
FT_STATUS ftStatus;
FT_DEVICE_LIST_INFO_NODE *info;
unsigned long n_devices = 0;
uint8_t out;
ftStatus = FT_CreateDeviceInfoList(&n_devices);
if (ftStatus == FT_OK)
{
FT_DEVICE_LIST_INFO_NODE devices[n_devices];
ftStatus = FT_GetDeviceInfoList(devices,&n_devices);
if (ftStatus == FT_OK)
{
for (out = 0; out < n_devices; out++)
{
printf("Dev %d:",n_devices - out -1);
printf(" Type=0x%x",devices[n_devices - out -1].Type);
printf(" SerialNumber=%s",devices[n_devices - out -1].SerialNumber);
printf(" Description=%s\n",devices[n_devices - out -1].Description);
}
}
else
{
printf("Failed to fetch device list.\n");
}
}
else
{
printf("Failed to fetch device list.\n");
}
}
FT_HANDLE prog_open(int iport)
{
FT_HANDLE ftHandle;
FT_STATUS ftStatus;
FT_DEVICE_LIST_INFO_NODE *info;
unsigned long n_devices = 0;
uint8_t out;
if (curr_handle) return 0;
ftStatus = FT_CreateDeviceInfoList(&n_devices);
if (ftStatus == FT_OK)
{
FT_DEVICE_LIST_INFO_NODE devices[n_devices];
ftStatus = FT_GetDeviceInfoList(devices,&n_devices);
if (ftStatus == FT_OK)
{
iport = n_devices - iport - 1;
if (iport < 0)
{
printf("Invalid port id.\n");
for (out = 0; out < n_devices; out++)
{
printf("Dev %d:",n_devices - out -1);
printf(" Type=0x%x",devices[n_devices - out -1].Type);
printf(" SerialNumber=%s",devices[n_devices - out -1].SerialNumber);
printf(" Description=%s\n",devices[n_devices - out -1].Description);
}
return 0;
}
}
}
ftStatus = FT_Open(iport, &ftHandle);
if(ftStatus != FT_OK) {
/*
This can fail if the ftdi_sio driver is loaded
use lsmod to check this and rmmod ftdi_sio to remove
also rmmod usbserial
*/
printf("FT_Open(%d) failed\n", iport);
return 0;
}
if(check_cbus2(ftHandle) < 0)
{
printf("Nano USB Programmer exiting...\n");
return(0);
}
FT_ResetDevice(ftHandle);
FT_SetBaudRate(ftHandle, 115200);
FT_SetUSBParameters(ftHandle, 64, 0);
out = 0x04;
ftStatus = FT_SetBitMode(ftHandle, out, 0x20);
if (ftStatus == FT_OK)
{
ftStatus = FT_SetLatencyTimer(ftHandle, 2);
}
if (ftStatus == FT_OK)
{
DWORD bytes;
out = 0xE0;
ftStatus = FT_SetBitMode(ftHandle, out, 0x04);
out = 0x80;
FT_Write(ftHandle, &out, 1, &bytes); /*write reset high*/
FT_Read(ftHandle, &out, 1, &bytes); /*read out*/
curr_mode = 1;
}
if (ftStatus != FT_OK)
{
printf("Failed to set CBUS2/bit bang mode.\n");
FT_ResetDevice(ftHandle);
sleep(3);
FT_Close(ftHandle);
ftHandle = 0;
}
curr_handle = ftHandle;
return ftHandle;
}
void prog_close(void)
{
FT_STATUS ftStatus;
DWORD bytes;
if (curr_handle)
{
FT_HANDLE ftHandle = curr_handle;
uint8_t out = 0x00;
FT_Write(ftHandle, &out, 1, &bytes); /*write reset low*/
FT_Read(ftHandle, &out, 1, &bytes); /*read out*/
sleep(1);
out = 0x80;
FT_Write(ftHandle, &out, 1, &bytes); /*write reset high*/
FT_Read(ftHandle, &out, 1, &bytes); /*read out*/
sleep(1);
out = 0x00;
ftStatus = FT_SetBitMode(ftHandle, out, 0x04);
FT_ResetDevice(ftHandle);
FT_Close(ftHandle);
ftHandle = 0;
curr_handle = ftHandle;
}
}
int prog_write(uint8_t byte)
{
FT_STATUS ftStatus;
uint8_t out[16];
uint8_t mask = 0x80;
int i;
DWORD bytes;
if (curr_mode == 0)
{
out[0] = 0xE0;
ftStatus = FT_SetBitMode(curr_handle, out[0], 0x04); /*Set DD as output*/
if (ftStatus != FT_OK)
{ printf("!WR");
fflush(stdout);
return -1;
}
curr_mode = 1;
}
i = 0;
while (mask)
{
out[i] = 0xC0; /*clock high, reset high*/
if (byte & mask) out[i] |= 0x20;
i++;
out[i] = 0x80; /*clock low, reset high*/
if (byte & mask) out[i] |= 0x20;
i++;
mask >>= 1;
}
ftStatus = FT_Write(curr_handle, out, 16, &bytes); /*write clock high and data bit*/
if (ftStatus != FT_OK)
{
printf("!W");
fflush(stdout);
return -1;
}
if(FT_Read(curr_handle, out, 16, &bytes) != FT_OK)
{
printf("!R");
return(-1);
}
return 0;
}
int prog_read(uint8_t *byte)
{
FT_STATUS ftStatus;
uint8_t rd;
uint8_t mask = 0x80;
DWORD bytes;
uint8_t out[17];
uint8_t i=0;
*byte = 0;
if (curr_mode == 1)
{
out[0] = 0xC0;
ftStatus = FT_SetBitMode(curr_handle, out[0], 0x04); /*Set DD as input*/
if (ftStatus != FT_OK)
{ printf("!RD");
fflush(stdout);
return -1;
}
curr_mode = 0;
}
while (mask)
{
out[i] = 0xC0; /*clock high, reset high*/
if (*byte & mask) out[i] |= 0x20;
i++;
out[i] = 0x80; /*clock low, reset high*/
if (*byte & mask) out[i] |= 0x20;
i++;
mask >>= 1;
}
out[16] = out[15];
ftStatus = FT_Write(curr_handle, out, 17, &bytes); /*write clock high and data bit*/
if(FT_Read(curr_handle, out, 17, &bytes) != FT_OK)
{
printf("!R");
return(-1);
}
mask = 0x80;
i = 1;
while (mask)
{
if (out[i] & 0x20) *byte |= mask;
mask >>= 1;
i+=2;
}
return 0;
}
int prog_start(void)
{
FT_STATUS ftStatus;
uint8_t wr;
uint8_t mask = 0x80;
DWORD bytes;
uint8_t out[16] = { 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80 };
printf("prog_start()\n");
if (curr_mode == 0)
{
wr = 0xE0;
ftStatus = FT_SetBitMode(curr_handle, wr, 0x04); /*Set DD as output*/
curr_mode = 1;
}
if(FT_Write(curr_handle, out, 7, &bytes) != FT_OK)
{
printf("!W\n");
return(-1);
}
if(FT_Read(curr_handle, out, 7, &bytes) != FT_OK)
{
printf("!R\n");
return(-1);
}
}

View file

@ -0,0 +1,46 @@
/*
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
*/
#ifndef _PROG_H
#define _PROG_H
#include "ftd2xx.h"
#include <inttypes.h>
extern FT_HANDLE prog_open(int iport);
extern void prog_close(void);
extern int prog_write(uint8_t byte);
extern int prog_read(uint8_t *byte);
extern int prog_start(void);
extern int check_cbus2(FT_HANDLE fthandle);
#endif