- 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
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;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue