- Added the Sensinode platform programming tools to /tools
This commit is contained in:
parent
83988ef554
commit
fc237101be
24 changed files with 5847 additions and 0 deletions
43
tools/sensinode/nano_programmer/Makefile
Normal file
43
tools/sensinode/nano_programmer/Makefile
Normal file
|
@ -0,0 +1,43 @@
|
|||
EXE_MAKE=$(notdir $(shell which "make.exe" 2>/dev/null))
|
||||
ifeq "$(EXE_MAKE)" "make.exe"
|
||||
PLATFORM=windows
|
||||
else
|
||||
PLATFORM=linux
|
||||
endif
|
||||
|
||||
OBJECTS = ihex.o $(PLATFORM)/port.o programmer.o cdi_program.o
|
||||
SUBDIRS =
|
||||
|
||||
ifeq "$(PLATFORM)" "linux"
|
||||
CFLAGS = -Wall -D_REENTRANT -I.
|
||||
LDFLAGS = -L. -D_REENTRANT -lpthread
|
||||
SUFFIX=
|
||||
else
|
||||
CFLAGS=-I. -I../nano_usb_programmer/ftdi_win32
|
||||
CFLAGS+= -L. -L../nano_usb_programmer/ftdi_win32 -DPLATFORM_WINDOWS
|
||||
CFLAGS+= -mwin32
|
||||
LDFLAGS=../nano_usb_programmer/ftdi_win32/ftd2xx.lib -lkernel32
|
||||
SUFFIX=.exe
|
||||
endif
|
||||
|
||||
TARGET = nano_programmer$(SUFFIX)
|
||||
|
||||
all: binary
|
||||
|
||||
binary: $(TARGET)
|
||||
strip $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
gcc -o $(TARGET) $(OBJECTS) $(LDFLAGS)
|
||||
|
||||
.c.o:
|
||||
gcc -c -o $(<:.c=.o) -O2 -Wall $(CFLAGS) $<
|
||||
|
||||
platform-test:
|
||||
@echo $(PLATFORM)
|
||||
|
||||
old-strip:
|
||||
if [ -x $(TARGET).exe ]; then $(PLATFORM)strip $(TARGET).exe; else $(PLATFORM)strip $(TARGET); fi
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) $(OBJECTS)
|
34
tools/sensinode/nano_programmer/README
Executable file
34
tools/sensinode/nano_programmer/README
Executable file
|
@ -0,0 +1,34 @@
|
|||
Nano Programmer
|
||||
|
||||
Programming tool for the Sensinode Nano series using Dxxx development boards.
|
||||
|
||||
Copyright 2007-2008 Sensinode Ltd.
|
||||
|
||||
1a - Installation (Linux)
|
||||
|
||||
No external libraries required.
|
||||
|
||||
1b - Installation (Windows/Cygwin)
|
||||
|
||||
Installation procedure:
|
||||
See the nano_usb_programmer README file on how to install FTDI library
|
||||
for nano_usb_programmer. The nano_programmer build system will fetch
|
||||
the library from there.
|
||||
|
||||
2 - Usage
|
||||
|
||||
Usage info for the Nano Programmer is available with command
|
||||
./nano_programmer --help. Note that use might require root/administrator privileges
|
||||
depending on system configuration.
|
||||
|
||||
3 - Known problems
|
||||
|
||||
Occasional timing failures resulting in "Reinit failed."-messages do come
|
||||
up in some PC configurations. If you experience programming failures (the programmer
|
||||
is not able to recover), please report your system configuration to Sensinode.
|
||||
On Linux, it is known that the "brltty" program causes problems with the FTDI
|
||||
serial driver. Uninstalling brltty resolves the problem.
|
||||
|
||||
4 - README Version
|
||||
|
||||
v1.3 2008-01-31 Martti Huttunen Multi-platform build and created instructions
|
607
tools/sensinode/nano_programmer/cdi_program.c
Normal file
607
tools/sensinode/nano_programmer/cdi_program.c
Normal file
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "programmer.h"
|
||||
#include "ihex.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern void crc_add(unsigned char *crc, unsigned char byte);
|
||||
|
||||
int cdi_page_write(port_t *port, unsigned long page_addr, unsigned char *page_buffer);
|
||||
int cdi_write(port_t *port, conf_opts_t *conf, FILE *ihex);
|
||||
|
||||
int cdi_programmer(conf_opts_t *conf, char *filename)
|
||||
{
|
||||
int error = 0;
|
||||
port_t *port = 0;
|
||||
unsigned char buffer[256];
|
||||
int length = 0;
|
||||
FILE *ihex = 0;
|
||||
|
||||
error = programmer_init(conf->device, &port);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
if((!error) && (conf->action != 'b'))
|
||||
{
|
||||
length = port_write_echo(port, "CDI\r");
|
||||
bzero(buffer, sizeof(buffer));
|
||||
if (length >= 4)
|
||||
{
|
||||
length = port_readline(port, buffer, sizeof(buffer), 100);
|
||||
}
|
||||
else length = 0;
|
||||
|
||||
if(memcmp(buffer, "OK", 2) == 0)
|
||||
{
|
||||
error = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Programming mode selection failed.\n");
|
||||
error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if((!error) && (conf->action != 'b'))
|
||||
{
|
||||
printf("Initialize.\n");
|
||||
// Succesfully in mode 1
|
||||
sleep(1);
|
||||
port_write_echo(port, "i\r");
|
||||
|
||||
bzero(buffer, 256);
|
||||
length = port_readline(port, buffer, sizeof(buffer), 100);
|
||||
|
||||
if(memcmp(buffer, "85", 2) == 0)
|
||||
{ /*Found CC2430 device*/
|
||||
printf("Found CC2430 device revision %c%c.\n", buffer[2], buffer[3]);
|
||||
}
|
||||
else if (memcmp(buffer, "89", 2) == 0)
|
||||
{
|
||||
printf("Found CC2431 device revision %c%c.\n", buffer[2], buffer[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("CC2430 not found.\n");
|
||||
error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) conf->action = ' ';
|
||||
|
||||
switch(conf->action)
|
||||
{
|
||||
case 'e':
|
||||
// Erase programming
|
||||
port_write_echo(port, "e\r");
|
||||
bzero(buffer, 256);
|
||||
length = port_readline(port, buffer, sizeof(buffer), 100);
|
||||
|
||||
if(memcmp(buffer, "OK", 2) == 0)
|
||||
{
|
||||
// Erase successful
|
||||
printf("Erase successful.\n");
|
||||
error = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Erase failed
|
||||
printf("Erase failed: %s.\n", buffer);
|
||||
error = -1;
|
||||
}
|
||||
if ((conf->action != 'P') || error)
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
case 'w':
|
||||
ihex = fopen(conf->ihex_file, "rb");
|
||||
if(ihex == NULL)
|
||||
{
|
||||
printf("Failed to open ihex file %s.\n", conf->ihex_file);
|
||||
error = -1;
|
||||
}
|
||||
else error = 0;
|
||||
|
||||
if (!error)
|
||||
{
|
||||
error = cdi_write(port, conf, ihex);
|
||||
if (error) printf("Programming failed.\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (ihex != NULL) fclose(ihex);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
length = port_write_echo(port, "V\r");
|
||||
bzero(buffer, sizeof(buffer));
|
||||
if (length >= 2)
|
||||
{
|
||||
length = port_readline(port, buffer, sizeof(buffer), 100);
|
||||
}
|
||||
else length = 0;
|
||||
|
||||
if(length > 4)
|
||||
{
|
||||
buffer[length] = 0;
|
||||
printf("BIOS: %s\n", buffer);
|
||||
error = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to get BIOS version. Upgrade recommended.\n");
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
ihex = fopen(conf->ihex_file, "wb");
|
||||
if(ihex == NULL)
|
||||
{
|
||||
printf("Failed to open ihex file %s.\n", conf->ihex_file);
|
||||
error = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
port_write_echo(port, "a000000\r");
|
||||
bzero(buffer, sizeof(buffer));
|
||||
length = port_readline(port, buffer, sizeof(buffer), 200);
|
||||
if (length <0) length = 0;
|
||||
if(memcmp(buffer, "OK", 2) == 0)
|
||||
{
|
||||
uint32_t address = 0;
|
||||
uint8_t check = 0;
|
||||
for (address = 0; address < 128*1024; address += 64)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
if ((address) && ((address & 0xFFFF)==0))
|
||||
{
|
||||
fprintf(ihex, ":02000004%4.4X%2.2X\r\n",
|
||||
(int)(address>>16), (int)(0xFA-(address>>16)));
|
||||
}
|
||||
port_write_echo(port, "r\r");
|
||||
bzero(buffer, 256);
|
||||
length = 0;
|
||||
while (length < 64)
|
||||
{
|
||||
length += port_readline(port, &buffer[length], sizeof(buffer)-length, 100);
|
||||
}
|
||||
for (i=0; i<64; i++)
|
||||
{
|
||||
if ((i & 0x0F) == 0)
|
||||
{
|
||||
check = 0;
|
||||
check -= 0x10;
|
||||
check -= (uint8_t) (address >> 8);
|
||||
check -= (uint8_t) (address + i);
|
||||
printf("%4.4X", (int) address + i);
|
||||
fprintf(ihex, ":10%4.4X00", (int) (address + i) & 0xFFFF);
|
||||
}
|
||||
fprintf(ihex, "%2.2X", buffer[i]);
|
||||
check -= buffer[i];
|
||||
if ((i & 0x0F) == 0x0F)
|
||||
{
|
||||
fprintf(ihex, "%2.2X\r\n", check);
|
||||
if (i > 0x30) printf("\n");
|
||||
else printf(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(ihex, ":00000001FF\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to set read address.\n");
|
||||
error = -1;
|
||||
}
|
||||
fclose(ihex);
|
||||
}
|
||||
break;
|
||||
/*skip for error case*/
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
port_write_echo(port, "a01F800\r");
|
||||
bzero(buffer, sizeof(buffer));
|
||||
length = port_readline(port, buffer, sizeof(buffer), 200);
|
||||
if (length <0) length = 0;
|
||||
if(memcmp(buffer, "OK", 2) == 0)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t address = 0;
|
||||
|
||||
for (address = 0x01F800; address < 128*1024; address += 64)
|
||||
{
|
||||
|
||||
port_write_echo(port, "r\r");
|
||||
bzero(buffer, 256);
|
||||
length = 0;
|
||||
while (length < 64)
|
||||
{
|
||||
length += port_readline(port, &buffer[length], sizeof(buffer)-length, 100);
|
||||
}
|
||||
if ((address & 0xff) == 0)
|
||||
{ printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
printf("\nDevice MAC: ");
|
||||
for (i=56; i<64; i++)
|
||||
{
|
||||
if (i != 56) printf(":");
|
||||
printf("%2.2X", buffer[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
port_write_echo(port, "a01F800\r");
|
||||
bzero(buffer, sizeof(buffer));
|
||||
length = port_readline(port, buffer, sizeof(buffer), 200);
|
||||
if (length <0) length = 0;
|
||||
if(memcmp(buffer, "OK", 2) == 0)
|
||||
{
|
||||
uint8_t p_buffer[2048];
|
||||
int error;
|
||||
|
||||
memset(p_buffer, 0xff, sizeof(p_buffer));
|
||||
memcpy(&p_buffer[2040], conf->write_mac, 8);
|
||||
|
||||
printf("\rWriting MAC: ");
|
||||
error = cdi_page_write(port, 0x01F800, p_buffer);
|
||||
if (!error)
|
||||
{
|
||||
printf("Write complete.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Write failed.\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown CDI action.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Close programmer.\n");
|
||||
usleep(100000);
|
||||
port_write_echo(port, "q\r");
|
||||
programmer_close(port);
|
||||
return error;
|
||||
}
|
||||
|
||||
int cdi_write(port_t *port, conf_opts_t *conf, FILE *ihex)
|
||||
{
|
||||
int error = 0;
|
||||
unsigned char buffer[256];
|
||||
int length;
|
||||
int i;
|
||||
int pages;
|
||||
|
||||
unsigned long ext_addr=0;
|
||||
unsigned short int addr=0;
|
||||
unsigned char page_buffer[128*1024];
|
||||
unsigned char page_table[64];
|
||||
|
||||
bzero(buffer, sizeof(buffer));
|
||||
|
||||
/*initialize page data*/
|
||||
memset(page_table, 0, 64);
|
||||
memset(page_buffer, 0xFF, sizeof(page_buffer));
|
||||
pages = 0;
|
||||
|
||||
error = 0;
|
||||
|
||||
if (conf->page_mode == PAGE_UNDEFINED)
|
||||
{
|
||||
int retval;
|
||||
|
||||
while((!error) && ((retval = fscanf(ihex, "%s", buffer)) == 1) )
|
||||
{
|
||||
unsigned char data_len = 0;
|
||||
|
||||
if (memcmp(&buffer[7], "00", 2) == 0)
|
||||
{ /*Data record*/
|
||||
}
|
||||
else if (memcmp(&buffer[7], "01", 2) == 0)
|
||||
{ /*end file*/
|
||||
printf("\nFile read complete.\n");
|
||||
break;
|
||||
}
|
||||
else if (memcmp(&buffer[7], "04", 2) == 0)
|
||||
{
|
||||
sscanf((char *)&(buffer[3]),"%4hx", &addr);
|
||||
sscanf((char *)&(buffer[9]),"%4lx", &ext_addr);
|
||||
|
||||
if (ext_addr >= 0x0002)
|
||||
{
|
||||
conf->page_mode = PAGE_SDCC;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (conf->page_mode == PAGE_UNDEFINED) conf->page_mode = PAGE_LINEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retval == -1)
|
||||
{
|
||||
printf("Read error\n");
|
||||
return -1;
|
||||
}
|
||||
rewind(ihex);
|
||||
retval = 0;
|
||||
error = 0;
|
||||
}
|
||||
switch (conf->page_mode)
|
||||
{
|
||||
case PAGE_SDCC:
|
||||
printf("SDCC banked file.\n");
|
||||
break;
|
||||
case PAGE_LINEAR:
|
||||
printf("Linear banked file.\n");
|
||||
break;
|
||||
case PAGE_UNDEFINED:
|
||||
printf("Non-banked file, assuming linear.\n");
|
||||
conf->page_mode = PAGE_LINEAR;
|
||||
break;
|
||||
}
|
||||
|
||||
while( (fscanf(ihex, "%s", buffer) == 1) && !error)
|
||||
{
|
||||
unsigned char data_len = 0;
|
||||
|
||||
if (memcmp(&buffer[7], "00", 2) == 0)
|
||||
{ /*Data record*/
|
||||
i=0;
|
||||
sscanf((char *)&buffer[1], "%2hhx", &data_len);
|
||||
sscanf((char *)&(buffer[3]),"%4hx", &addr);
|
||||
while(i<data_len)
|
||||
{
|
||||
uint32_t absolute_address = ext_addr+addr+i;
|
||||
|
||||
if (page_table[absolute_address/2048] == 0)
|
||||
{
|
||||
page_table[absolute_address/2048] = 1;
|
||||
pages++;
|
||||
}
|
||||
sscanf((char *)&buffer[2*i+9], "%2hhx", &page_buffer[absolute_address]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else if (memcmp(&buffer[7], "01", 2) == 0)
|
||||
{ /*end file*/
|
||||
printf("\nFile read complete.\n");
|
||||
printf("Writing %d pages.\n", pages);
|
||||
break;
|
||||
}
|
||||
else if (memcmp(&buffer[7], "04", 2) == 0)
|
||||
{
|
||||
sscanf((char *)&(buffer[3]),"%4hx", &addr);
|
||||
sscanf((char *)&(buffer[9]),"%4lx", &ext_addr);
|
||||
if (conf->page_mode == PAGE_SDCC)
|
||||
{
|
||||
if (ext_addr) ext_addr--;
|
||||
ext_addr *= 0x8000;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_addr *= 0x10000;
|
||||
}
|
||||
printf("\rExtended page address: 0x%8.8lX\r", ext_addr);
|
||||
}
|
||||
}
|
||||
|
||||
if (pages)
|
||||
{
|
||||
int retry = 0;
|
||||
// Successfully in mode 3 (programming)
|
||||
printf("Starting programming.\n");
|
||||
error = 0;
|
||||
for (i=0; i<64; i++)
|
||||
{
|
||||
if (page_table[i] != 0)
|
||||
{
|
||||
ext_addr = 2048*i;
|
||||
|
||||
bzero(buffer, sizeof(buffer));
|
||||
|
||||
// Write the start address and check return
|
||||
usleep(3000);
|
||||
sprintf((char *)buffer, "a%6.6lX\r", ext_addr);
|
||||
port_write_echo(port, (char *)buffer);
|
||||
|
||||
if((length = port_readline(port, buffer, sizeof(buffer), 200)) < 0)
|
||||
{
|
||||
printf("Read from serial timed out without data.\n");
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(strncmp((char *)buffer, "OK\r\n", 4) == 0)
|
||||
{
|
||||
printf("\r \r");
|
||||
printf("\rWriting @ 0x%6.6lX: ", ext_addr);
|
||||
fflush(stdout);
|
||||
error = cdi_page_write(port, ext_addr, &page_buffer[ext_addr]);
|
||||
if (error)
|
||||
{
|
||||
usleep(20000);
|
||||
port_write_echo(port, "i\r");
|
||||
|
||||
bzero(buffer, 256);
|
||||
length = port_readline(port, buffer, sizeof(buffer), 100);
|
||||
|
||||
if(memcmp(buffer, "85", 2) == 0)
|
||||
{ /*Found CC2430 device*/
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Reinit failed.\n");
|
||||
error = -1;
|
||||
}
|
||||
if (retry++ < 3)
|
||||
{
|
||||
error = 0;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else retry = 0;
|
||||
fflush(stdout);
|
||||
usleep(20000);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to set CDI programming start address.\n");
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (error) break;
|
||||
}
|
||||
usleep(200000);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int cdi_page_write(port_t *port, unsigned long page_addr, unsigned char *page_buffer)
|
||||
{
|
||||
int error = 0;
|
||||
unsigned char buffer[80];
|
||||
unsigned char cmd[16];
|
||||
unsigned char block, i;
|
||||
int length;
|
||||
int retry = 0;
|
||||
|
||||
// Write page
|
||||
port_write_echo(port, "w\r");
|
||||
usleep(10000);
|
||||
for (block=0; block<(2048/64); block++)
|
||||
{
|
||||
sprintf((char *)cmd, "%6.6lX", page_addr + (64*block));
|
||||
bzero(buffer, sizeof(buffer));
|
||||
length = port_readline(port, buffer, sizeof(buffer), 2000);
|
||||
if (length <0)
|
||||
{ length = 0;
|
||||
printf("l!");fflush(stdout);
|
||||
}
|
||||
buffer[length] = 0;
|
||||
if (block & 1)
|
||||
{
|
||||
}
|
||||
if(memcmp(buffer, cmd, 6) == 0)
|
||||
{
|
||||
#define WRITE_SIZE 64
|
||||
for (i=0; i<64; i+=WRITE_SIZE)
|
||||
{
|
||||
port_write(port, &page_buffer[(unsigned int)(block*64)+i], WRITE_SIZE);
|
||||
usleep(1250);
|
||||
}
|
||||
|
||||
bzero(buffer, sizeof(buffer));
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
length = port_readline(port, buffer, sizeof(buffer), 200);
|
||||
if(memcmp(buffer, "OK", 2) == 0)
|
||||
{
|
||||
retry = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
block--;
|
||||
if (retry++ >= 8)
|
||||
{
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[length] = 0;
|
||||
printf("%s",buffer);
|
||||
port_rts_clear(port);
|
||||
usleep(300000);
|
||||
port_rts_set(port);
|
||||
bzero(buffer, sizeof(buffer));
|
||||
length = port_readline(port, buffer, sizeof(buffer), 800);
|
||||
if(memcmp(buffer, "CDI", 3) == 0)
|
||||
{
|
||||
printf("R");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
printf("w"); fflush(stdout);
|
||||
bzero(buffer, sizeof(buffer));
|
||||
length = port_readline(port, buffer, sizeof(buffer), 800);
|
||||
if(memcmp(buffer, "WROK", 4) == 0)
|
||||
{
|
||||
error = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%c%c", buffer[0], buffer[1]);
|
||||
error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) printf("OK\r");
|
||||
return error;
|
||||
}
|
||||
|
99
tools/sensinode/nano_programmer/ihex.c
Normal file
99
tools/sensinode/nano_programmer/ihex.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
int hexfile_parse(char *line, unsigned int *type, unsigned int *addr, unsigned char *buffer)
|
||||
{
|
||||
unsigned int row_len = 0;
|
||||
unsigned int row_index = 7;
|
||||
unsigned int i;
|
||||
int tmp;
|
||||
|
||||
uint8_t cksum = 0;
|
||||
int retval = 0;
|
||||
|
||||
retval = sscanf(line, ":%2x%4x%2x", &row_len, addr, type);
|
||||
|
||||
cksum += row_len;
|
||||
cksum += *addr >> 8;
|
||||
cksum += *addr & 0xFF;
|
||||
cksum += *type;
|
||||
|
||||
i = 0;
|
||||
if (retval == 3)
|
||||
{
|
||||
while(i < row_len)
|
||||
{
|
||||
|
||||
if (sscanf(&line[row_index], "%2x", &tmp) == 1)
|
||||
{
|
||||
cksum += tmp;
|
||||
buffer[i++] = (unsigned char) tmp;
|
||||
row_index += 2;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
if (sscanf(&line[row_index], "%2x", &tmp) == 1)
|
||||
{
|
||||
if ((cksum + (uint8_t) tmp) == 0) return row_len;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes)
|
||||
{
|
||||
uint8_t cksum = 0;
|
||||
uint8_t i = 0;
|
||||
char tmp[8];
|
||||
|
||||
sprintf(line, ":%2.2X%4.4X%2.2X", bytes, address, type);
|
||||
cksum -= bytes;
|
||||
cksum -= address >> 8;
|
||||
cksum -= address & 0xFF;
|
||||
cksum -= type;
|
||||
|
||||
for (i=0; i<bytes; i++)
|
||||
{
|
||||
sprintf(tmp, "%2.2X", data[i]);
|
||||
strcat(line, tmp);
|
||||
cksum -= data[i];
|
||||
}
|
||||
sprintf(tmp, "%2.2X\r\n", cksum);
|
||||
strcat(line, tmp);
|
||||
|
||||
return strlen(line);
|
||||
}
|
||||
|
36
tools/sensinode/nano_programmer/ihex.h
Normal file
36
tools/sensinode/nano_programmer/ihex.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _IHEX_H
|
||||
#define _IHEX_H
|
||||
|
||||
extern int hexfile_parse(char *line, unsigned char *type, unsigned int *addr, char *buffer);
|
||||
extern int hexfile_out(char *line, unsigned int type, unsigned int address, unsigned char *data, unsigned int bytes);
|
||||
|
||||
#endif /*_IHEX_H*/
|
371
tools/sensinode/nano_programmer/linux/port.c
Normal file
371
tools/sensinode/nano_programmer/linux/port.c
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include "port.h"
|
||||
|
||||
int port_open(port_t **port, char *device)
|
||||
{
|
||||
port_t *new_port = (port_t *) malloc(sizeof(port_t));
|
||||
char err_string[128];
|
||||
|
||||
*port = new_port;
|
||||
|
||||
new_port->device = 0;
|
||||
new_port->handle = 0;
|
||||
|
||||
new_port->handle = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
||||
|
||||
if (new_port->handle <= 0)
|
||||
{
|
||||
strerror_r(errno, err_string, 128);
|
||||
|
||||
printf("Serial port open failed with error message: %s.\n", err_string);
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcgetattr(new_port->handle, &(new_port->old_params));
|
||||
|
||||
fcntl(new_port->handle, F_SETFL, FASYNC);
|
||||
printf("Serial port %s opened succesfully.\n", device);
|
||||
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
int port_close(port_t *port)
|
||||
{
|
||||
if (!port)
|
||||
return(-1);
|
||||
|
||||
if ((port->handle) > 0)
|
||||
{
|
||||
tcflush(port->handle, TCIFLUSH);
|
||||
tcsetattr(port->handle,TCSANOW,&(port->old_params));
|
||||
|
||||
close(port->handle);
|
||||
port->handle = 0;
|
||||
}
|
||||
|
||||
if (port->device) free(port->device);
|
||||
port->device = 0;
|
||||
free(port);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/** @todo port_write() function probably needs mutexes -mjs */
|
||||
|
||||
int port_write(port_t *port, unsigned char *buffer, size_t buflen)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
if (!port) return -1;
|
||||
|
||||
/** @todo The write to serial port is at the moment done one octet at a time with 10ms interval between each write operation due to some minor problems in MCU interrupts. -mjs */
|
||||
while(i < buflen)
|
||||
{
|
||||
write(port->handle, &(buffer[i]), 1);
|
||||
tcflush(port->handle, TCIFLUSH);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* write(port->handle, &(buffer[i]), buflen);*/
|
||||
|
||||
tcflush(port->handle, TCIFLUSH);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int port_read(port_t *port, unsigned char *buffer, size_t buflen)
|
||||
{
|
||||
unsigned int l = 0;
|
||||
l = read(port->handle, buffer, buflen);
|
||||
return(l);
|
||||
}
|
||||
|
||||
int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts)
|
||||
{
|
||||
int rate = B115200;
|
||||
struct termios newtio;
|
||||
|
||||
if (!port) return -1;
|
||||
|
||||
switch (speed)
|
||||
{
|
||||
case 230400:
|
||||
rate = B230400;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 115200:
|
||||
rate = B115200;
|
||||
break;
|
||||
|
||||
case 57600:
|
||||
rate = B57600;
|
||||
break;
|
||||
|
||||
case 38400:
|
||||
rate = B38400;
|
||||
break;
|
||||
|
||||
case 19200:
|
||||
rate = B19200;
|
||||
break;
|
||||
|
||||
case 9600:
|
||||
rate = B9600;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
||||
}
|
||||
bzero(&newtio, sizeof(newtio));
|
||||
|
||||
if (speed == 9600)
|
||||
{
|
||||
newtio.c_cflag |= CS8 | CSTOPB | CLOCAL | CREAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
newtio.c_cflag |= CS8 | CLOCAL | CREAD;
|
||||
}
|
||||
if (rtscts)
|
||||
{
|
||||
newtio.c_cflag |= CRTSCTS;
|
||||
}
|
||||
newtio.c_iflag = IGNPAR;
|
||||
|
||||
cfsetispeed(&newtio, rate);
|
||||
cfsetospeed(&newtio, rate);
|
||||
|
||||
newtio.c_cc[VTIME] = 0;
|
||||
newtio.c_cc[VMIN] = 1;
|
||||
|
||||
#if 0
|
||||
newtio.c_cflag = rate | CS8 | CLOCAL | CREAD | CSTOPB;
|
||||
/* if (rts_cts) newtio.c_cflag |= CRTSCTS;*/
|
||||
|
||||
newtio.c_iflag = IGNPAR;
|
||||
newtio.c_oflag = 0;
|
||||
|
||||
newtio.c_lflag = 0;
|
||||
|
||||
newtio.c_cc[VTIME] = 0;
|
||||
newtio.c_cc[VMIN] = 1;
|
||||
#endif
|
||||
|
||||
tcflush(port->handle, TCIFLUSH);
|
||||
tcsetattr(port->handle,TCSANOW,&newtio);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int port_dtr_set(port_t *port)
|
||||
{
|
||||
int port_state = TIOCM_DTR;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
/* error = ioctl(port->handle, TIOCMGET, &port_state);
|
||||
port_state |= TIOCM_RTS;
|
||||
ioctl(port->handle, TIOCMSET, &port_state);*/
|
||||
|
||||
ioctl(port->handle, TIOCMBIS, &port_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_dtr_clear(port_t *port)
|
||||
{
|
||||
int port_state = TIOCM_DTR;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
ioctl(port->handle, TIOCMBIC, &port_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_rts_set(port_t *port)
|
||||
{
|
||||
int port_state = TIOCM_RTS;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
ioctl(port->handle, TIOCMBIS, &port_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_rts_clear(port_t *port)
|
||||
{
|
||||
int port_state = TIOCM_RTS;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
ioctl(port->handle, TIOCMBIC, &port_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_get(port_t *port, unsigned char *buffer, int timeout)
|
||||
{
|
||||
struct pollfd pfds;
|
||||
unsigned int nfds = 1;
|
||||
int bytes = 0;
|
||||
int rval;
|
||||
|
||||
pfds.fd = (int)(port->handle);
|
||||
pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
||||
|
||||
rval = poll(&pfds, nfds, timeout);
|
||||
|
||||
if((rval & POLLIN) != POLLIN)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = port_read(port, buffer, 1);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout)
|
||||
{
|
||||
int length = 0;
|
||||
struct pollfd pfds;
|
||||
unsigned int nfds = 1;
|
||||
int bytes = 0;
|
||||
int rval;
|
||||
|
||||
pfds.fd = (int)(port->handle);
|
||||
pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
||||
|
||||
do
|
||||
{
|
||||
rval = poll(&pfds, nfds, timeout);
|
||||
if((rval & POLLIN) != POLLIN)
|
||||
{
|
||||
return(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = port_read(port, &(buffer[length]), 1);
|
||||
if (buffer[length] == '\n')
|
||||
{
|
||||
buf_size = length;
|
||||
}
|
||||
length += bytes;
|
||||
}
|
||||
|
||||
}while(length < buf_size);
|
||||
|
||||
buffer[length] = 0;
|
||||
|
||||
if(length != 0)
|
||||
return length;
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int port_write_echo(port_t *port, char *string)
|
||||
{
|
||||
int length = 0;
|
||||
int retry = 0;
|
||||
unsigned char byte;
|
||||
|
||||
while( (string[length]) && (retry < 100) )
|
||||
{
|
||||
port_write(port, (unsigned char *) &string[length], 1);
|
||||
while (retry++ < 100)
|
||||
{
|
||||
if (port_read(port, &byte, 1) == 1)
|
||||
{
|
||||
/* printf("%c",byte);*/
|
||||
if (byte == string[length])
|
||||
{
|
||||
retry = 0;
|
||||
length++;
|
||||
break;
|
||||
}
|
||||
else retry = 100;
|
||||
}
|
||||
else usleep(1000);
|
||||
}
|
||||
}
|
||||
if ((string[strlen(string)-1] == '\r') && (retry < 100) )
|
||||
{ /*wait for \n*/
|
||||
retry = 0;
|
||||
while (retry++ < 100)
|
||||
{
|
||||
if (port_read(port, &byte, 1) == 1)
|
||||
{
|
||||
/* printf("%c",byte);*/
|
||||
break;
|
||||
}
|
||||
else usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry >= 100) return 0;
|
||||
else return length;
|
||||
}
|
||||
|
||||
|
||||
int port_write_8byte_no_echo(port_t *port, int dlen, char *string)
|
||||
{
|
||||
int length = 0;
|
||||
int total_len;
|
||||
int wrbytes = 4;
|
||||
|
||||
total_len = dlen;
|
||||
|
||||
/* printf("total: %d, length: %d, dlen: %d.\n", total_len, length, dlen); */
|
||||
while(total_len > length)
|
||||
{
|
||||
if((total_len - length) >= wrbytes)
|
||||
{
|
||||
port_write(port, (unsigned char *)&string[length], wrbytes);
|
||||
length += wrbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
port_write(port, (unsigned char *)&string[length], total_len - length);
|
||||
length += total_len - length;
|
||||
}
|
||||
usleep(1250);
|
||||
|
||||
}
|
||||
|
||||
return(length);
|
||||
}
|
||||
|
BIN
tools/sensinode/nano_programmer/nano_programmer
Executable file
BIN
tools/sensinode/nano_programmer/nano_programmer
Executable file
Binary file not shown.
94
tools/sensinode/nano_programmer/port.h
Normal file
94
tools/sensinode/nano_programmer/port.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _PORT_H
|
||||
#define _PORT_H
|
||||
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
#include "windows.h"
|
||||
#include <stdint.h>
|
||||
#include "ftd2xx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
typedef struct
|
||||
{
|
||||
int handle;
|
||||
char *device;
|
||||
struct termios old_params;
|
||||
}port_t;
|
||||
|
||||
extern int port_open(port_t **port, char *device);
|
||||
#else
|
||||
typedef struct port_t
|
||||
{
|
||||
FT_HANDLE handle;
|
||||
int device;
|
||||
HANDLE event_handle;
|
||||
}port_t;
|
||||
|
||||
extern int port_open(port_t **port, int device);
|
||||
#endif
|
||||
|
||||
extern int port_close(port_t *port);
|
||||
extern int port_write(port_t *port, unsigned char *buffer, size_t buflen);
|
||||
extern int port_read(port_t *port, unsigned char *buffer, size_t buflen);
|
||||
extern int port_get(port_t *port, unsigned char *buffer, int timeout);
|
||||
extern int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts);
|
||||
extern int port_dtr_set(port_t *port);
|
||||
extern int port_dtr_clear(port_t *port);
|
||||
extern int port_rts_set(port_t *port);
|
||||
extern int port_rts_clear(port_t *port);
|
||||
extern int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout);
|
||||
extern int port_write_echo(port_t *port, char *string);
|
||||
extern int port_write_8byte_no_echo(port_t *port, int dlen, char *string);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _PORT_H */
|
440
tools/sensinode/nano_programmer/programmer.c
Normal file
440
tools/sensinode/nano_programmer/programmer.c
Normal file
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "programmer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern int cdi_programmer(conf_opts_t *conf, char *filename);
|
||||
|
||||
void usage(char *prg_name)
|
||||
{
|
||||
printf("\nUsage: %s [-d device]\n", prg_name);
|
||||
printf("General options:\n");
|
||||
printf(" -V/--version Get programmer version\n");
|
||||
printf(" -1/--d100 Use D100 board (default D200)\n");
|
||||
printf("Operating modes:\n");
|
||||
printf(" -b/--bios to get programmer BIOS version\n");
|
||||
printf(" -P/--program [ihex file] Do a complete programming sequence (write and verify)\n");
|
||||
printf(" -v/--verify [ihex file] Verify against ihex file\n");
|
||||
printf(" -r/--read [ihex file] Read program code into ihex file\n");
|
||||
printf(" -m/--mac Read device MAC address\n");
|
||||
printf(" -Q/--write-mac [MAC address] Write device MAC address\n");
|
||||
printf(" -e/--erase Erase flash (erases MAC address!)\n");
|
||||
printf("Programming options:\n");
|
||||
printf(" -l/--linear Force linear model for extended addresses (not SDCC file)\n");
|
||||
printf(" -s/--sdcc Force SDCC model for extended addresses (SDCC file)\n");
|
||||
printf("Defaults:\n");
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
printf("device /dev/ttyUSB0\n");
|
||||
#else
|
||||
printf("device 0\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
conf_opts_t conf_opts;
|
||||
|
||||
static int option_index = 0;
|
||||
|
||||
int do_exit = 0;
|
||||
|
||||
#define OPTIONS_STRING "d:ec1lsmVbP:v:r:Q:"
|
||||
/* long option list */
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"device", 1, NULL, 'd'},
|
||||
{"psoc", 0, NULL, 'p'},
|
||||
{"d100", 0, NULL, '1'},
|
||||
{"erase", 0, NULL, 'e'},
|
||||
{"mac", 0, NULL, 'm'},
|
||||
{"linear", 0, NULL, 'l'},
|
||||
{"sdcc", 0, NULL, 's'},
|
||||
{"cdi", 0, NULL, 'c'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
{"bios", 0, NULL, 'b'},
|
||||
{"program", 1, NULL, 'P'},
|
||||
{"verify", 1, NULL, 'v'},
|
||||
{"read", 1, NULL, 'r'},
|
||||
{"write-mac", 1, NULL, 'Q'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int parse_opts(int count, char* param[])
|
||||
{
|
||||
int opt;
|
||||
int error=0;
|
||||
|
||||
conf_opts.target_type = CDI;
|
||||
while ((opt = getopt_long(count, param, OPTIONS_STRING,
|
||||
long_options, &option_index)) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'V':
|
||||
conf_opts.target_type = VERSION;
|
||||
break;
|
||||
|
||||
case '1':
|
||||
conf_opts.prg_type = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
conf_opts.target_type = CDI;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
if (sscanf(optarg, "%d", &conf_opts.device) != 1)
|
||||
{
|
||||
printf("Device ID must be a positive integer.\n");
|
||||
conf_opts.action = ' ';
|
||||
}
|
||||
#else
|
||||
printf("device:%s\n", optarg);
|
||||
strcpy(conf_opts.device, optarg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
printf("Programming mode.\n");
|
||||
conf_opts.action = 'P';
|
||||
strcpy(conf_opts.ihex_file, optarg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (conf_opts.page_mode == PAGE_UNDEFINED)
|
||||
{
|
||||
conf_opts.page_mode = PAGE_SDCC;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Only one paging option allowed.\n");
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (conf_opts.page_mode == PAGE_UNDEFINED)
|
||||
{
|
||||
conf_opts.page_mode = PAGE_LINEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Only one paging option allowed.\n");
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
printf("Erase.\n");
|
||||
conf_opts.action = 'e';
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
printf("Get MAC.\n");
|
||||
conf_opts.action = 'm';
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf("Get BIOS version\n");
|
||||
conf_opts.action = 'b';
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
printf("Write MAC.\n");
|
||||
conf_opts.action = 'Q';
|
||||
if (sscanf(optarg, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&conf_opts.write_mac[0], &conf_opts.write_mac[1],
|
||||
&conf_opts.write_mac[2], &conf_opts.write_mac[3],
|
||||
&conf_opts.write_mac[4], &conf_opts.write_mac[5],
|
||||
&conf_opts.write_mac[6], &conf_opts.write_mac[7]) != 8)
|
||||
{
|
||||
printf("Invalid MAC.\n");
|
||||
conf_opts.action = ' ';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
printf("Verify by comparing to ihex file:%s\n", optarg);
|
||||
conf_opts.action = 'v';
|
||||
strcpy(conf_opts.ihex_file, optarg);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
printf("Read program to ihex file:%s\n", optarg);
|
||||
conf_opts.action = 'r';
|
||||
strcpy(conf_opts.ihex_file, optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
printf("Duh\n");
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error && (conf_opts.target_type == CDI) )
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
printf("Setup: Device %d.\n", conf_opts.device);
|
||||
#else
|
||||
printf("Setup: Device %s.\n", conf_opts.device);
|
||||
#endif
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
/*
|
||||
int port_write_8byte_echo(port_t *port, char *string)
|
||||
{
|
||||
int length = 0;
|
||||
int total_len;
|
||||
int i, j;
|
||||
struct pollfd pfds;
|
||||
unsigned int nfds = 1;
|
||||
int rval = 0;
|
||||
|
||||
int wrbytes = 2;
|
||||
unsigned char byte8[wrbytes];
|
||||
|
||||
pfds.fd = (int)(port->handle);
|
||||
pfds.events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
||||
|
||||
total_len = strlen(string);
|
||||
|
||||
while(total_len > length)
|
||||
{
|
||||
if(total_len - length >= wrbytes)
|
||||
{
|
||||
i=0;
|
||||
port_write(port, (unsigned char *)&string[length], wrbytes);
|
||||
|
||||
if((rval = poll(&pfds, nfds, 100)) == 0)
|
||||
{
|
||||
printf("Timed out...\n");
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
while(i<wrbytes)
|
||||
{
|
||||
i += port_read(port, &byte8[i], wrbytes);
|
||||
}
|
||||
|
||||
if(i != wrbytes || memcmp(byte8, &string[length], wrbytes) != 0)
|
||||
{
|
||||
printf("Got wrong length (%d) or wrong bytes back.\n", i);
|
||||
for(j=0;j<wrbytes;j++)
|
||||
{
|
||||
printf("%.2x <-> %.2x\n", string[length+j], byte8[j]);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("8Bwok - ");
|
||||
fflush(stdout);
|
||||
length += wrbytes;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i=0;
|
||||
port_write(port, (unsigned char *)&string[length], total_len - length);
|
||||
|
||||
if((rval = poll(&pfds, nfds, 100)) == 0)
|
||||
{
|
||||
printf("Timed out...\n");
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
while(i<(total_len-length))
|
||||
{
|
||||
i = port_read(port, &byte8[i], total_len - length);
|
||||
}
|
||||
if(i != total_len - length || memcmp(byte8, &string[length], total_len - length) != 0)
|
||||
{
|
||||
printf("Got wrong length or wrong bytes back.\n");
|
||||
for(j=0;j<total_len - length;j++)
|
||||
{
|
||||
printf("%.2x <-> %.2x\n", string[length+j], byte8[j]);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("<8Bwok - \n");
|
||||
fflush(stdout);
|
||||
length += (total_len - length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usleep(5000);
|
||||
|
||||
}
|
||||
|
||||
return(length);
|
||||
}
|
||||
*/
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
int programmer_init(int device, port_t **port)
|
||||
#else
|
||||
int programmer_init(char *device, port_t **port)
|
||||
#endif
|
||||
{
|
||||
int error = port_open(port, device);
|
||||
uint8_t buffer[8];
|
||||
|
||||
buffer[0] = 0;
|
||||
|
||||
if (error >= 0)
|
||||
{
|
||||
if (conf_opts.prg_type == 1)
|
||||
{
|
||||
int retry = 0;
|
||||
port_set_params(*port, 9600, 0);
|
||||
// Activate programming...
|
||||
port_dtr_clear(*port);
|
||||
port_rts_clear(*port);
|
||||
sleep(1);
|
||||
printf("Select D100.\n");
|
||||
port_rts_set(*port);
|
||||
sleep(1);
|
||||
buffer[0] = '\r';
|
||||
while (retry++ < 3)
|
||||
{
|
||||
int length;
|
||||
port_write_echo(*port, "q\r");
|
||||
length = port_readline(*port, buffer, sizeof(buffer), 800);
|
||||
if (length)
|
||||
{
|
||||
if (*buffer == '!')
|
||||
{
|
||||
printf("D100 found.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("No programmer found.\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
port_set_params(*port, 57600, 0);
|
||||
// Activate programming...
|
||||
port_dtr_clear(*port);
|
||||
port_rts_clear(*port);
|
||||
usleep(300000);
|
||||
printf("Select D200.\n");
|
||||
port_rts_set(*port);
|
||||
usleep(200000);
|
||||
port_set_params(*port, 57600, 1);
|
||||
port_write(*port, (uint8_t *)"\r", 1);
|
||||
usleep(100000);
|
||||
if ((port_get(*port, buffer, 500) >= 1) && (buffer[0] == '!'))
|
||||
{
|
||||
printf("D200 found.\n");
|
||||
return 0;
|
||||
}
|
||||
printf("No programmer found.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void programmer_close(port_t *port)
|
||||
{
|
||||
if (port)
|
||||
{
|
||||
port_rts_clear(port);
|
||||
port_dtr_set(port);
|
||||
sleep(1);
|
||||
port_close(port);
|
||||
printf("Port closed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
conf_opts.target_type = 0;
|
||||
conf_opts.action = 0;
|
||||
conf_opts.prg_type = 2;
|
||||
|
||||
|
||||
#ifndef PLATFORM_WINDOWS
|
||||
strncpy(conf_opts.device, "/dev/ttyUSB0", 12);
|
||||
/* Install a new handler for SIGIO.
|
||||
*
|
||||
* According to man 7 signal this signal is by default ignored by most systems.
|
||||
* It seems that pre FC7 this was true for Fedoras also. We have noticed that at least
|
||||
* on some FC7 installations the default action has changed. We avoid abnormal program
|
||||
* exits by defining the SIGIO as SIG_IGN (ignore). - mjs
|
||||
*/
|
||||
if(signal(SIGIO, SIG_IGN) == SIG_ERR)
|
||||
{
|
||||
printf("%s error: failed to install SIGIO handler. Exit.\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
conf_opts.device = 0;
|
||||
#endif
|
||||
|
||||
conf_opts.page_mode = PAGE_UNDEFINED;
|
||||
|
||||
if ( (argc <= 1) || (error = parse_opts(argc, argv)) )
|
||||
{
|
||||
usage(argv[0]);
|
||||
if (error < 0) return error;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
if(conf_opts.target_type == CDI)
|
||||
{ /*CDI*/
|
||||
error = cdi_programmer(&conf_opts, conf_opts.ihex_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\nSensinode Nano series programmer "PROGRAMMER_VERSION "\n");
|
||||
}
|
||||
return error;
|
||||
}
|
62
tools/sensinode/nano_programmer/programmer.h
Normal file
62
tools/sensinode/nano_programmer/programmer.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#define PROGRAMMER_VERSION "v1.3"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PAGE_SDCC,
|
||||
PAGE_LINEAR,
|
||||
PAGE_UNDEFINED
|
||||
}page_mode_t;
|
||||
|
||||
typedef struct {
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
int device;
|
||||
#else
|
||||
char device[128];
|
||||
#endif
|
||||
int target_type;
|
||||
int prg_type;
|
||||
int action;
|
||||
char ihex_file[128];
|
||||
unsigned char write_mac[8];
|
||||
page_mode_t page_mode;
|
||||
}conf_opts_t;
|
||||
|
||||
enum target { UNDEFINED, VERSION, CDI };
|
||||
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
extern int programmer_init(int device, port_t **port);
|
||||
#else
|
||||
extern int programmer_init(char *device, port_t **port);
|
||||
#endif
|
||||
|
||||
extern void programmer_close(port_t *port);
|
||||
|
383
tools/sensinode/nano_programmer/windows/port.c
Normal file
383
tools/sensinode/nano_programmer/windows/port.c
Normal file
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
|
||||
|
||||
Copyright (C) 2006-2007 Sensinode Ltd.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Address:
|
||||
Sensinode Ltd.
|
||||
Teknologiantie 6
|
||||
90570 Oulu, Finland
|
||||
|
||||
E-mail:
|
||||
info@sensinode.com
|
||||
*/
|
||||
|
||||
|
||||
#include "port.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int port_open(port_t **port, int device)
|
||||
{
|
||||
port_t *new_port = (port_t *) malloc(sizeof(port_t));
|
||||
FT_STATUS status;
|
||||
|
||||
*port = new_port;
|
||||
|
||||
new_port->device = device;
|
||||
new_port->handle = 0;
|
||||
|
||||
status = FT_Open(device, &(new_port->handle));
|
||||
|
||||
if (status != FT_OK)
|
||||
{
|
||||
new_port->handle = 0;
|
||||
|
||||
printf("Serial port open failed with error message: %d.\n", (int)status);
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD mask;
|
||||
new_port->event_handle = CreateEvent(NULL, TRUE, FALSE, "SN_USB_UART_EVENTS");
|
||||
if (new_port->event_handle == NULL)
|
||||
{
|
||||
printf("Event handle creation failed.\n");
|
||||
FT_Close(new_port->handle);
|
||||
new_port->handle = 0;
|
||||
return(-1);
|
||||
}
|
||||
mask = FT_EVENT_RXCHAR | FT_EVENT_MODEM_STATUS;
|
||||
status = FT_SetEventNotification(new_port->handle,mask,new_port->event_handle);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
printf("Setting event notification failed.\n");
|
||||
}
|
||||
FT_SetTimeouts(new_port->handle,400,0);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
int port_close(port_t *port)
|
||||
{
|
||||
if (!port)
|
||||
return(-1);
|
||||
|
||||
if ((port->event_handle) != NULL)
|
||||
{
|
||||
CloseHandle(port->event_handle);
|
||||
port->event_handle = NULL;
|
||||
|
||||
FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX);
|
||||
FT_Close(port->handle);
|
||||
port->handle = 0;
|
||||
}
|
||||
|
||||
port->device = 0;
|
||||
free(port);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
int port_set_params(port_t *port, uint32_t speed, uint8_t rtscts)
|
||||
{
|
||||
FT_STATUS status;
|
||||
|
||||
if (!port) return -1;
|
||||
status = FT_SetBaudRate (port->handle, speed);
|
||||
if (status != FT_OK) return -1;
|
||||
if (speed == 9600)
|
||||
{
|
||||
status = FT_SetDataCharacteristics(port->handle, FT_BITS_8, FT_STOP_BITS_2, FT_PARITY_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = FT_SetDataCharacteristics(port->handle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
|
||||
}
|
||||
|
||||
if (status != FT_OK) return -1;
|
||||
|
||||
if (rtscts)
|
||||
{
|
||||
status = FT_SetFlowControl(port->handle, FT_FLOW_RTS_CTS, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = FT_SetFlowControl(port->handle, FT_FLOW_NONE, 0, 0);
|
||||
}
|
||||
|
||||
if (status != FT_OK) return -1;
|
||||
|
||||
FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int port_dtr_set(port_t *port)
|
||||
{
|
||||
FT_STATUS status;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
status = FT_SetDtr(port->handle);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
printf("Control failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_dtr_clear(port_t *port)
|
||||
{
|
||||
FT_STATUS status;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
status = FT_ClrDtr(port->handle);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
printf("Control failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_rts_set(port_t *port)
|
||||
{
|
||||
FT_STATUS status;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
status = FT_SetRts(port->handle);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
printf("Control failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_rts_clear(port_t *port)
|
||||
{
|
||||
FT_STATUS status;
|
||||
|
||||
if (!port) return(-1);
|
||||
|
||||
status = FT_ClrRts(port->handle);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
printf("Control failed.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_write(port_t *port, unsigned char *buffer, size_t buflen)
|
||||
{
|
||||
FT_STATUS status;
|
||||
DWORD bytes_out;
|
||||
|
||||
if (!port) return -1;
|
||||
|
||||
// FT_Purge(port->handle, FT_PURGE_RX);
|
||||
|
||||
status = FT_Write (port->handle, (LPVOID) buffer, (DWORD) buflen,&bytes_out);
|
||||
if (status != FT_OK) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_read(port_t *port, unsigned char *buffer, size_t buflen)
|
||||
{
|
||||
DWORD l = 0;
|
||||
FT_STATUS status;
|
||||
status = FT_Read(port->handle, buffer, buflen, &l);
|
||||
return((int) l);
|
||||
}
|
||||
|
||||
int port_get(port_t *port, unsigned char *buffer, int timeout)
|
||||
{
|
||||
DWORD bytes = 0;
|
||||
FT_STATUS status;
|
||||
|
||||
FT_SetTimeouts(port->handle, timeout, 0);
|
||||
|
||||
status = FT_Read(port->handle, buffer, 1, &bytes);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int port_readline(port_t *port, unsigned char *buffer, int buf_size, int timeout)
|
||||
{
|
||||
int length = 0;
|
||||
DWORD bytes = 0;
|
||||
FT_STATUS status;
|
||||
|
||||
FT_SetTimeouts(port->handle, timeout, 0);
|
||||
|
||||
do
|
||||
{
|
||||
status = FT_Read(port->handle, &buffer[length], 1, &bytes);
|
||||
length += bytes;
|
||||
if ((status != FT_OK) || (bytes == 0))
|
||||
{
|
||||
return(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffer[length-1] == '\n')
|
||||
{
|
||||
buf_size = length;
|
||||
}
|
||||
}
|
||||
}while(length < buf_size);
|
||||
|
||||
buffer[length] = 0;
|
||||
|
||||
if(length != 0)
|
||||
return length;
|
||||
else
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int port_write_echo(port_t *port, char *string)
|
||||
{
|
||||
int length = 0;
|
||||
int retry = 0;
|
||||
unsigned char byte;
|
||||
DWORD bytes_out;
|
||||
FT_STATUS status;
|
||||
|
||||
FT_Purge(port->handle, FT_PURGE_RX | FT_PURGE_TX);
|
||||
|
||||
while( (string[length]) && (retry < 100) )
|
||||
{
|
||||
retry = 0;
|
||||
while (retry++ < 100)
|
||||
{
|
||||
status = FT_Write (port->handle, (LPVOID) &string[length], (DWORD) 1,&bytes_out);
|
||||
if (status != FT_OK) return -1;
|
||||
if (port_get(port, &byte, 1000) == 1)
|
||||
{
|
||||
/* printf("%c",byte);*/
|
||||
if (byte == string[length])
|
||||
{
|
||||
retry = 0;
|
||||
length++;
|
||||
break;
|
||||
}
|
||||
else retry = 100;
|
||||
}
|
||||
else usleep(500);
|
||||
}
|
||||
}
|
||||
if ((string[strlen(string)-1] == '\r') && (retry < 100) )
|
||||
{ /*wait for \n*/
|
||||
retry = 0;
|
||||
while (retry++ < 100)
|
||||
{
|
||||
if (port_get(port, &byte, 1000) == 1)
|
||||
{
|
||||
/* printf("%c",byte);*/
|
||||
break;
|
||||
}
|
||||
else usleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry >= 100) return 0;
|
||||
else return length;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
int port_write_echo(port_t *port, char *string)
|
||||
{
|
||||
int length = 0;
|
||||
int retry = 0;
|
||||
unsigned char byte;
|
||||
|
||||
while( (string[length]) && (retry < 100) )
|
||||
{
|
||||
port_write(port, (unsigned char *) &string[length], 1);
|
||||
while (retry++ < 100)
|
||||
{
|
||||
if (port_read(port, &byte, 1) == 1)
|
||||
{
|
||||
/* printf("%c",byte);*/
|
||||
if (byte == string[length])
|
||||
{
|
||||
retry = 0;
|
||||
length++;
|
||||
break;
|
||||
}
|
||||
else retry = 100;
|
||||
}
|
||||
else usleep(1000);
|
||||
}
|
||||
}
|
||||
if ((string[strlen(string)-1] == '\r') && (retry < 100) )
|
||||
{ /*wait for \n*/
|
||||
retry = 0;
|
||||
while (retry++ < 100)
|
||||
{
|
||||
if (port_read(port, &byte, 1) == 1)
|
||||
{
|
||||
/* printf("%c",byte);*/
|
||||
break;
|
||||
}
|
||||
else usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry >= 100) return 0;
|
||||
else return length;
|
||||
}
|
||||
|
||||
|
||||
int port_write_8byte_no_echo(port_t *port, int dlen, char *string)
|
||||
{
|
||||
int length = 0;
|
||||
int total_len;
|
||||
int wrbytes = 4;
|
||||
|
||||
total_len = dlen;
|
||||
|
||||
/* printf("total: %d, length: %d, dlen: %d.\n", total_len, length, dlen); */
|
||||
while(total_len > length)
|
||||
{
|
||||
if((total_len - length) >= wrbytes)
|
||||
{
|
||||
port_write(port, (unsigned char *)&string[length], wrbytes);
|
||||
length += wrbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
port_write(port, (unsigned char *)&string[length], total_len - length);
|
||||
length += total_len - length;
|
||||
}
|
||||
usleep(1250);
|
||||
|
||||
}
|
||||
|
||||
return(length);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue