CCHL, a hardware ChipCon programmer following swra124, running on CC1110.
Follows (almost) same protocol as CCTL, so same client s/w runs on osx/linux/win
This commit is contained in:
1 parent
ce3b5b77a7
commit
07ff76a515
10 files changed
+1785
-6
No files matched your search
@@ -1,8 +1,12 @@
|
|||||||
all:
|
all:
|
||||||
make -C boot
|
make -C cctl
|
||||||
make -C cctl-prog
|
make -C cctl-prog
|
||||||
|
make -C cchl
|
||||||
|
make -C example_payload
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make -C boot clean
|
make -C cctl clean
|
||||||
make -C cctl-prog clean
|
make -C cctl-prog clean
|
||||||
|
make -C cchl clean
|
||||||
|
make -C example_payload clean
|
||||||
|
|
||||||
@@ -4,6 +4,8 @@ CC Tiny Loader
|
|||||||
CCTL is a serial bootloader for the Chipcon CC1110/CC1111 using only one 1KB page of flash.
|
CCTL is a serial bootloader for the Chipcon CC1110/CC1111 using only one 1KB page of flash.
|
||||||
It allows update of the the microcontroller firmware over its serial port.
|
It allows update of the the microcontroller firmware over its serial port.
|
||||||
|
|
||||||
|
Included is CCHL, ChipCon Hardware Loader, an application which runs on the CC111x and can program a slave device over the ChipCon debug interface (http://focus.ti.com/lit/ug/swra124/swra124.pdf)
|
||||||
|
|
||||||
The bootloader consists of two components, a piece of firmware that is flashed
|
The bootloader consists of two components, a piece of firmware that is flashed
|
||||||
onto the device and a utility for downloading code and manipulating the
|
onto the device and a utility for downloading code and manipulating the
|
||||||
flash memory. The client program, `cctl-prog` runs on Linux, OSX/Darwin and Windows.
|
flash memory. The client program, `cctl-prog` runs on Linux, OSX/Darwin and Windows.
|
||||||
@@ -138,6 +140,13 @@ The protocol is given in detail in http://focus.ti.com/lit/ug/swra124/swra124.pd
|
|||||||
|
|
||||||
(CCTL is placed in the flash using this protocol, it is different to the serial protocol).
|
(CCTL is placed in the flash using this protocol, it is different to the serial protocol).
|
||||||
|
|
||||||
|
If you have access to one of the devices below, you can bootstrap out of it, by programming CCHL into a CC1110. CCHL allows the CC1110 to program virgin chips over the debug interface.
|
||||||
|
|
||||||
|
To reflash a slave device, connect P1_6 to DD, P1_5 to DC and P1_4 to RESET, load `cchl.hex` onto a CC1110 running CCTL and run `cctl-prog` using the `--passthrough` flag. Eg. to program the `cctl` bootloader into a device:
|
||||||
|
|
||||||
|
`./cctl-prog -p -d /dev/ttyUSB0 -f cctl.hex`
|
||||||
|
|
||||||
|
|
||||||
Official hardware programmer
|
Official hardware programmer
|
||||||
|
|
||||||
* TI's CC-Debugger http://www.ti.com/tool/cc-debugger (Windows only)
|
* TI's CC-Debugger http://www.ti.com/tool/cc-debugger (Windows only)
|
||||||
@@ -152,6 +161,7 @@ Open source implementations of protcol
|
|||||||
* Teensy (C) https://github.com/jkerdels/open_imme/tree/master/tools/teensy-prog
|
* Teensy (C) https://github.com/jkerdels/open_imme/tree/master/tools/teensy-prog
|
||||||
* Linux GPIO sysfs (C) https://github.com/ffainelli/cc2530prog
|
* Linux GPIO sysfs (C) https://github.com/ffainelli/cc2530prog
|
||||||
|
|
||||||
|
|
||||||
Building for Windows
|
Building for Windows
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
CC = sdcc
|
||||||
|
|
||||||
|
CFLAGS = --model-small --opt-code-speed
|
||||||
|
|
||||||
|
# NOTE: code-loc should be the same as the value specified for
|
||||||
|
# USER_CODE_BASE in the bootloader!
|
||||||
|
LDFLAGS_FLASH = \
|
||||||
|
--out-fmt-ihx \
|
||||||
|
--code-loc 0x400 --code-size 0x8000 \
|
||||||
|
--xram-loc 0xf000 --xram-size 0x1000 \
|
||||||
|
--iram-size 0x100
|
||||||
|
|
||||||
|
ifdef DEBUG
|
||||||
|
CFLAGS += --debug
|
||||||
|
endif
|
||||||
|
|
||||||
|
SRC = main.c
|
||||||
|
|
||||||
|
ADB=$(SRC:.c=.adb)
|
||||||
|
ASM=$(SRC:.c=.asm)
|
||||||
|
LNK=$(SRC:.c=.lnk)
|
||||||
|
LST=$(SRC:.c=.lst)
|
||||||
|
REL=$(SRC:.c=.rel)
|
||||||
|
RST=$(SRC:.c=.rst)
|
||||||
|
SYM=$(SRC:.c=.sym)
|
||||||
|
|
||||||
|
PROGS=cchl.hex
|
||||||
|
PCDB=$(PROGS:.hex=.cdb)
|
||||||
|
PLNK=$(PROGS:.hex=.lnk)
|
||||||
|
PMAP=$(PROGS:.hex=.map)
|
||||||
|
PMEM=$(PROGS:.hex=.mem)
|
||||||
|
PAOM=$(PROGS:.hex=)
|
||||||
|
|
||||||
|
%.rel : %.c
|
||||||
|
$(CC) -c $(CFLAGS) -o$*.rel $<
|
||||||
|
|
||||||
|
all: $(PROGS)
|
||||||
|
|
||||||
|
cchl.hex: $(REL) Makefile
|
||||||
|
$(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o cchl.hex $(REL)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM)
|
||||||
|
rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
|
||||||
|
|
||||||
File renamed without changes.
+416
@@ -0,0 +1,416 @@
|
|||||||
|
/*
|
||||||
|
* CCHL - ChipCon Hardware Loader
|
||||||
|
* A hardware programmer for the CC1110/CC1111 which runs on the CC1110/CC1111
|
||||||
|
* Joby Taffey (c) 2012 <jrt-cctl@hodgepig.org>
|
||||||
|
*
|
||||||
|
* Derived from:
|
||||||
|
* CC Bootloader
|
||||||
|
* Fergus Noble (c) 2011
|
||||||
|
*
|
||||||
|
* Open IMME https://github.com/jkerdels/open_imme
|
||||||
|
* Jochen kerdels
|
||||||
|
*
|
||||||
|
* 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; version 2 of the License.
|
||||||
|
*
|
||||||
|
* 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.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <cc1110.h>
|
||||||
|
#include "cc1110-ext.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Connect the target CC1110 up as follows
|
||||||
|
#define DD P1_6
|
||||||
|
#define DD_BIT BIT6
|
||||||
|
#define DC P1_5
|
||||||
|
#define DC_BIT BIT5
|
||||||
|
#define RST P1_4
|
||||||
|
#define RST_BIT BIT4
|
||||||
|
|
||||||
|
#define RXFIFO_ELEMENTS 2048
|
||||||
|
#define RXFIFO_SIZE (RXFIFO_ELEMENTS - 1)
|
||||||
|
static __xdata uint8_t rxfifo[RXFIFO_SIZE];
|
||||||
|
static uint8_t rxfifo_in;
|
||||||
|
static uint8_t rxfifo_out;
|
||||||
|
static const __code uint8_t * __at (0x0000) flashp;
|
||||||
|
__xdata uint8_t rambuf[1024];
|
||||||
|
static uint8_t page;
|
||||||
|
|
||||||
|
static const char banner[] = {'\r', '\n', 'C', 'C', 'H', 'L', '\r', '\n'};
|
||||||
|
|
||||||
|
|
||||||
|
#define BIT0 1
|
||||||
|
#define BIT1 2
|
||||||
|
#define BIT2 4
|
||||||
|
#define BIT3 8
|
||||||
|
#define BIT4 16
|
||||||
|
#define BIT5 32
|
||||||
|
#define BIT6 64
|
||||||
|
#define BIT7 128
|
||||||
|
|
||||||
|
|
||||||
|
#define ST_CHIP_ERASE_DONE 0x80
|
||||||
|
#define ST_PCON_IDLE 0x40
|
||||||
|
#define ST_CPU_HALTED 0x20
|
||||||
|
#define ST_POWER_MODE_0 0x10
|
||||||
|
#define ST_HALT_STATUS 0x08
|
||||||
|
#define ST_DEBUG_LOCKED 0x04
|
||||||
|
#define ST_OSCILLATOR_STABLE 0x02
|
||||||
|
#define ST_STACK_OVERFLOW 0x01
|
||||||
|
|
||||||
|
#define FLASHPAGE_SIZE 1024
|
||||||
|
#define FLASH_WORD_SIZE 2
|
||||||
|
#define WORDS_PER_FLASH_PAGE 512
|
||||||
|
|
||||||
|
#define nop() __asm nop __endasm;
|
||||||
|
|
||||||
|
void delay (unsigned char n)
|
||||||
|
{
|
||||||
|
unsigned char i = 0;
|
||||||
|
unsigned char j = 0;
|
||||||
|
|
||||||
|
n <<= 1;
|
||||||
|
while (--n != 0)
|
||||||
|
while (--i != 0)
|
||||||
|
while (--j != 0)
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_byte(uint8_t ch)
|
||||||
|
{
|
||||||
|
int8_t i;
|
||||||
|
P1DIR |= DD_BIT; // output
|
||||||
|
|
||||||
|
for (i = 7; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (ch & (1 << i))
|
||||||
|
DD = 1;
|
||||||
|
else
|
||||||
|
DD = 0;
|
||||||
|
DC = 1;
|
||||||
|
DC = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t recv_byte(void)
|
||||||
|
{
|
||||||
|
uint8_t ch = 0;
|
||||||
|
int8_t i;
|
||||||
|
|
||||||
|
P1DIR &= ~DD_BIT; // input
|
||||||
|
|
||||||
|
for (i = 7; i >= 0; i--)
|
||||||
|
{
|
||||||
|
DC = 1;
|
||||||
|
if (DD)
|
||||||
|
ch |= (1 << i);
|
||||||
|
DC = 0;
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void dbg_init(void)
|
||||||
|
{
|
||||||
|
P1DIR |= RST_BIT;
|
||||||
|
P1DIR |= DC_BIT; // DC
|
||||||
|
P1DIR |= DD_BIT; // DD
|
||||||
|
DD = 0;
|
||||||
|
|
||||||
|
// send debug init sequence
|
||||||
|
RST = 0;
|
||||||
|
delay(1);
|
||||||
|
DC = 0;
|
||||||
|
delay(1);
|
||||||
|
DC = 1;
|
||||||
|
delay(1);
|
||||||
|
DC = 0;
|
||||||
|
delay(1);
|
||||||
|
DC = 1;
|
||||||
|
delay(1);
|
||||||
|
DC = 0;
|
||||||
|
delay(1);
|
||||||
|
RST = 1;
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t read_status(void)
|
||||||
|
{
|
||||||
|
send_byte(0x34);
|
||||||
|
return recv_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbg_mass_erase(void)
|
||||||
|
{
|
||||||
|
send_byte(0x14);
|
||||||
|
recv_byte();
|
||||||
|
while (!(read_status() & ST_CHIP_ERASE_DONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t debug_instr_1(uint8_t in0)
|
||||||
|
{
|
||||||
|
send_byte(0x55);
|
||||||
|
send_byte(in0);
|
||||||
|
return recv_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t debug_instr_2(uint8_t in0, uint8_t in1)
|
||||||
|
{
|
||||||
|
send_byte(0x56);
|
||||||
|
send_byte(in0);
|
||||||
|
send_byte(in1);
|
||||||
|
return recv_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t debug_instr_3(uint8_t in0, uint8_t in1, uint8_t in2)
|
||||||
|
{
|
||||||
|
send_byte(0x57);
|
||||||
|
send_byte(in0);
|
||||||
|
send_byte(in1);
|
||||||
|
send_byte(in2);
|
||||||
|
return recv_byte();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_xdata_memory(uint16_t address, uint16_t count, const __xdata uint8_t *buf)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
debug_instr_3(0x90,address >> 8,address);
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
debug_instr_2(0x74, buf[i]);
|
||||||
|
debug_instr_1(0xF0);
|
||||||
|
debug_instr_1(0xA3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_pc(uint16_t address)
|
||||||
|
{
|
||||||
|
debug_instr_3(0x02,address >> 8,address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpu_resume(void)
|
||||||
|
{
|
||||||
|
send_byte(0x4C);
|
||||||
|
recv_byte(); // ignore sent value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void read_code_memory(uint16_t address,
|
||||||
|
uint8_t bank,
|
||||||
|
uint16_t count,
|
||||||
|
__xdata uint8_t *outputData)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (address >= 0x8000)
|
||||||
|
address = (address & 0x7FFF) + (bank * 0x8000);
|
||||||
|
|
||||||
|
debug_instr_3(0x75,0xC7,(bank * 16) + 1);
|
||||||
|
debug_instr_3(0x90,address >> 8,address);
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
debug_instr_1(0xE4);
|
||||||
|
outputData[i] = debug_instr_1(0x93);
|
||||||
|
debug_instr_1(0xA3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static __xdata uint8_t updProc[] =
|
||||||
|
{
|
||||||
|
0x75, 0xAD, /*ADDRESS*/0x00,
|
||||||
|
0x75, 0xAC, 0x00,
|
||||||
|
0x75, 0xAB, 0x23, 0x00,
|
||||||
|
0x75, 0xAE, 0x01, // ------
|
||||||
|
0xE5, 0xAE, // erase code
|
||||||
|
0x20, 0xE7, 0xFB, // ------
|
||||||
|
0x90, 0xF0, 0x00,
|
||||||
|
0x7F, WORDS_PER_FLASH_PAGE >> 8,
|
||||||
|
0x7E, WORDS_PER_FLASH_PAGE & 0xFF,
|
||||||
|
0x75, 0xAE, 0x02,
|
||||||
|
0x7D, FLASH_WORD_SIZE,
|
||||||
|
0xE0,
|
||||||
|
0xA3,
|
||||||
|
0xF5, 0xAF,
|
||||||
|
0xDD, 0xFA,
|
||||||
|
0xE5, 0xAE,
|
||||||
|
0x20, 0xE6, 0xFB,
|
||||||
|
0xDE, 0xF1,
|
||||||
|
0xDF, 0xEF,
|
||||||
|
0xA5
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void write_flash_page(uint32_t address)
|
||||||
|
{
|
||||||
|
uint8_t updProcSize = sizeof(updProc);
|
||||||
|
|
||||||
|
updProc[2] = ((address >> 8) / FLASH_WORD_SIZE) & 0x7E;
|
||||||
|
|
||||||
|
write_xdata_memory(0xF000, FLASHPAGE_SIZE, rambuf);
|
||||||
|
write_xdata_memory(0xF000 + FLASHPAGE_SIZE, updProcSize, updProc);
|
||||||
|
debug_instr_3(0x75,0xC7,0x51);
|
||||||
|
set_pc(0xF000 + FLASHPAGE_SIZE);
|
||||||
|
cpu_resume();
|
||||||
|
while (!(read_status() & ST_CPU_HALTED));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void read_flash_page(uint32_t address, __xdata uint8_t *outputData)
|
||||||
|
{
|
||||||
|
read_code_memory(address & 0xFFFF,
|
||||||
|
(address >> 15) & 0x03, FLASHPAGE_SIZE, outputData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void dbg_readpage(void)
|
||||||
|
{
|
||||||
|
read_flash_page(page * 1024, rambuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dbg_writepage(void)
|
||||||
|
{
|
||||||
|
uint32_t addr = page*1024;
|
||||||
|
write_flash_page(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t cons_getch(void)
|
||||||
|
{
|
||||||
|
if (rxfifo_in == rxfifo_out)
|
||||||
|
return 0;
|
||||||
|
page = rxfifo[rxfifo_out];
|
||||||
|
if (rxfifo_out + 1 == RXFIFO_SIZE)
|
||||||
|
rxfifo_out = 0;
|
||||||
|
else
|
||||||
|
rxfifo_out++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cons_putc(uint8_t ch)
|
||||||
|
{
|
||||||
|
U0DBUF = ch;
|
||||||
|
while(!(U0CSR & U0CSR_TX_BYTE)); // wait for byte to be transmitted
|
||||||
|
U0CSR &= ~U0CSR_TX_BYTE; // Clear transmit byte status
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart0_isr(void) __interrupt URX0_VECTOR
|
||||||
|
{
|
||||||
|
URX0IF = 0;
|
||||||
|
|
||||||
|
// HACK we know the buffer is big enough, as client is waiting for our ACK
|
||||||
|
// if(rxfifo_in != (( rxfifo_out - 1 + RXFIFO_SIZE) % RXFIFO_SIZE)) // not full
|
||||||
|
{
|
||||||
|
rxfifo[rxfifo_in] = U0DBUF;
|
||||||
|
if (rxfifo_in + 1 == RXFIFO_SIZE)
|
||||||
|
rxfifo_in = 0;
|
||||||
|
else
|
||||||
|
rxfifo_in++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint8_t n;
|
||||||
|
|
||||||
|
// Initialise clocks
|
||||||
|
SLEEP &= ~SLEEP_OSC_PD; // enable RC oscillator
|
||||||
|
while( !(SLEEP & SLEEP_XOSC_S) ); // let oscillator stabilise
|
||||||
|
|
||||||
|
CLKCON = CLKCON_OSC32 | CLKCON_OSC | TICKSPD_DIV_32 | CLKSPD_DIV_2; // select internal HS RC oscillator
|
||||||
|
while (!(CLKCON & CLKCON_OSC));
|
||||||
|
|
||||||
|
CLKCON = CLKCON_OSC32 | TICKSPD_DIV_32 | CLKSPD_DIV_1; // select external crystal
|
||||||
|
|
||||||
|
// while (CLKCON & CLKCON_OSC);
|
||||||
|
// SLEEP |= SLEEP_OSC_PD; // Disable RC oscillator now that we have an external crystal
|
||||||
|
|
||||||
|
rxfifo_in = rxfifo_out = 0;
|
||||||
|
|
||||||
|
PERCFG = (PERCFG & ~PERCFG_U0CFG) | PERCFG_U1CFG;
|
||||||
|
P0SEL |= (1<<3) | (1<<2);
|
||||||
|
U0CSR = 0x80 | 0x40; // UART, RX on
|
||||||
|
U0BAUD = 34; // 115200
|
||||||
|
U0GCR = 13; // 115k2 baud at 13MHz, useful for coming out of sleep. Assumes clkspd_div2 in clkcon for HSRC osc
|
||||||
|
URX0IF = 0; // No interrupts pending at start
|
||||||
|
URX0IE = 1; // Serial Rx irqs enabled in system interrupt register
|
||||||
|
|
||||||
|
EA = 1;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
while(n < sizeof(banner))
|
||||||
|
cons_putc(banner[n++]);
|
||||||
|
|
||||||
|
dbg_init();
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while(!cons_getch())
|
||||||
|
{
|
||||||
|
if (i-- == 0)
|
||||||
|
{
|
||||||
|
cons_putc('P');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if (cons_getch())
|
||||||
|
{
|
||||||
|
switch(page)
|
||||||
|
{
|
||||||
|
case 'e':
|
||||||
|
while(!cons_getch());
|
||||||
|
dbg_mass_erase();
|
||||||
|
goto ack;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
while(!cons_getch());
|
||||||
|
dbg_writepage();
|
||||||
|
goto ack;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
while(!cons_getch());
|
||||||
|
dbg_readpage();
|
||||||
|
for (i=0;i<1024;i++)
|
||||||
|
cons_putc(rambuf[i]);
|
||||||
|
goto ack;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
i = 0;
|
||||||
|
while(i<1024)
|
||||||
|
{
|
||||||
|
while(!cons_getch());
|
||||||
|
rambuf[i] = page;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
goto ack;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'j':
|
||||||
|
WDCTL = (WDCTL & ~WDCTL_INT) | WDCTL_INT_SEC_1; // watchdog on LS RCOSC, ~1s
|
||||||
|
WDCTL = (WDCTL & ~WDCTL_MODE) | WDCTL_EN; // start
|
||||||
|
while(1); // reset
|
||||||
|
break;
|
||||||
|
|
||||||
|
ack:
|
||||||
|
cons_putc(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+25
-4
@@ -34,6 +34,7 @@ static struct option long_options[] =
|
|||||||
{"flash", required_argument, 0, 'f'},
|
{"flash", required_argument, 0, 'f'},
|
||||||
{"device", required_argument, 0, 'd'},
|
{"device", required_argument, 0, 'd'},
|
||||||
{"timeout", required_argument, 0, 't'},
|
{"timeout", required_argument, 0, 't'},
|
||||||
|
{"passthrough", no_argument, 0, 'p'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ void usage(void)
|
|||||||
fprintf(stderr, " --console -c Connect console to serial port on device\n");
|
fprintf(stderr, " --console -c Connect console to serial port on device\n");
|
||||||
fprintf(stderr, " --flash=file.hex -f file.hex Reflash device with intel hex file\n");
|
fprintf(stderr, " --flash=file.hex -f file.hex Reflash device with intel hex file\n");
|
||||||
fprintf(stderr, " --timeout=n -t n Search for bootload string for n seconds\n");
|
fprintf(stderr, " --timeout=n -t n Search for bootload string for n seconds\n");
|
||||||
|
fprintf(stderr, " --passthrough -p Program remote device over passthrough\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool opt_console = false;
|
static bool opt_console = false;
|
||||||
@@ -57,6 +59,7 @@ static int opt_timeout = 10;
|
|||||||
static bool opt_device = false;
|
static bool opt_device = false;
|
||||||
static char *flash_filename = NULL;
|
static char *flash_filename = NULL;
|
||||||
static char *device_name = NULL;
|
static char *device_name = NULL;
|
||||||
|
static bool opt_passthrough = 0;
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
static struct termios orig_termios;
|
static struct termios orig_termios;
|
||||||
@@ -69,7 +72,7 @@ int parse_options(int argc, char **argv)
|
|||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
c = getopt_long (argc, argv, "hcf:d:t:", long_options, &option_index);
|
c = getopt_long (argc, argv, "hcf:d:t:p", long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
switch(c)
|
switch(c)
|
||||||
@@ -77,6 +80,9 @@ int parse_options(int argc, char **argv)
|
|||||||
case 'h':
|
case 'h':
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
opt_passthrough = 1;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
opt_timeout = atoi(optarg);
|
opt_timeout = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
@@ -352,11 +358,15 @@ int read_page(int fd, uint8_t page, uint8_t *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int already_erased = 0; // passthrough programmer only supports mass erase
|
||||||
int erase_page(int fd, uint8_t page)
|
int erase_page(int fd, uint8_t page)
|
||||||
{
|
{
|
||||||
char cmd = 'e';
|
char cmd = 'e';
|
||||||
char rsp;
|
char rsp;
|
||||||
|
|
||||||
|
if (already_erased && opt_passthrough)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (serialWrite(fd, &cmd, 1) <= 0)
|
if (serialWrite(fd, &cmd, 1) <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -369,6 +379,8 @@ int erase_page(int fd, uint8_t page)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_erased = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +469,8 @@ int wait_for_bootloader(int fd, int timeout)
|
|||||||
|
|
||||||
gettimeofday(&start, NULL);
|
gettimeofday(&start, NULL);
|
||||||
|
|
||||||
serialWrite(fd, "+++", 3);
|
if (!opt_passthrough)
|
||||||
|
serialWrite(fd, "+++", 3);
|
||||||
|
|
||||||
printf("Waiting %ds for bootloader, reset board now\n", timeout);
|
printf("Waiting %ds for bootloader, reset board now\n", timeout);
|
||||||
|
|
||||||
@@ -479,8 +492,16 @@ int wait_for_bootloader(int fd, int timeout)
|
|||||||
else
|
else
|
||||||
if (rc == 1)
|
if (rc == 1)
|
||||||
{
|
{
|
||||||
if (c == 'B' && prev_c == 'B')
|
if (opt_passthrough)
|
||||||
break;
|
{
|
||||||
|
if (c == 'P' && prev_c == 'P')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c == 'B' && prev_c == 'B')
|
||||||
|
break;
|
||||||
|
}
|
||||||
prev_c = c;
|
prev_c = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File renamed without changes.
+1283
File diff suppressed because it is too large.
Load diff
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user