373 lines
7.7 KiB
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);
|
||
|
}
|
||
|
|
||
|
}
|