Permalink
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...
1 parent 3326e46 commit bb215d5639fbf930aca387c5300522b940dc9d86 Gene Jones committed Aug 15, 2013
Showing with 1,032 additions and 178 deletions.
  1. +181 −0 Devices.h
  2. +0 −46 avrdude.c
  3. +491 −0 avriscp.c
  4. +108 −0 command.h
  5. +157 −51 flashChip.c
  6. +35 −12 hex-files.c
  7. +6 −0 hexFileBreakdown.txt
  8. +54 −69 server.c
View
181 Devices.h
@@ -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
View
46 avrdude.c
@@ -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;
View
491 avriscp.c
@@ -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);
+ }
+}
+
+
View
108 command.h
@@ -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 ]**************************
View
208 flashChip.c
@@ -11,36 +11,37 @@
*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){
attempt = 0; //the programming attempt we are currently on
//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;
}
function programAVR(){
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,64 +59,169 @@ 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;
}
return 1;
//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
//Max Flash size on an ATMEGA-328P is 34Kb
//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;
+}
View
47 hex-files.c
@@ -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;
}
View
6 hexFileBreakdown.txt
@@ -0,0 +1,6 @@
+:100000000C9462000C948A000C948A000C948A0070
+
+:10 - bytelength (16)
+0000 - lfash address
+000C9462000C948A000C948A000C948A00 - data (16 bytes)
+70 - checksum of data
View
123 server.c
@@ -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,17 +127,19 @@ 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
local target_properties = targets[TARGET_NAME];
//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();

0 comments on commit bb215d5

Please sign in to comment.