Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updated for working. Github authorization now works

Server can update Github statuses & create web hooks.

Hex files compile and nominally work, are now included within the
flashChip file.

Converted from SPI to Serial comms. Should still work well.
  • Loading branch information...
commit bb215d5639fbf930aca387c5300522b940dc9d86 1 parent 3326e46
Gene Jones authored
181 Devices.h
View
@@ -0,0 +1,181 @@
+//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************
+//*
+//* Title: AVR061 - STK500 Communication Protocol
+//* Filename: devices.h
+//* Version: 1.0
+//* Last updated: 09.09.2002
+//*
+//* Support E-mail: avr@atmel.com
+//*
+//**************************************************************************
+
+#ifndef __DEVICES_INCLUDED
+#define __DEVICES_INCLUDED
+
+/* 0x00-0x0F reserved */
+
+/* 0x10-0x1F ATtiny 1K devices */
+
+#define ATTINY10 0x10
+#define ATTINY11 0x11
+#define ATTINY12 0x12
+#define ATTINY15 0x13
+
+/* 0x20-0x2F ATtiny 2K devices */
+
+#define ATTINY22 0x20
+#define ATTINY26 0x21
+#define ATTINY28 0x22
+
+/* 0x30-0x3F ATclassic 1K devices */
+
+#define AT90S1200 0x33
+
+/* 0x40-0x4F ATclassic 2K devices */
+
+#define AT90S2313 0x40
+#define AT90S2323 0x41
+#define AT90S2333 0x42
+#define AT90S2343 0x43
+
+/* 0x50-0x5F ATclassic 4K devices */
+
+#define AT90S4414 0x50
+#define AT90S4433 0x51
+#define AT90S4434 0x52
+
+/* 0x60-0x6F ATclassic 8K devices */
+
+#define AT90S8515 0x60
+#define AT90S8535 0x61
+#define AT90C8534 0x62
+#define ATMEGA8515 0x63
+#define ATMEGA8535 0x64
+
+/* 0x70-0x7F ATmega 8K devices */
+
+#define ATMEGA8 0x70
+
+/* 0x80-0x8F ATmega 16K devices */
+
+#define ATMEGA161 0x80
+#define ATMEGA163 0x81
+#define ATMEGA16 0x82
+#define ATMEGA162 0x83
+#define ATMEGA169 0x84
+
+/* 0x90-0x9F ATmega 32K devices */
+
+#define ATMEGA323 0x90
+#define ATMEGA32 0x91
+
+/* 0xA0-0xAF ATmega 64K devices */
+
+/* 0xB0-0xBF ATmega 128K devices */
+
+#define ATMEGA103 0xB1
+#define ATMEGA128 0xB2
+
+/* 0xC0-0xCF not used */
+
+/* 0xD0-0xDF Other devices */
+#define AT86RF401 0xD0
+
+/* 0xE0-0xEF AT89 devices */
+#define AT89START 0xE0
+#define AT89S51 0xE0
+#define AT89S52 0xE1
+
+/* 0xF0-0xFF reserved */
+
+#define DEFAULTDEVICE AT90S8515
+
+
+struct Device
+{
+ UCHAR ucId; // Device ID
+ UCHAR ucRev; // Device revision
+
+ DWORD dwFlashSize; // FLASH memory
+ WORD wEepromSize; // EEPROM memory
+
+ UCHAR ucFuseBytes; // Number of fuse bytes
+ UCHAR ucLockBytes; // Number of lock bytes
+
+ UCHAR ucSerFProg; // (internal) Serial fuse programming support
+ UCHAR ucSerLProg; // (internal) Serial lockbit programming support
+ UCHAR ucSerFLRead; // (internal) Serial fuse/lockbit reading support
+ UCHAR ucCommonLFR; // (internal) Indicates if lockbits and fuses are combined on read
+ UCHAR ucSerMemProg; // (internal) Serial memory progr. support
+
+ WORD wPageSize; // Flash page size
+ UCHAR ucEepromPageSize; // Eeprom page size (extended parameter)
+
+ UCHAR ucSelfTimed; // True if all instructions are self timed
+ UCHAR ucFullPar; // True if part has full paralell interface
+ UCHAR ucPolling; // True if polling can be used during SPI access
+
+ UCHAR ucFPol; // Flash poll value
+ UCHAR ucEPol1; // Eeprom poll value 1
+ UCHAR ucEPol2; // Eeprom poll value 2
+
+ LPCTSTR name; // Device name
+
+ UCHAR ucSignalPAGEL; // Position of PAGEL signal (0xD7 by default)
+ UCHAR ucSignalBS2; // Position of BS2 signal (0xA0 by default)
+};
+
+
+const struct Device g_deviceTable[] =
+{
+// Id Rv FSize ESize FB LB SerFP SerLP SerFLR CLFR SerMP PS EPS SelfT FulPar Poll FPoll EPol1 EPol2 Name
+ {ATTINY10, 1, 1024, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0, FALSE, FALSE, FALSE, 0x00, 0x00, 0x00, "ATtiny10", 0xD7, 0xA0},
+ {ATTINY11, 1, 1024, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0, FALSE, FALSE, FALSE, 0x00, 0x00, 0x00, "ATtiny11", 0xD7, 0xA0},
+ {ATTINY12, 1, 1024, 64, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 0, 0, TRUE, FALSE, TRUE, 0xFF, 0xFF, 0xFF, "ATtiny12", 0xD7, 0xA0},
+ {ATTINY15, 1, 1024, 64, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 0, 0, TRUE, FALSE, TRUE, 0xFF, 0xFF, 0xFF, "ATtiny15", 0xD7, 0xA0},
+
+ {ATTINY22, 1, 2048, 128, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, FALSE, FALSE, TRUE, 0xFF, 0x00, 0xFF, "ATtiny22", 0xD7, 0xA0},
+ {ATTINY26, 1, 2048, 128, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 32, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATtiny26", 0xD7, 0xA0},
+ {ATTINY28, 1, 2048, 0, 1, 1, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0, TRUE, TRUE, FALSE, 0x00, 0x00, 0x00, "ATtiny28", 0xD7, 0xA0},
+
+ {AT90S1200, 4, 1024, 64, 1, 1, FALSE, TRUE, FALSE, TRUE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0xFF, 0x00, 0xFF, "AT90S1200", 0xD7, 0xA0},
+
+ {AT90S2313, 1, 2048, 128, 1, 1, FALSE, TRUE, FALSE, TRUE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0x7F, 0x80, 0x7F, "AT90S2313", 0xD7, 0xA0},
+ {AT90S2323, 1, 2048, 128, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, FALSE, FALSE, TRUE, 0xFF, 0x00, 0xFF, "AT90S2323", 0xD7, 0xA0},
+ {AT90S2333, 1, 2048, 128, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0xFF, 0x00, 0xFF, "AT90S2333", 0xD7, 0xA0},
+ {AT90S2343, 1, 2048, 128, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, FALSE, FALSE, TRUE, 0xFF, 0x00, 0xFF, "AT90S2343", 0xD7, 0xA0},
+
+ {AT90S4414, 1, 4096, 256, 1, 1, FALSE, TRUE, FALSE, TRUE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0x7F, 0x80, 0x7F, "AT90S4414", 0xD7, 0xA0},
+ {AT90S4433, 1, 4096, 128, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0xFF, 0x00, 0xFF, "AT90S4433", 0xD7, 0xA0},
+ {AT90S4434, 1, 4096, 256, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0xFF, 0x00, 0xFF, "AT90S4434", 0xD7, 0xA0},
+
+ {AT90S8515, 1, 8192, 256, 1, 1, FALSE, TRUE, FALSE, TRUE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0x7F, 0x80, 0x7F, "AT90S8515", 0xD7, 0xA0},
+ {AT90S8535, 1, 8192, 512, 1, 1, TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, FALSE, TRUE, TRUE, 0xFF, 0x00, 0xFF, "AT90S8535", 0xD7, 0xA0},
+ {AT90C8534, 1, 8192, 512, 0, 1, FALSE, FALSE, FALSE, TRUE, FALSE, 0, 0, FALSE, TRUE, FALSE, 0x00, 0x00, 0x00, "AT90C8534", 0xD7, 0xA0},
+
+ {ATMEGA8, 1, 8192, 512, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 64, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega8", 0xD7, 0xA0},
+ {ATMEGA8515, 1, 8192, 512, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 64, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega8515", 0xD7, 0xA0},
+ {ATMEGA8535, 1, 8192, 512, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 64, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega8535", 0xD7, 0xA0},
+
+ {ATMEGA161, 1, 16384, 512, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 0, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega161", 0xD7, 0xA0},
+ {ATMEGA162, 1, 16384, 512, 3, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega162", 0xD7, 0xA0},
+ {ATMEGA163, 1, 16384, 512, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 0, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega163", 0xD7, 0xA0},
+ {ATMEGA16, 1, 16384, 512, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega16", 0xD7, 0xA0},
+ {ATMEGA169, 1, 16384, 512, 3, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega169", 0xD7, 0xA0},
+
+ {ATMEGA323, 1, 32768, 1024, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 0, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega323", 0xD7, 0xA0},
+ {ATMEGA32, 1, 32768, 1024, 2, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 128, 4, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega32", 0xD7, 0xA0},
+
+ {ATMEGA103, 1, 131072, 4096, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 256, 0, FALSE, TRUE, FALSE, 0x00, 0x00, 0x00, "ATmega103", 0xA0, 0xD7},
+ {ATMEGA128, 1, 131072, 4096, 3, 1, TRUE, TRUE, TRUE, FALSE, TRUE, 256, 8, TRUE, TRUE, TRUE, 0xFF, 0xFF, 0xFF, "ATmega128", 0xD7, 0xA0},
+
+ {AT86RF401, 1, 2048, 128, 0, 1, FALSE, TRUE, TRUE, FALSE, TRUE, 0, 0, FALSE, FALSE, FALSE, 0x00, 0x00, 0x00, "AT86RF401", 0xD7, 0xA0},
+
+ {AT89S51, 1, 4096, 0, 0, 1, FALSE, TRUE, TRUE, FALSE, TRUE, 0, 0, FALSE, FALSE, FALSE, 0x00, 0x00, 0x00, "AT89S51", 0xD7, 0xA0},
+ {AT89S52, 1, 8192, 0, 0, 1, FALSE, TRUE, TRUE, FALSE, TRUE, 0, 0, FALSE, FALSE, FALSE, 0x00, 0x00, 0x00, "AT89S52", 0xD7, 0xA0},
+
+ {0}
+};
+
+
+#endif
46 avrdude.c
View
@@ -81,48 +81,7 @@ int pmode=0;
int here;
uint8_t buff[256]; // global block storage
-#define beget16(addr) (*addr * 256 + *(addr+1) )
-typedef struct param {
- uint8_t devicecode;
- uint8_t revision;
- uint8_t progtype;
- uint8_t parmode;
- uint8_t polling;
- uint8_t selftimed;
- uint8_t lockbytes;
- uint8_t fusebytes;
- int flashpoll;
- int eeprompoll;
- int pagesize;
- int eepromsize;
- int flashsize;
-}
-parameter;
-
-parameter param;
-
-// this provides a heartbeat on pin 9, so you can tell the software is running.
-uint8_t hbval=128;
-int8_t hbdelta=8;
-void heartbeat() {
- if (hbval > 192) hbdelta = -hbdelta;
- if (hbval < 32) hbdelta = -hbdelta;
- hbval += hbdelta;
- analogWrite(LED_HB, hbval);
- delay(20);
-}
-
-
void loop(void) {
- // is pmode active?
- if (pmode) digitalWrite(LED_PMODE, HIGH);
- else digitalWrite(LED_PMODE, LOW);
- // is there an error?
- if (error) digitalWrite(LED_ERR, HIGH);
- else digitalWrite(LED_ERR, LOW);
-
- // light the heartbeat LED
- heartbeat();
if (Serial.available()) {
avrisp();
}
@@ -149,11 +108,6 @@ void pulse(int pin, int times) {
while (times--);
}
-void prog_lamp(int state) {
- if (PROG_FLICKER)
- digitalWrite(LED_PMODE, state);
-}
-
void spi_init() {
uint8_t x;
SPCR = 0x53;
491 avriscp.c
View
@@ -0,0 +1,491 @@
+// ArduinoISP version 04m3
+// Copyright (c) 2008-2011 Randall Bohn
+// If you require a license, see
+// http://www.opensource.org/licenses/bsd-license.php
+//
+// This sketch turns the Arduino into a AVRISP
+// using the following arduino pins:
+//
+// pin name: not-mega: mega(1280 and 2560)
+// slave reset: 10: 53
+// MOSI: 11: 51
+// MISO: 12: 50
+// SCK: 13: 52
+//
+// Put an LED (with resistor) on the following pins:
+// 9: Heartbeat - shows the programmer is running
+// 8: Error - Lights up if something goes wrong (use red if that makes sense)
+// 7: Programming - In communication with the slave
+//
+// 23 July 2011 Randall Bohn
+// -Address Arduino issue 509 :: Portability of ArduinoISP
+// http://code.google.com/p/arduino/issues/detail?id=509
+//
+// October 2010 by Randall Bohn
+// - Write to EEPROM > 256 bytes
+// - Better use of LEDs:
+// -- Flash LED_PMODE on each flash commit
+// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress)
+// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync.
+// - Use pins_arduino.h (should also work on Arduino Mega)
+//
+// October 2009 by David A. Mellis
+// - Added support for the read signature command
+//
+// February 2009 by Randall Bohn
+// - Added support for writing to EEPROM (what took so long?)
+// Windows users should consider WinAVR's avrdude instead of the
+// avrdude included with Arduino software.
+//
+// January 2008 by Randall Bohn
+// - Thanks to Amplificar for helping me with the STK500 protocol
+// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
+// - The SPI functions herein were developed for the AVR910_ARD programmer
+// - More information at http://code.google.com/p/mega-isp
+
+#include "pins_arduino.h"
+#define RESET SS
+
+#define LED_HB 9
+#define LED_ERR 8
+#define LED_PMODE 7
+#define PROG_FLICKER true
+
+#define HWVER 2
+#define SWMAJ 1
+#define SWMIN 18
+
+// STK Definitions
+#define STK_OK 0x10
+#define STK_FAILED 0x11
+#define STK_UNKNOWN 0x12
+#define STK_INSYNC 0x14
+#define STK_NOSYNC 0x15
+#define CRC_EOP 0x20 //ok it is a space...
+
+void pulse(int pin, int times);
+
+void setup() {
+ Serial.begin(19200);
+}
+
+int error=0;
+int pmode=0;
+// address for reading and writing, set by 'U' command
+int here;
+uint8_t buff[256]; // global block storage
+
+void loop(void) {
+ if (Serial.available()) {
+ avrisp();
+ }
+}
+
+uint8_t getch() {
+ while(!Serial.available());
+ return Serial.read();
+}
+void fill(int n) {
+ for (int x = 0; x < n; x++) {
+ buff[x] = getch();
+ }
+}
+
+#define PTIME 30
+void pulse(int pin, int times) {
+ do {
+ digitalWrite(pin, HIGH);
+ delay(PTIME);
+ digitalWrite(pin, LOW);
+ delay(PTIME);
+ }
+ while (times--);
+}
+
+void spi_init() {
+ uint8_t x;
+ SPCR = 0x53;
+ x=SPSR;
+ x=SPDR;
+}
+
+void spi_wait() {
+ do {
+ }
+ while (!(SPSR & (1 << SPIF)));
+}
+
+uint8_t spi_send(uint8_t b) {
+ uint8_t reply;
+ SPDR=b;
+ spi_wait();
+ reply = SPDR;
+ return reply;
+}
+
+uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
+ uint8_t n;
+ spi_send(a);
+ n=spi_send(b);
+ //if (n != a) error = -1;
+ n=spi_send(c);
+ return spi_send(d);
+}
+
+void empty_reply() {
+ if (CRC_EOP == getch()) {
+ Serial.print((char)STK_INSYNC);
+ Serial.print((char)STK_OK);
+ }
+ else {
+ error++;
+ Serial.print((char)STK_NOSYNC);
+ }
+}
+
+void breply(uint8_t b) {
+ if (CRC_EOP == getch()) {
+ Serial.print((char)STK_INSYNC);
+ Serial.print((char)b);
+ Serial.print((char)STK_OK);
+ }
+ else {
+ error++;
+ Serial.print((char)STK_NOSYNC);
+ }
+}
+
+void get_version(uint8_t c) {
+ switch(c) {
+ case 0x80:
+ breply(HWVER);
+ break;
+ case 0x81:
+ breply(SWMAJ);
+ break;
+ case 0x82:
+ breply(SWMIN);
+ break;
+ case 0x93:
+ breply('S'); // serial programmer
+ break;
+ default:
+ breply(0);
+ }
+}
+
+void set_parameters() {
+ // call this after reading paramter packet into buff[]
+ param.devicecode = buff[0];
+ param.revision = buff[1];
+ param.progtype = buff[2];
+ param.parmode = buff[3];
+ param.polling = buff[4];
+ param.selftimed = buff[5];
+ param.lockbytes = buff[6];
+ param.fusebytes = buff[7];
+ param.flashpoll = buff[8];
+ // ignore buff[9] (= buff[8])
+ // following are 16 bits (big endian)
+ param.eeprompoll = beget16(&buff[10]);
+ param.pagesize = beget16(&buff[12]);
+ param.eepromsize = beget16(&buff[14]);
+
+ // 32 bits flashsize (big endian)
+ param.flashsize = buff[16] * 0x01000000
+ + buff[17] * 0x00010000
+ + buff[18] * 0x00000100
+ + buff[19];
+
+}
+
+void start_pmode() {
+ spi_init();
+ // following delays may not work on all targets...
+ pinMode(RESET, OUTPUT);
+ digitalWrite(RESET, HIGH);
+ pinMode(SCK, OUTPUT);
+ digitalWrite(SCK, LOW);
+ delay(50);
+ digitalWrite(RESET, LOW);
+ delay(50);
+ pinMode(MISO, INPUT);
+ pinMode(MOSI, OUTPUT);
+ spi_transaction(0xAC, 0x53, 0x00, 0x00);
+ pmode = 1;
+}
+
+void end_pmode() {
+ pinMode(MISO, INPUT);
+ pinMode(MOSI, INPUT);
+ pinMode(SCK, INPUT);
+ pinMode(RESET, INPUT);
+ pmode = 0;
+}
+
+void universal() {
+ int w;
+ uint8_t ch;
+
+ fill(4);
+ ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
+ breply(ch);
+}
+
+void flash(uint8_t hilo, int addr, uint8_t data) {
+ spi_transaction(0x40+8*hilo,
+ addr>>8 & 0xFF,
+ addr & 0xFF,
+ data);
+}
+void commit(int addr) {
+ if (PROG_FLICKER) prog_lamp(LOW);
+ spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
+ if (PROG_FLICKER) {
+ delay(PTIME);
+ prog_lamp(HIGH);
+ }
+}
+
+//#define _current_page(x) (here & 0xFFFFE0)
+int current_page(int addr) {
+ if (param.pagesize == 32) return here & 0xFFFFFFF0;
+ if (param.pagesize == 64) return here & 0xFFFFFFE0;
+ if (param.pagesize == 128) return here & 0xFFFFFFC0;
+ if (param.pagesize == 256) return here & 0xFFFFFF80;
+ return here;
+}
+
+
+void write_flash(int length) {
+ fill(length);
+ if (CRC_EOP == getch()) {
+ Serial.print((char) STK_INSYNC);
+ Serial.print((char) write_flash_pages(length));
+ }
+ else {
+ error++;
+ Serial.print((char) STK_NOSYNC);
+ }
+}
+
+uint8_t write_flash_pages(int length) {
+ int x = 0;
+ int page = current_page(here);
+ while (x < length) {
+ if (page != current_page(here)) {
+ commit(page);
+ page = current_page(here);
+ }
+ flash(LOW, here, buff[x++]);
+ flash(HIGH, here, buff[x++]);
+ here++;
+ }
+
+ commit(page);
+
+ return STK_OK;
+}
+
+#define EECHUNK (32)
+uint8_t write_eeprom(int length) {
+ // here is a word address, get the byte address
+ int start = here * 2;
+ int remaining = length;
+ if (length > param.eepromsize) {
+ error++;
+ return STK_FAILED;
+ }
+ while (remaining > EECHUNK) {
+ write_eeprom_chunk(start, EECHUNK);
+ start += EECHUNK;
+ remaining -= EECHUNK;
+ }
+ write_eeprom_chunk(start, remaining);
+ return STK_OK;
+}
+// write (length) bytes, (start) is a byte address
+uint8_t write_eeprom_chunk(int start, int length) {
+ // this writes byte-by-byte,
+ // page writing may be faster (4 bytes at a time)
+ fill(length);
+ prog_lamp(LOW);
+ for (int x = 0; x < length; x++) {
+ int addr = start+x;
+ spi_transaction(0xC0, (addr>>8) & 0xFF, addr & 0xFF, buff[x]);
+ delay(45);
+ }
+ prog_lamp(HIGH);
+ return STK_OK;
+}
+
+void program_page() {
+ char result = (char) STK_FAILED;
+ int length = 256 * getch();
+ length += getch();
+ char memtype = getch();
+ // flash memory @here, (length) bytes
+ if (memtype == 'F') {
+ write_flash(length);
+ return;
+ }
+ if (memtype == 'E') {
+ result = (char)write_eeprom(length);
+ if (CRC_EOP == getch()) {
+ Serial.print((char) STK_INSYNC);
+ Serial.print(result);
+ }
+ else {
+ error++;
+ Serial.print((char) STK_NOSYNC);
+ }
+ return;
+ }
+ Serial.print((char)STK_FAILED);
+ return;
+}
+
+uint8_t flash_read(uint8_t hilo, int addr) {
+ return spi_transaction(0x20 + hilo * 8,
+ (addr >> 8) & 0xFF,
+ addr & 0xFF,
+ 0);
+}
+
+char flash_read_page(int length) {
+ for (int x = 0; x < length; x+=2) {
+ uint8_t low = flash_read(LOW, here);
+ Serial.print((char) low);
+ uint8_t high = flash_read(HIGH, here);
+ Serial.print((char) high);
+ here++;
+ }
+ return STK_OK;
+}
+
+char eeprom_read_page(int length) {
+ // here again we have a word address
+ int start = here * 2;
+ for (int x = 0; x < length; x++) {
+ int addr = start + x;
+ uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF);
+ Serial.print((char) ee);
+ }
+ return STK_OK;
+}
+
+void read_page() {
+ char result = (char)STK_FAILED;
+ int length = 256 * getch();
+ length += getch();
+ char memtype = getch();
+ if (CRC_EOP != getch()) {
+ error++;
+ Serial.print((char) STK_NOSYNC);
+ return;
+ }
+ Serial.print((char) STK_INSYNC);
+ if (memtype == 'F') result = flash_read_page(length);
+ if (memtype == 'E') result = eeprom_read_page(length);
+ Serial.print(result);
+ return;
+}
+
+void read_signature() {
+ if (CRC_EOP != getch()) {
+ error++;
+ Serial.print((char) STK_NOSYNC);
+ return;
+ }
+ Serial.print((char) STK_INSYNC);
+ uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
+ Serial.print((char) high);
+ uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
+ Serial.print((char) middle);
+ uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
+ Serial.print((char) low);
+ Serial.print((char) STK_OK);
+}
+//////////////////////////////////////////
+//////////////////////////////////////////
+
+
+////////////////////////////////////
+////////////////////////////////////
+int avrisp() {
+ uint8_t data, low, high;
+ uint8_t ch = getch();
+ switch (ch) {
+ case '0': // signon
+ error = 0;
+ empty_reply();
+ break;
+ case '1':
+ if (getch() == CRC_EOP) {
+ Serial.print((char) STK_INSYNC);
+ Serial.print("AVR ISP");
+ Serial.print((char) STK_OK);
+ }
+ break;
+ case 'A':
+ get_version(getch());
+ break;
+ case 'B':
+ fill(20);
+ set_parameters();
+ break;
+ case 'P':
+ start_pmode();
+ break;
+ case 'U': // set address (word)
+ here = getch();
+ here += 256 * getch();
+ break;
+
+ case 0x60: //STK_PROG_FLASH
+ low = getch();
+ high = getch();
+ break;
+ case 0x61: //STK_PROG_DATA
+ data = getch();
+ break;
+
+ case 0x64: //STK_PROG_PAGE
+ program_page();
+ break;
+
+ case 0x74: //STK_READ_PAGE 't'
+ read_page();
+ break;
+
+ case 'V': //0x56
+ universal();
+ break;
+ case 'Q': //0x51
+ error=0;
+ end_pmode();
+ empty_reply();
+ break;
+
+ case 0x75: //STK_READ_SIGN 'u'
+ read_signature();
+ break;
+
+ // expecting a command, not CRC_EOP
+ // this is how we can get back in sync
+ case CRC_EOP:
+ error++;
+ Serial.print((char) STK_NOSYNC);
+ break;
+
+ // anything else we will return STK_UNKNOWN
+ default:
+ error++;
+ if (CRC_EOP == getch())
+ Serial.print((char)STK_UNKNOWN);
+ else
+ Serial.print((char)STK_NOSYNC);
+ }
+}
+
+
108 command.h
View
@@ -0,0 +1,108 @@
+//**** ATMEL AVR - A P P L I C A T I O N N O T E ************************
+//*
+//* Title: AVR061 - STK500 Communication Protocol
+//* Filename: command.h
+//* Version: 1.0
+//* Last updated: 09.09.2002
+//*
+//* Support E-mail: avr@atmel.com
+//*
+//**************************************************************************
+
+// *****************[ STK Message constants ]***************************
+
+#define STK_SIGN_ON_MESSAGE "AVR STK" // Sign on string for Cmnd_STK_GET_SIGN_ON
+
+// *****************[ STK Response constants ]***************************
+
+#define Resp_STK_OK 0x10 // ' '
+#define Resp_STK_FAILED 0x11 // ' '
+#define Resp_STK_UNKNOWN 0x12 // ' '
+#define Resp_STK_NODEVICE 0x13 // ' '
+#define Resp_STK_INSYNC 0x14 // ' '
+#define Resp_STK_NOSYNC 0x15 // ' '
+
+#define Resp_ADC_CHANNEL_ERROR 0x16 // ' '
+#define Resp_ADC_MEASURE_OK 0x17 // ' '
+#define Resp_PWM_CHANNEL_ERROR 0x18 // ' '
+#define Resp_PWM_ADJUST_OK 0x19 // ' '
+
+// *****************[ STK Special constants ]***************************
+
+#define Sync_CRC_EOP 0x20 // 'SPACE'
+
+// *****************[ STK Command constants ]***************************
+
+#define Cmnd_STK_GET_SYNC 0x30 // ' '
+#define Cmnd_STK_GET_SIGN_ON 0x31 // ' '
+#define Cmnd_STK_RESET 0x32 // ' '
+#define Cmnd_STK_SINGLE_CLOCK 0x33 // ' '
+#define Cmnd_STK_STORE_PARAMETERS 0x34 // ' '
+
+#define Cmnd_STK_SET_PARAMETER 0x40 // ' '
+#define Cmnd_STK_GET_PARAMETER 0x41 // ' '
+#define Cmnd_STK_SET_DEVICE 0x42 // ' '
+#define Cmnd_STK_GET_DEVICE 0x43 // ' '
+#define Cmnd_STK_GET_STATUS 0x44 // ' '
+#define Cmnd_STK_SET_DEVICE_EXT 0x45 // ' '
+
+#define Cmnd_STK_ENTER_PROGMODE 0x50 // ' '
+#define Cmnd_STK_LEAVE_PROGMODE 0x51 // ' '
+#define Cmnd_STK_CHIP_ERASE 0x52 // ' '
+#define Cmnd_STK_CHECK_AUTOINC 0x53 // ' '
+#define Cmnd_STK_CHECK_DEVICE 0x54 // ' '
+#define Cmnd_STK_LOAD_ADDRESS 0x55 // ' '
+#define Cmnd_STK_UNIVERSAL 0x56 // ' '
+
+#define Cmnd_STK_PROG_FLASH 0x60 // ' '
+#define Cmnd_STK_PROG_DATA 0x61 // ' '
+#define Cmnd_STK_PROG_FUSE 0x62 // ' '
+#define Cmnd_STK_PROG_LOCK 0x63 // ' '
+#define Cmnd_STK_PROG_PAGE 0x64 // ' '
+#define Cmnd_STK_PROG_FUSE_EXT 0x65 // ' '
+
+#define Cmnd_STK_READ_FLASH 0x70 // ' '
+#define Cmnd_STK_READ_DATA 0x71 // ' '
+#define Cmnd_STK_READ_FUSE 0x72 // ' '
+#define Cmnd_STK_READ_LOCK 0x73 // ' '
+#define Cmnd_STK_READ_PAGE 0x74 // ' '
+#define Cmnd_STK_READ_SIGN 0x75 // ' '
+#define Cmnd_STK_READ_OSCCAL 0x76 // ' '
+#define Cmnd_STK_READ_FUSE_EXT 0x77 // ' '
+#define Cmnd_STK_READ_OSCCAL_EXT 0x78 // ' '
+
+// *****************[ STK Parameter constants ]***************************
+
+#define Parm_STK_HW_VER 0x80 // ' ' - R
+#define Parm_STK_SW_MAJOR 0x81 // ' ' - R
+#define Parm_STK_SW_MINOR 0x82 // ' ' - R
+#define Parm_STK_LEDS 0x83 // ' ' - R/W
+#define Parm_STK_VTARGET 0x84 // ' ' - R/W
+#define Parm_STK_VADJUST 0x85 // ' ' - R/W
+#define Parm_STK_OSC_PSCALE 0x86 // ' ' - R/W
+#define Parm_STK_OSC_CMATCH 0x87 // ' ' - R/W
+#define Parm_STK_RESET_DURATION 0x88 // ' ' - R/W
+#define Parm_STK_SCK_DURATION 0x89 // ' ' - R/W
+
+#define Parm_STK_BUFSIZEL 0x90 // ' ' - R/W, Range {0..255}
+#define Parm_STK_BUFSIZEH 0x91 // ' ' - R/W, Range {0..255}
+#define Parm_STK_DEVICE 0x92 // ' ' - R/W, Range {0..255}
+#define Parm_STK_PROGMODE 0x93 // ' ' - 'P' or 'S'
+#define Parm_STK_PARAMODE 0x94 // ' ' - TRUE or FALSE
+#define Parm_STK_POLLING 0x95 // ' ' - TRUE or FALSE
+#define Parm_STK_SELFTIMED 0x96 // ' ' - TRUE or FALSE
+
+
+// *****************[ STK status bit definitions ]***************************
+
+#define Stat_STK_INSYNC 0x01 // INSYNC status bit, '1' - INSYNC
+#define Stat_STK_PROGMODE 0x02 // Programming mode, '1' - PROGMODE
+#define Stat_STK_STANDALONE 0x04 // Standalone mode, '1' - SM mode
+#define Stat_STK_RESET 0x08 // RESET button, '1' - Pushed
+#define Stat_STK_PROGRAM 0x10 // Program button, ' 1' - Pushed
+#define Stat_STK_LEDG 0x20 // Green LED status, '1' - Lit
+#define Stat_STK_LEDR 0x40 // Red LED status, '1' - Lit
+#define Stat_STK_LEDBLINK 0x80 // LED blink ON/OFF, '1' - Blink
+
+
+// *****************************[ End Of COMMAND.H ]**************************
208 flashChip.c
View
@@ -11,11 +11,18 @@
*released under CC-A 3.0; no guarantee of any kind is made for this code
*/
-PROG-ENABLE <- "\xAC\x53\x00\x00";
-CHIP-ERASE <- "\xAC\x80\x00\x00";
-CHIP-ERASE-DELAY <- 0.09; //need to wait for a good 90ms before doing after erasing chip
-SIGNATURE-CHECK <- "\x30\x00";
-SYNC-CHECK-PROG <- 0x53;
+PROGRAM_SERIAL_SPEED <- 115200; //the baud for UNO programming
+//Duemilanove 328P requires 57600, 168P based programm at 19200 baud
+
+STK_ENTER_PROGMODE <- 0x50;
+STK_CRC_EOP <- 0x20;
+STK_OK <- 0x10;
+CHIP_ERASE <- "\xAC\x80\x00\x00";
+CHIP_ERASE_DELAY <- 0.09; //need to wait for a good 90ms before doing after erasing chip
+SIGNATURE_CHECK <- "\x30\x00";
+SYNC_CHECK_PROG <- 0x53;
+STK_LOAD_ADDRESS <- 0x55;
+STK_LEAVE_PROGMODE <- 0x51;
class ArduinoProgrammer {
constructor(target, hex_info){
@@ -23,10 +30,7 @@ class ArduinoProgrammer {
//configure hardware for our usage
hardware.pin7.configure(DIGITAL_OUT_OD_PULLUP) //this will be our reset pin
resetPin = hardware.pin7;
- //it should be pulled up most of the time, so we don't inadverrently pull the avr into a reset
- local spi_speed = hardware.spi.configure(MSB_FIRST|CLOCK_IDLE_LOW,300);
- server.log(format("Configured SPI to run at %s", spi_speed));
- spi = hardware.spi257;
+ serial = hardware.uart12.configure(PROGRAM_SERIAL_SPEED, 8, PARITY_NONE, 1, NO_CTSRTS);
hex_info = hex_info;
target = target;
}
@@ -34,13 +38,10 @@ class ArduinoProgrammer {
server.log("Starting AVR programming process now");
try{
resetAVR();
- enable_programming_request();
+ enable_programming();
verify_signature();
- delete_flash();
- write_flash();
- verify_flash();
+ program();
server.log("Successfully programmed AVR with new .hex file");
- agent.send("avr reflash success");
}
catch (error) {
server.log("ERROR. Programming failed due to "+error);
@@ -58,22 +59,45 @@ class ArduinoProgrammer {
imp.sleep(0.05); //wait 50ms to allow the AVR to wake back up
}
- function enable_programming_request(){
- response = spi.writeread(PROG-ENABLE);
- if (response[2] != SYNC-CHECK-PROG){
+ function send_command(){
+ serial.write(command + STK_CRC_EOP);
+ serial.flush();
+ local b = serial.read();
+ response = blob(1);
+ while( b!= STK_OK){
+ if(b >= 0){
+ response.writen(b);
+ }
+ local b = serial.read();
+ }
+ return response;
+ }
+
+ function enable_programming(){
+ response = send_command(PROG-ENABLE);
+ if (response[2] != STK_OK){
//we expect the third byte recieved to be the same as the second byte we sent; if not, we are not in sync
throw "Error in programming enable: not in sync";
}
}
+ function exit_programming(){
+ response = send_command(STK_LEAVE_PROGMODE);
+ if (response[2] != STK_OK){
+ //we expect the third byte recieved to be the same as the second byte we sent; if not, we are not in sync
+ throw "Error in programming enable: not in sync";
+ }
+ }
+
+ function program(){
+ extractAddressAndData(hex_info);
+ }
+
function verify_signature(){
//we need to see if the device signature is correct
//we DO NOT want to program an ATTiny8 as if it was an ATMega328
- local observed_sig = blob(3);
- for (local i=0; i<3; i++){
- spi.write(SIGNATURE-CHECK + 0);
- observed_sig[i] = spi.readblob(1)//we expect a single blob response
- }
+ observed_sig = send_command(SIGNATURE_CHECK);
+ observed_sig = observed_sig.slice(0, 3);
if (target.SIG != observed_sig){
throw "Target device signature was incorrect. Expected "+target.SIG+" but recieved "+observed_sig;
}
@@ -81,34 +105,8 @@ class ArduinoProgrammer {
//everything checked out!
}
- function chip_erase(){
- //erase the flash programming
- //*might* also delete the EEPROM programming, but that depends on fuse bits
- //you should make sure before overwritting EEPROM
- //default Arduino fuse doesn't overwrite EEPROM
- spi.write(CHIP-ERASE);
- //send the erase command
- imp.sleep(CHIP-ERASE-DELAY);
- //wait for the chip to erase before doing anything else
- }
- function write_flash(){
-
- //esentially, we move from page address to page address until we run out of .hex to write
- //then we finish up
- //note that due to memory constraints on the Imp, we don't load the entire .hex at the same time
- //so we verify the bit of the .hex we have, then grab some more
-
- for (local i=0; i<=hex_info.size; i+target.PAGE_SIZE){
- //let's write this page to Flash memory!
- //first send LOAD PROGRAM MEMORY PAGE instruction
- spi.write();
- //then send the data
- spi.write();
- //then issue WRITE PROGRAM MEMORY PAGE instruction
- imp.sleep(0.045); //wait 4.5ms until the flash location has been written to
- }
- }
}
+
//hex, ArduinoProgrammer class are garbage collected after run
//hex can use up signifigant portion of user-memory
@@ -116,6 +114,114 @@ class ArduinoProgrammer {
//There are 40KB of user-code-RAM; 34Kb/40Kb used by Hex File AND more RAM needed for other aspects of the code
//I will look into splitting hex into chunks and downloading chunks as needed later
agent.on("avr firmware change", function (target, hex_info){
- prog = ArduinoProgrammer(target, hex_info);
+ local prog = ArduinoProgrammer(target, hex_info);
prog.programAVR();
-});
+ agent.send("avr reflash success");
+ //because this is local, the prog constructor should be garbage collected after this function is ran...
+});
+
+//start hex stuff:
+//This file is for understanding .hex files
+//It has two main functions
+//The first function breaks up the .hex by line breaks
+//The second analyzes each line, and turns the .hex into a binary blob
+
+//http://www.sbprojects.com/knowledge/fileformats/intelhex.php
+
+function splitHex(hexString){
+ //split each instruction in the hex File by newline instructions (0x0D0A)
+ local lines = String.split(hexString, "\r\n");
+ return lines;
+}
+
+function extractAddressAndData(hexString){
+ local lines = splitHex(hexString);
+ for (local i=0; i<lines.len(); i++){
+ local result = understandHex(lines[i]);
+ }
+}
+
+function convertHexToInteger(hex){
+ //expects a string representing the hexidecimal of a single byte
+ if (! len(hex) == 2){
+ raise ("Error converting hexadecimal: length incorrect. Expected 2 chars to represent a single byte");
+ }
+
+ // see http://devwiki.electricimp.com/doku.php?id=webcolor&s[]=hex
+ //I basically took the above, and add extra checks
+
+ local result = 0;
+ local shift = hex.len() * 4;
+ for (local d=0; d<hex.len(); d++){
+ local digit;
+
+ // convert ascii such that it is case insensitive
+ if(hex[d] >= 0x61 && hex[d] <= 0x66){ //if the hex digit is greater than or equal to 'a', but less than or greater than 'f'
+ digit = hex[d] - 0x57;
+ }
+ else if(hex[d] >= 0x41 && hex[d] <= 0x41){//if the hex digit is less than or equal to 'A', but less than or greater than 'F'
+ digit = hex[d] - 0x37; //shift value downwards by 55 (decimal), such that 'A' = 10 (decimal), and 'F' = 16
+ }
+ else if (hex[d] >= 0x30 && hex[d] <= 0x39){ //if the digit is greater or equal to 0, but less than or equal to 9
+ digit = hex[d] - 0x30; //move the value downwards by 48 (decimal), such that 0 (ascii) represents 0 (integer), and 9 (ascii) represents 9 (integer)
+ }
+ else{
+ raise (format("Error in hexadecimal conversion: value outside of expected ranges (0-9, A-F, a-f). Value was %x", hex[d]));
+ }
+
+ // Accumulate digit
+ shift -= 4;
+ result += digit << shift;
+ }
+ return result;
+}
+
+function integerToBlob(integer){
+ local blob_result = blob(1);
+ blob_result.writen(integer, 'b'); //write the integer result as an unsigned 8-bit integer (basically, a single byte)
+ return blob_result;
+}
+
+//needs hex to be split by line...
+function understandHex(hexLine){
+ //Recall that we come close to the Max RAM on the Imp when programming, so saving the table space is worth it.
+ if (!hexLine[0] == ':'){
+ raise ("Error: hex format not correct, must contain : on start of each line");
+ }
+ local byteCount = convertHexToInteger(hexLine.splice(1,2) );
+ local address = blob(2);
+ address.writen(convertHexToInteger(hexLine.splice(3,4) ), 'b');
+ address.writen(convertHexToInteger(hexLine.splice(5,6) ), 'b');
+ local recordType = hexLine[8];
+ local dataPayload = blob(byteCount);
+ for (local i =0; i<byteCount; i++){
+ local datum = convertHexToInteger(hexLine.splice(8 + i, 9 + i) );
+ dataPayload.writen(datum, 'b');
+ }
+ //local checksum = convertHexToInteger(hexLine[byteCount + 10: byteCount + 11]);
+ //I am not checking the checksum, HTTPS checksum already ensures integrity
+ //if the checksum fails, we have bigger problems, so let's just assume it would have never failed
+ if (recordType = '0'){
+ //record is data, program chip...
+ send_command(STK_LOAD_ADDRESS + address);
+ //#55#00#00#20 STK_LOAD_ADDRESS, 0×0000(address location)
+ //now write the data to the address...
+ send_command(STK_PROGRAM_PAGE + byteCount + 'F' + dataPayload);
+ //STK_PROGRAM_PAGE, 0×0080 (page size), ‘F’(flash memory), data bytes…,SYNC_CRC_EOP
+ imp.sleep(0.045); //wait 4.5ms until the flash location has been written to
+ }
+ else if (recordType = '1'){
+ //this is the last record. It's empty, should have no data, checksum should be 'FF'
+ //assert byteCount is 00
+ if (byteCount == 00){
+ exitProgramMode();
+ }
+ else{
+ raise ("Error: final record contains more than 0 bytes. Abort.");
+ }
+ }
+ else{
+ raise ("Error: in hex format, Extended Address modes NOT accepted. Record type must be 0x00 or 0x01");
+ }
+ return results;
+}
47 hex-files.c
View
@@ -6,10 +6,18 @@
//http://www.sbprojects.com/knowledge/fileformats/intelhex.php
function splitHex(hexString){
- local lines = String.split(hexString, "\n");
+ //split each instruction in the hex File by newline instructions (0x0D0A)
+ local lines = String.split(hexString, "\r\n");
return lines;
}
+function extractAddressAndData(hexString){
+ local lines = splitHex(hexString);
+ for (line in lines){
+ local result = understandHex(line);
+ }
+}
+
function convertHexToInteger(hex){
//expects a string representing the hexidecimal of a single byte
if (! len(hex) = 2){
@@ -47,35 +55,50 @@ function convertHexToInteger(hex){
function integerToBlob(integer){
local blob_result = blob(1);
- blob_result.writen(integer, 'b'); //write the integer result as an unsigned 8-bit integer (basically, a single byte!)
+ blob_result.writen(integer, 'b'); //write the integer result as an unsigned 8-bit integer (basically, a single byte)
return blob_result;
}
+//needs hex to be split by line...
function understandHex(hexLine){
+ //Recall that we come close to the Max RAM on the Imp when programming, so saving the table space is worth it.
if (!hexLine[0] == ':'){
raise ("Error: hex format not correct, must contain : on start of each line");
}
- local length = len(hexLine);
local byteCount = convertHexToInteger(hexLine[1:2]);
- local addressField = blob(2);
- addressField.writen(convertHexToInteger(hexLine[3:4]), 'b');
- addressField.writen(convertHexToInteger(hexLine[5:6]), 'b');
+ local address = blob(2);
+ address.writen(convertHexToInteger(hexLine[3:4]), 'b');
+ address.writen(convertHexToInteger(hexLine[5:6]), 'b');
local recordType = hexLine[8];
- local data = blob(0);
+ local dataPayload = blob(byteCount);
for (local i =0; i<byteCount; i++){
local datum = convertHexToInteger(hexLine[8 + i: 9 + i]);
- data.writen(datum, 'b');
+ dataPayload.writen(datum, 'b');
}
- local checksum = convertHexToInteger(hexLine[byteCount + 10: byteCount + 11]);
- //I am not checking the checksum
+ //local checksum = convertHexToInteger(hexLine[byteCount + 10: byteCount + 11]);
+ //I am not checking the checksum, HTTPS checksum already ensures integrity
+ //if the checksum fails, we have bigger problems, so let's just assume it would have never failed
if (recordType = '0'){
- //record is data, nothing special here
+ //record is data, program chip...
+ spi.write(STK_LOAD_ADDRESS + address + SYNC_CRC_EOP);
+ //#55#00#00#20 STK_LOAD_ADDRESS, 0×0000(address location), SYNC_CRC_EOP
+ //now write the data to the address...
+ spi.write(STK_PROGRAM_PAGE + byteCount + 'F' + dataPayload + SYNC_CRC_EOP);
+ //STK_PROGRAM_PAGE, 0×0080 (page size), ‘F’(flash memory), data bytes…,SYNC_CRC_EOP
+ imp.sleep(0.045); //wait 4.5ms until the flash location has been written to
}
else if (recordType = '1'){
//this is the last record. It's empty, should have no data, checksum should be 'FF'
+ //assert byteCount is 00
+ if (byteCount == 00){
+ exitProgramMode();
+ }
+ else{
+ raise ("Error: final record contains more than 0 bytes. Abort.");
+ }
}
else{
raise ("Error: in hex format, Extended Address modes NOT accepted. Record type must be 0x00 or 0x01");
}
- return data;
+ return results;
}
6 hexFileBreakdown.txt
View
@@ -0,0 +1,6 @@
+:100000000C9462000C948A000C948A000C948A0070
+
+:10 - bytelength (16)
+0000 - lfash address
+000C9462000C948A000C948A000C948A00 - data (16 bytes)
+70 - checksum of data
123 server.c
View
@@ -1,7 +1,7 @@
/*
-* Secret Robot
-* Reprogram an arduino anywhere!
-* Uses an Electric Imp, some hardware, some code, and some magic.
+* Secret Robot
+* Reprogram an arduino anywhere!
+* Uses an Electric Imp, some hardware, some code, and some magic.
* All you need is a WiFi connection at your Arduino deploy location.
*
*
@@ -18,46 +18,37 @@
*/
//define per-user constants
-const OWNER_NAME = "generjones"; //your Github user-name
+const OWNER_NAME = "genejones"; //your Github user-name
const REPO_NAME = "blink"; //your Github REPO_NAME
const FILE_PATH = "./build/uno/firmware.hex"; //the path to the .hex file within the repo. By default, using the ino build-system, it should be './build/uno/firmware.hex'
const TARGET_NAME = "ATMEGA328P"; //the type of your AVR, choose among the targets table below. ATmega328P is typical for Arduino Uno and Diecemillia.
//can also be within a folder, e.g. 'hardware/avr/flash.hex'
-//heres some oAuth stuff
-//taken liberally from http://devwiki.electricimp.com/doku.php?id=example:howsthedaylooking
-//we use oAuth with Github so we can update statuses, and also not worry about quotas and the like
server.log("agent started on "+http.agenturl());
-const GITHUB_TOKEN = ""
-//see https://github.com/blog/1509-personal-api-tokens on how to generate the above
-
-
-const HOOK_SECRET = "You can't hack me! I'm invincible!"; //some random secret phrase for added protection from fake requests
-//don't share this with anyone!
-
+GITHUB_TOKEN <- "837acf5d5b4b2d6bab0daab04c48635c3a70f9e8";
//general constants. Don't modify unless you know what you are doing.
GITHUB_URL_BASE <- "https://api.github.com/repos/" + OWNER_NAME + "/" + REPO_NAME;
-
+server.log("running against " + GITHUB_URL_BASE);
//define device constants
//taken from 28.3 and 28.5 in the Atmel AVR doc
//signature is what we expect the value to be
//flash size is how many words are present
-//page_zie defines how many words are in each page
//each word is 2 bytes long, so a Flash Size of 1600 is 32 Kb
targets <- {
-"ATMEGA328P" : {"SIG":"\x1e\x95\x0f", "FLASH_SIZE":16384, "PAGE_SIZE":64},
-"ATMEGA328" : {"SIG":"\x1e\x95\x14", "FLASH_SIZE":16384, "PAGE_SIZE":64},
-"ATMEGA168A" : {"SIG":"\x1e\x94\x06", "FLASH_SIZE":8192, "PAGE_SIZE":64},
+"ATMEGA328P" : {"SIG":"\x1e\x95\x0f", "FLASH_SIZE":16384},
+"ATMEGA328" : {"SIG":"\x1e\x95\x14", "FLASH_SIZE":16384},
+"ATMEGA168A" : {"SIG":"\x1e\x94\x06", "FLASH_SIZE":8192},
}
function router(request, res){
try{
switch(request.path){
case "/updateAVR":
+ server.log("github request made...");
github_request(request, res)
default:
if (request.method == "OPTIONS" && request.path == ""){
@@ -92,53 +83,35 @@ function github_request(request, res){
//We will be diligent, wary, and awesome.
//Let no unhallowed code pass through.
- if (github.repository.owner.name == OWNER_NAME && github.secret == HOOK_SECRET){
+ if (github.repository.owner.name == OWNER_NAME){
//Alright Mr. Request...who sent you?
//Oh, I see from this note you carry that you were sent on my behalf by Github.
//And, you also carry the secret pass phrase me and Github setup a while ago...
//Hmm. Well, that's not enough proof. Let's see if Github backs up your story.
local canidateCommit = github.commits[0].id;
+ server.log("canidate Commit " + canidateCommit);
+ updateGithubStatus(canidateCommit, "pending", "Secret Robot is uploading everything now");
//Github, was the .hex file updated on my repository recently?
- hexFileInfoResponse <- http.get(GITHUB_URL_BASE + "contents/" + FILE_PATH, {"Accept":"application/vnd.github.raw", "User-Agent" : "Secret Robot/Imp Agent", "Authorization":"token "+GITHUB_TOKEN} ).sendsync();
+ server.log(ITHUB_URL_BASE + "/contents/" + FILE_PATH);
+ hexFileInfoResponse <- http.get(GITHUB_URL_BASE + "/contents/" + FILE_PATH, {"Accept":"application/vnd.github.raw", "User-Agent" : "Secret Robot/Imp Agent", "Authorization":getAuthority()} ).sendsync();
if (hexFileInfoResponse.statuscode == 200){
+ server.log("good response from github");
//I was able to reach out to my friend at Github. What did he say?
hexInfo <- http.jsondecode(hexFileInfoResponse.body);
+ server.log(hexFileInfoResponse.body);
if (hexInfo.sha == canidateCommit){
- //Good news, Mr. Request, Github says that my .hex file *was* updated and it matches your claimed commit ID
- //I guess everything checks out.
- //Holdup! How do I know that you aren't just a repeated message?
- //I know! I'll check to see if I already wrote this commit ID.
- //If I haven't, then you are totally legit, and I'll go about your business.
- if ("lastCommit" in server.permanent){
- if (server.permanent.lastCommit != canidateCommit){
- //OK, I haven't written this commit yet.
- //Sorry for the bother, Mr. Request.
- //I'm going to jot down your commit ID so I don't forget I already let you in...
- updatePermanent("lastCommit", canidateCommit);
- //I'll get right on that update for you:
- update_avr(hexInfo.bindenv(this));
- }
- else{
- raise ("You imposter! I already wrote that commit! Go away!");
- }
- }
- else{
- //Huh. That's embarrassing...
- //I haven't actually written any .hex files yet...
- //I guess I'll trust you, just this once.
- //But I'm going to write down your commit ID, and it's never going to happen again, OK?
- updatePermanent("lastCommit", canidateCommit);
- //All right, let's get to the .hex writing!
- update_avr(hexInfo.html_url);
- }
+ update_avr(hexInfo.bindenv(this));
+ //All right, let's get to the .hex writing!
+ //update_avr(hexInfo.html_url);
}
}
+ else{server.log(hexFileInfoResponse.body + hexFileInfoResponse.statuscode);}
}
res.send(200, "Hex Updated");
- }
- catch (e){
- res.send(200, "Are you a hacker? Your JSON is all wrong: "+e);
- }
+ }
+ catch (e){
+ res.send(200, "Are you a hacker? Your JSON is all wrong: "+e);
+ }
case "OPTIONS":
res.header("ALLOW", "POST,OPTIONS");
res.send(200, "Allowed methods are POST. POST should be JSON formated according to <a href='https://help.github.com/articles/post-receive-hooks'>Github</a>. We check with Github to ensure a valid commit, so don't try anything funny.");
@@ -154,6 +127,7 @@ function update_avr(info){
//and "length" as well, which we use to determine the length, funnily enough
try{
//alright, let's get started by telling Github that we are starting the deploy process
+ server.log("updating the avr...");
updateGithubStatus(info.sha, "pending", "Rascal is on the job!");
//this provides a nice, easy wasy to see the status of our deploy
@@ -161,10 +135,11 @@ function update_avr(info){
//find out what our device is, and it's capabilities
if (info.size > target_properties.size){
//our target has too small of a flash memory
- //this should have gotten caught by the GCC process
+ //this should have gotten caught by the Garbage collection process
raise ("Flash memory smaller than flash program");
}
+ server.log("sending over to the Imp");
device.send("avr firmware change", target_properties, info); //just send the code right over to the Imp
//it's in his hands now.
@@ -186,17 +161,15 @@ function update_avr(info){
}
function updateGithubStatus(commitID, status, description){
- local headers = {"User-Agent" : "Secret Robot/Imp Agent", "Authorization":"token "+GITHUB_TOKEN};
+ local headers = {"User-Agent" : "Secret Robot/Imp Agent", "Authorization":getAuthority()};
local payload = http.jsonencode({"state":status, "description":description});
- http.post(GITHUB_URL_BASE + "statuses/" + commitID, headers, payload).sendsync();
-}
-
-function updatePermanent(name, value){
- //used so server.permanent isn't overridden with an empty table
- //server.log("adding/changing " +name + " to " + value);
- cachedPerm = server.permanent;
- cachedPerm <- {name = value};
- server.setpermanentvalues(cachedPerm);
+ statusUpdatedRequest <- http.post(GITHUB_URL_BASE + "/statuses/" + commitID, headers, payload).sendsync();
+ if (statusUpdatedRequest.statuscode == 201){
+ server.log("Updated successfully");
+ }
+ else{
+ server.log(statusUpdatedRequest.body);
+ }
}
function setUpHook(){
@@ -212,12 +185,24 @@ function setUpHook(){
"config": {
"url" : http.agenturl()+"/updateAVR",
"content_type": "json",
- "secret": HOOK_SECRET
}
});
- response <- http.post(GITHUB_URL_BASE + "hooks/" {"User-Agent" : "Secret Robot/Imp Agent", "Authorization":"token "+GITHUB_TOKEN}, body).sendsync();
- if (! response.statuscode == 201){
- server.log("Hook was not setup correctly");
+ response <- http.post(GITHUB_URL_BASE + "/hooks" {"User-Agent" : "Secret Robot/Imp Agent", "Authorization":getAuthority()}, body).sendsync();
+ switch(response.statuscode){
+ case 201:
+ server.log("Hook was setup correctly!");
+ break;
+ case 422:
+ server.log("Hook already exists on this repository");
+ break;
+ default:
+ server.log("Error occured within " + response.statuscode);
+ break;
}
- updatePermanent("hookSetup", true);
-}
+}
+
+function getAuthority(){
+ return "Basic " + http.base64encode(OWNER_NAME + ":" + GITHUB_TOKEN);
+}
+
+//setUpHook();
Please sign in to comment.
Something went wrong with that request. Please try again.