From cc4b5607c753a2bf9dc81b32eeb7374b34db149d Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Mon, 18 Jun 2012 20:31:20 -0300 Subject: [PATCH] RESET protocol to jump from application to boot loader without power cycling --- PROTOCOL | 2 ++ fw/Makefile | 8 ++++++-- fw/antorcha.c | 8 +------- fw/boot.c | 12 +++++++++++- fw/dispatch.h | 2 ++ fw/fw.c | 6 +++++- fw/proto.h | 1 + tools/antorcha.c | 18 ++++++++++++++---- 8 files changed, 42 insertions(+), 15 deletions(-) diff --git a/PROTOCOL b/PROTOCOL index f55afc8..328e7eb 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -7,6 +7,8 @@ Protocol 1 0 0 Pong (maybe return version string in the future) + 2 0 0 Reset (64 bytes reset secret) + 4 0 N Unlock secret (64 bytes payload) 4 1..N-1 N Firmware binary (64 bytes payload) 4 N N First half of hash diff --git a/fw/Makefile b/fw/Makefile index a87619f..1682a70 100644 --- a/fw/Makefile +++ b/fw/Makefile @@ -30,7 +30,7 @@ OBJCOPY = $(AVR_PREFIX)objcopy #OBJDUMP = $(AVR_PREFIX)objdump SIZE = $(AVR_PREFIX)size -OBJS = $(NAME).o dispatch.o hash.o $(COMMON_OBJS) +OBJS = $(NAME).o dispatch.o hash.o reset.o $(COMMON_OBJS) BOOT_OBJS = boot.o flash.o fw.o $(COMMON_OBJS) COMMON_OBJS = rf.o spi.o @@ -87,7 +87,7 @@ clean: rm -f version.c version.d version.o nosecrets: - rm -f unlock-secret.inc image-secret.inc + rm -f unlock-secret.inc reset-secret.inc image-secret.inc # ----- Build version --------------------------------------------------------- @@ -129,10 +129,14 @@ SECRET = { dd if=$(RANDOM) iflag=fullblock bs=$(1) count=1 status=noxfer | \ unlock-secret.inc: $(BUILD) $(call SECRET,64) >$@ || { rm -f $@; exit 1; } +reset-secret.inc: + $(BUILD) $(call SECRET,64) >$@ || { rm -f $@; exit 1; } + image-secret.inc: $(BUILD) $(call SECRET,128) >$@ || { rm -f $@; exit 1; } fw.o: unlock-secret.inc +reset.o: unlock-secret.inc # ----- Dependencies ---------------------------------------------------------- diff --git a/fw/antorcha.c b/fw/antorcha.c index 04e3c72..3c822a0 100644 --- a/fw/antorcha.c +++ b/fw/antorcha.c @@ -23,8 +23,8 @@ #include "dispatch.h" - static const struct handler *protos[] = { + &reset_handler, NULL }; @@ -39,12 +39,6 @@ int main(void) * It has also brought up RF and the underlying SPI. */ -while (1) { - SET(LED_B8); - _delay_ms(100); - CLR(LED_B8); - _delay_ms(100); -} while (1) { got = rf_recv(buf, sizeof(buf)); if (got > 2) diff --git a/fw/boot.c b/fw/boot.c index f497e53..9a31256 100644 --- a/fw/boot.c +++ b/fw/boot.c @@ -57,9 +57,19 @@ int main(void) PORTD = 0; DDRD = 0xff; - /* disable pull-ups */ + /* Disable pull-ups */ MCUCR |= 1 << PUD; + /* + * Disable the watchdog timer, in case the boot loader has been + * entered by a watchdog reset commanded by the application. + */ + + MCUSR = 0; /* Remove override */ + WDTCSR |= 1 << WDCE; /* Enable change */ + WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling + change */ + rf_init(); /* diff --git a/fw/dispatch.h b/fw/dispatch.h index ccd56ea..6dbb28a 100644 --- a/fw/dispatch.h +++ b/fw/dispatch.h @@ -26,6 +26,8 @@ struct handler { }; +extern struct handler reset_handler; + bool dispatch(const uint8_t *buf, uint8_t len, const struct handler **protos); #endif /* !PROTO_H */ diff --git a/fw/fw.c b/fw/fw.c index 1472277..8609653 100644 --- a/fw/fw.c +++ b/fw/fw.c @@ -15,6 +15,9 @@ #include #include +#define F_CPU 8000000UL +#include + #include "io.h" #include "flash.h" #include "proto.h" @@ -54,8 +57,9 @@ bool fw_packet(const uint8_t *buf, uint8_t len) static uint8_t limit; uint8_t ack[] = { FIRMWARE+1, buf[1], buf[2] }; - /* short (barely visible) flash to indicate reception */ + /* short flash to indicate reception */ SET(LED_B7); + _delay_ms(1); CLR(LED_B7); /* Check packet for formal validity */ diff --git a/fw/proto.h b/fw/proto.h index 7f7015a..006cf15 100644 --- a/fw/proto.h +++ b/fw/proto.h @@ -18,6 +18,7 @@ enum pck_type { PING = 0, /* version query */ PONG = 1, /* version response */ + RESET = 2, /* reset to boot loader */ FIRMWARE = 4, /* firmware upload */ FIRMWARE_ACK = 5, /* firmware upload acknowledgement */ IMAGE = 6, /* image upload */ diff --git a/tools/antorcha.c b/tools/antorcha.c index 2eb790f..31af37e 100644 --- a/tools/antorcha.c +++ b/tools/antorcha.c @@ -49,6 +49,7 @@ static void rf_send(struct atrf_dsc *dsc, void *buf, int len) /* Copy the message to append the CRC placeholders */ memcpy(tmp, buf, len); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); + flush_interrupts(dsc); atrf_buf_write(dsc, tmp, len+2); atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START); wait_for_interrupt(dsc, IRQ_TRX_END, @@ -98,17 +99,25 @@ static void ping(struct atrf_dsc *dsc) } -static void packet(struct atrf_dsc *dsc, +static void packet_noack(struct atrf_dsc *dsc, uint8_t type, uint8_t seq, uint8_t last, const void *payload, int len) { uint8_t tx_buf[PAYLOAD+3] = { type, seq, last }; - uint8_t rx_buf[10]; - int got; assert(len == PAYLOAD); memcpy(tx_buf+3, payload, len); + rf_send(dsc, tx_buf, sizeof(tx_buf)); +} + + +static void packet(struct atrf_dsc *dsc, + uint8_t type, uint8_t seq, uint8_t last, const void *payload, int len) +{ + uint8_t rx_buf[10]; + int got; + while (1) { - rf_send(dsc, tx_buf, sizeof(tx_buf)); + packet_noack(dsc, type, seq, last, payload, len); if (verbose) write(2, ">", 1); got = rf_recv(dsc, rx_buf, sizeof(rx_buf)); @@ -146,6 +155,7 @@ static void send_firmware(struct atrf_dsc *dsc, void *buf, int len) write(2, "firmware ", 9); last = (len+63)/64; seq = 0; + packet_noack(dsc, RESET, 0, 0, unlock_secret, PAYLOAD); packet(dsc, FIRMWARE, seq++, last, unlock_secret, PAYLOAD); while (len >= PAYLOAD) { packet(dsc, FIRMWARE, seq++, last, buf, PAYLOAD);