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

373 lines
7.7 KiB
C

/*
NanoStack: MCU software and PC tools for IP-based wireless sensor networking.
Copyright (C) 2006-2007 Sensinode Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Address:
Sensinode Ltd.
Teknologiantie 6
90570 Oulu, Finland
E-mail:
info@sensinode.com
*/
#include <stdio.h>
#include <inttypes.h>
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#endif
#include <ftd2xx.h>
FT_HANDLE curr_handle = 0;
uint8_t curr_mode = 0; /* 0 = in, 1=out */
/*
* This function checks if the CBUS2 ise set to SLEEP and modifies it if necessary.
* The CBUS2 must be set to sleep in order the programming to succeed.
*/
int check_cbus2(FT_HANDLE fthandle)
{
FT_PROGRAM_DATA eeprom_data;
char manufacturer_buf[32];
char manufacturer_id[16];
char description_buf[64];
char serialnumber_buf[16];
eeprom_data.Signature1 = 0x00000000; // This is a given value from the FT232R programming guide
eeprom_data.Signature2 = 0xffffffff; // This is a given value from the FT232R programming guide
eeprom_data.Version = 0x00000002; // This is a given value from the FT232R programming guide
eeprom_data.Manufacturer = manufacturer_buf;
eeprom_data.ManufacturerId = manufacturer_id;
eeprom_data.Description = description_buf;
eeprom_data.SerialNumber = serialnumber_buf;
if(FT_EE_Read(fthandle, &eeprom_data) != FT_OK)
{
printf("FTDI EEPROM read failed.\n");
return(-1);
}
if(eeprom_data.Cbus2 != 0x05)
{
printf("Need to re-program the CBUS2 to 0x05\n");
eeprom_data.Cbus2 = 0x05;
if(FT_EE_Program(fthandle, &eeprom_data) != FT_OK)
{
printf("FTDI EEPROM program error.\n");
return(-1);
}
else
{
printf("FTDI EEPROM program ok\n");
return(1);
}
}
else
{
return(1);
}
return(1);
}
void prog_scan(void)
{
FT_STATUS ftStatus;
FT_DEVICE_LIST_INFO_NODE *info;
unsigned long n_devices = 0;
uint8_t out;
ftStatus = FT_CreateDeviceInfoList(&n_devices);
if (ftStatus == FT_OK)
{
FT_DEVICE_LIST_INFO_NODE devices[n_devices];
ftStatus = FT_GetDeviceInfoList(devices,&n_devices);
if (ftStatus == FT_OK)
{
for (out = 0; out < n_devices; out++)
{
printf("Dev %d:",n_devices - out -1);
printf(" Type=0x%x",devices[n_devices - out -1].Type);
printf(" SerialNumber=%s",devices[n_devices - out -1].SerialNumber);
printf(" Description=%s\n",devices[n_devices - out -1].Description);
}
}
else
{
printf("Failed to fetch device list.\n");
}
}
else
{
printf("Failed to fetch device list.\n");
}
}
FT_HANDLE prog_open(int iport)
{
FT_HANDLE ftHandle;
FT_STATUS ftStatus;
FT_DEVICE_LIST_INFO_NODE *info;
unsigned long n_devices = 0;
uint8_t out;
if (curr_handle) return 0;
ftStatus = FT_CreateDeviceInfoList(&n_devices);
if (ftStatus == FT_OK)
{
FT_DEVICE_LIST_INFO_NODE devices[n_devices];
ftStatus = FT_GetDeviceInfoList(devices,&n_devices);
if (ftStatus == FT_OK)
{
iport = n_devices - iport - 1;
if (iport < 0)
{
printf("Invalid port id.\n");
for (out = 0; out < n_devices; out++)
{
printf("Dev %d:",n_devices - out -1);
printf(" Type=0x%x",devices[n_devices - out -1].Type);
printf(" SerialNumber=%s",devices[n_devices - out -1].SerialNumber);
printf(" Description=%s\n",devices[n_devices - out -1].Description);
}
return 0;
}
}
}
ftStatus = FT_Open(iport, &ftHandle);
if(ftStatus != FT_OK) {
/*
This can fail if the ftdi_sio driver is loaded
use lsmod to check this and rmmod ftdi_sio to remove
also rmmod usbserial
*/
printf("FT_Open(%d) failed\n", iport);
return 0;
}
if(check_cbus2(ftHandle) < 0)
{
printf("Nano USB Programmer exiting...\n");
return(0);
}
FT_ResetDevice(ftHandle);
FT_SetBaudRate(ftHandle, 115200);
FT_SetUSBParameters(ftHandle, 64, 0);
out = 0x04;
ftStatus = FT_SetBitMode(ftHandle, out, 0x20);
if (ftStatus == FT_OK)
{
ftStatus = FT_SetLatencyTimer(ftHandle, 2);
}
if (ftStatus == FT_OK)
{
DWORD bytes;
out = 0xE0;
ftStatus = FT_SetBitMode(ftHandle, out, 0x04);
out = 0x80;
FT_Write(ftHandle, &out, 1, &bytes); /*write reset high*/
FT_Read(ftHandle, &out, 1, &bytes); /*read out*/
curr_mode = 1;
}
if (ftStatus != FT_OK)
{
printf("Failed to set CBUS2/bit bang mode.\n");
FT_ResetDevice(ftHandle);
sleep(3);
FT_Close(ftHandle);
ftHandle = 0;
}
curr_handle = ftHandle;
return ftHandle;
}
void prog_close(void)
{
FT_STATUS ftStatus;
DWORD bytes;
if (curr_handle)
{
FT_HANDLE ftHandle = curr_handle;
uint8_t out = 0x00;
FT_Write(ftHandle, &out, 1, &bytes); /*write reset low*/
FT_Read(ftHandle, &out, 1, &bytes); /*read out*/
sleep(1);
out = 0x80;
FT_Write(ftHandle, &out, 1, &bytes); /*write reset high*/
FT_Read(ftHandle, &out, 1, &bytes); /*read out*/
sleep(1);
out = 0x00;
ftStatus = FT_SetBitMode(ftHandle, out, 0x04);
FT_ResetDevice(ftHandle);
FT_Close(ftHandle);
ftHandle = 0;
curr_handle = ftHandle;
}
}
int prog_write(uint8_t byte)
{
FT_STATUS ftStatus;
uint8_t out[16];
uint8_t mask = 0x80;
int i;
DWORD bytes;
if (curr_mode == 0)
{
out[0] = 0xE0;
ftStatus = FT_SetBitMode(curr_handle, out[0], 0x04); /*Set DD as output*/
if (ftStatus != FT_OK)
{ printf("!WR");
fflush(stdout);
return -1;
}
curr_mode = 1;
}
i = 0;
while (mask)
{
out[i] = 0xC0; /*clock high, reset high*/
if (byte & mask) out[i] |= 0x20;
i++;
out[i] = 0x80; /*clock low, reset high*/
if (byte & mask) out[i] |= 0x20;
i++;
mask >>= 1;
}
ftStatus = FT_Write(curr_handle, out, 16, &bytes); /*write clock high and data bit*/
if (ftStatus != FT_OK)
{
printf("!W");
fflush(stdout);
return -1;
}
if(FT_Read(curr_handle, out, 16, &bytes) != FT_OK)
{
printf("!R");
return(-1);
}
return 0;
}
int prog_read(uint8_t *byte)
{
FT_STATUS ftStatus;
uint8_t rd;
uint8_t mask = 0x80;
DWORD bytes;
uint8_t out[17];
uint8_t i=0;
*byte = 0;
if (curr_mode == 1)
{
out[0] = 0xC0;
ftStatus = FT_SetBitMode(curr_handle, out[0], 0x04); /*Set DD as input*/
if (ftStatus != FT_OK)
{ printf("!RD");
fflush(stdout);
return -1;
}
curr_mode = 0;
}
while (mask)
{
out[i] = 0xC0; /*clock high, reset high*/
if (*byte & mask) out[i] |= 0x20;
i++;
out[i] = 0x80; /*clock low, reset high*/
if (*byte & mask) out[i] |= 0x20;
i++;
mask >>= 1;
}
out[16] = out[15];
ftStatus = FT_Write(curr_handle, out, 17, &bytes); /*write clock high and data bit*/
if(FT_Read(curr_handle, out, 17, &bytes) != FT_OK)
{
printf("!R");
return(-1);
}
mask = 0x80;
i = 1;
while (mask)
{
if (out[i] & 0x20) *byte |= mask;
mask >>= 1;
i+=2;
}
return 0;
}
int prog_start(void)
{
FT_STATUS ftStatus;
uint8_t wr;
uint8_t mask = 0x80;
DWORD bytes;
uint8_t out[16] = { 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80 };
printf("prog_start()\n");
if (curr_mode == 0)
{
wr = 0xE0;
ftStatus = FT_SetBitMode(curr_handle, wr, 0x04); /*Set DD as output*/
curr_mode = 1;
}
if(FT_Write(curr_handle, out, 7, &bytes) != FT_OK)
{
printf("!W\n");
return(-1);
}
if(FT_Read(curr_handle, out, 7, &bytes) != FT_OK)
{
printf("!R\n");
return(-1);
}
}