From fc237101bedb715befb5c60373bb017e95c70cea Mon Sep 17 00:00:00 2001 From: zdshelby Date: Wed, 9 Sep 2009 09:48:16 +0000 Subject: [PATCH] - Added the Sensinode platform programming tools to /tools --- tools/sensinode/nano_programmer/Makefile | 43 + tools/sensinode/nano_programmer/README | 34 + tools/sensinode/nano_programmer/cdi_program.c | 607 +++++++++++ tools/sensinode/nano_programmer/ihex.c | 99 ++ tools/sensinode/nano_programmer/ihex.h | 36 + tools/sensinode/nano_programmer/linux/port.c | 371 +++++++ .../sensinode/nano_programmer/nano_programmer | Bin 0 -> 18776 bytes tools/sensinode/nano_programmer/port.h | 94 ++ tools/sensinode/nano_programmer/programmer.c | 440 ++++++++ tools/sensinode/nano_programmer/programmer.h | 62 ++ .../sensinode/nano_programmer/windows/port.c | 383 +++++++ tools/sensinode/nano_usb_programmer/Makefile | 32 + tools/sensinode/nano_usb_programmer/README | 56 + .../sensinode/nano_usb_programmer/Rules.make | 14 + tools/sensinode/nano_usb_programmer/cdi.c | 506 +++++++++ tools/sensinode/nano_usb_programmer/cdi.h | 44 + .../nano_usb_programmer/ftdi_linux/WinTypes.h | 116 +++ .../nano_usb_programmer/ftdi_linux/ftd2xx.h | 975 ++++++++++++++++++ .../nano_usb_programmer/ftdi_win32/ftd2xx.h | 923 +++++++++++++++++ tools/sensinode/nano_usb_programmer/ihex.c | 210 ++++ tools/sensinode/nano_usb_programmer/ihex.h | 36 + tools/sensinode/nano_usb_programmer/main.c | 348 +++++++ tools/sensinode/nano_usb_programmer/prog.c | 372 +++++++ tools/sensinode/nano_usb_programmer/prog.h | 46 + 24 files changed, 5847 insertions(+) create mode 100644 tools/sensinode/nano_programmer/Makefile create mode 100755 tools/sensinode/nano_programmer/README create mode 100644 tools/sensinode/nano_programmer/cdi_program.c create mode 100644 tools/sensinode/nano_programmer/ihex.c create mode 100644 tools/sensinode/nano_programmer/ihex.h create mode 100644 tools/sensinode/nano_programmer/linux/port.c create mode 100755 tools/sensinode/nano_programmer/nano_programmer create mode 100644 tools/sensinode/nano_programmer/port.h create mode 100644 tools/sensinode/nano_programmer/programmer.c create mode 100644 tools/sensinode/nano_programmer/programmer.h create mode 100644 tools/sensinode/nano_programmer/windows/port.c create mode 100644 tools/sensinode/nano_usb_programmer/Makefile create mode 100644 tools/sensinode/nano_usb_programmer/README create mode 100644 tools/sensinode/nano_usb_programmer/Rules.make create mode 100644 tools/sensinode/nano_usb_programmer/cdi.c create mode 100644 tools/sensinode/nano_usb_programmer/cdi.h create mode 100644 tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h create mode 100644 tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h create mode 100755 tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h create mode 100644 tools/sensinode/nano_usb_programmer/ihex.c create mode 100644 tools/sensinode/nano_usb_programmer/ihex.h create mode 100644 tools/sensinode/nano_usb_programmer/main.c create mode 100644 tools/sensinode/nano_usb_programmer/prog.c create mode 100644 tools/sensinode/nano_usb_programmer/prog.h diff --git a/tools/sensinode/nano_programmer/Makefile b/tools/sensinode/nano_programmer/Makefile new file mode 100644 index 000000000..06c0fb979 --- /dev/null +++ b/tools/sensinode/nano_programmer/Makefile @@ -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) diff --git a/tools/sensinode/nano_programmer/README b/tools/sensinode/nano_programmer/README new file mode 100755 index 000000000..27daa114a --- /dev/null +++ b/tools/sensinode/nano_programmer/README @@ -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 diff --git a/tools/sensinode/nano_programmer/cdi_program.c b/tools/sensinode/nano_programmer/cdi_program.c new file mode 100644 index 000000000..3b2ecd255 --- /dev/null +++ b/tools/sensinode/nano_programmer/cdi_program.c @@ -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 +#include +#include + +#include "port.h" +#include "programmer.h" +#include "ihex.h" + +#include + +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(ipage_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; +} + diff --git a/tools/sensinode/nano_programmer/ihex.c b/tools/sensinode/nano_programmer/ihex.c new file mode 100644 index 000000000..83234714e --- /dev/null +++ b/tools/sensinode/nano_programmer/ihex.c @@ -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 +#include +#include +#include + +#include + +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 + +#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); +} + diff --git a/tools/sensinode/nano_programmer/nano_programmer b/tools/sensinode/nano_programmer/nano_programmer new file mode 100755 index 0000000000000000000000000000000000000000..fd3e46b8a66dbbb1df54b70bac68e3c11ed4d6a4 GIT binary patch literal 18776 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 d&*&D!`}>RztI1m07&WhD +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include "windows.h" +#include +#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 */ diff --git a/tools/sensinode/nano_programmer/programmer.c b/tools/sensinode/nano_programmer/programmer.c new file mode 100644 index 000000000..ee82c9389 --- /dev/null +++ b/tools/sensinode/nano_programmer/programmer.c @@ -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 +#include +#include + +#include "port.h" +#include "programmer.h" + +#include + +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 %.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 %.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; +} diff --git a/tools/sensinode/nano_programmer/programmer.h b/tools/sensinode/nano_programmer/programmer.h new file mode 100644 index 000000000..d8eab549e --- /dev/null +++ b/tools/sensinode/nano_programmer/programmer.h @@ -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); + diff --git a/tools/sensinode/nano_programmer/windows/port.c b/tools/sensinode/nano_programmer/windows/port.c new file mode 100644 index 000000000..5b9a09f9c --- /dev/null +++ b/tools/sensinode/nano_programmer/windows/port.c @@ -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 + +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 diff --git a/tools/sensinode/nano_usb_programmer/Makefile b/tools/sensinode/nano_usb_programmer/Makefile new file mode 100644 index 000000000..2c1e40988 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/Makefile @@ -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 diff --git a/tools/sensinode/nano_usb_programmer/README b/tools/sensinode/nano_usb_programmer/README new file mode 100644 index 000000000..c2c1c706f --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/README @@ -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 diff --git a/tools/sensinode/nano_usb_programmer/Rules.make b/tools/sensinode/nano_usb_programmer/Rules.make new file mode 100644 index 000000000..034cd0321 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/Rules.make @@ -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 diff --git a/tools/sensinode/nano_usb_programmer/cdi.c b/tools/sensinode/nano_usb_programmer/cdi.c new file mode 100644 index 000000000..2d490869f --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/cdi.c @@ -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 +#ifdef PLATFORM_WINDOWS +#include +#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>= 3; + for (i=0; i> 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> 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; +} diff --git a/tools/sensinode/nano_usb_programmer/cdi.h b/tools/sensinode/nano_usb_programmer/cdi.h new file mode 100644 index 000000000..40e909178 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/cdi.h @@ -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 diff --git a/tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h b/tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h new file mode 100644 index 000000000..4def457b7 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ftdi_linux/WinTypes.h @@ -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 + +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 diff --git a/tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h b/tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h new file mode 100644 index 000000000..f4146f1d8 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ftdi_linux/ftd2xx.h @@ -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 +#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 */ + + + + + + diff --git a/tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h b/tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h new file mode 100755 index 000000000..fd15376f8 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ftdi_win32/ftd2xx.h @@ -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 */ + diff --git a/tools/sensinode/nano_usb_programmer/ihex.c b/tools/sensinode/nano_usb_programmer/ihex.c new file mode 100644 index 000000000..a7889e57b --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/ihex.c @@ -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 +#include +#include +#include + +#include + +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> 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 +#include +#include +#include +#include + +#include +#ifdef PLATFORM_WINDOWS +#include +#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 ]\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; +} + diff --git a/tools/sensinode/nano_usb_programmer/prog.c b/tools/sensinode/nano_usb_programmer/prog.c new file mode 100644 index 000000000..1cce8ec83 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/prog.c @@ -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 +#include +#ifdef PLATFORM_WINDOWS +#include +#endif +#include + +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); + } + +} diff --git a/tools/sensinode/nano_usb_programmer/prog.h b/tools/sensinode/nano_usb_programmer/prog.h new file mode 100644 index 000000000..fc2107d47 --- /dev/null +++ b/tools/sensinode/nano_usb_programmer/prog.h @@ -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 + +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