Permalink
Browse files

very, very, very close to working

Stripped out Github logic for now.

Data now sent in chunks from the agent to the device; server performs
most of the heavy lifting of decoding the hex, line splits, etc.

Agent code is working.
Device code a little finicky, but very close to working.
  • Loading branch information...
1 parent 5cb883e commit 67f1349c3af9dac505858fb6841a4035ff0d392f Gene Jones committed Oct 4, 2013
Showing with 201 additions and 299 deletions.
  1. +78 −128 flashChip.c
  2. +123 −171 server.c
View
@@ -1,4 +1,4 @@
-/*
+/*
* Secret Robot
* Reprogram an arduino anywhere!
* Uses an Electric Imp, some hardware, some code, and some magic.
@@ -11,6 +11,21 @@
*released under CC-A 3.0; no guarantee of any kind is made for this code
*/
+//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
+//each word is 2 bytes long, so a Flash Size of 1600 is 32 Kb
+targets <- {
+"ATMEGA328P" : {"SIG":"\x1e\x95\x0f", "FLASH_SIZE":16384},
+"ATMEGA328" : {"SIG":"\x1e\x95\x14", "FLASH_SIZE":16384},
+"ATMEGA168A" : {"SIG":"\x1e\x94\x06", "FLASH_SIZE":8192},
+}
+
+imp.configure("8-bit-internet", [], []);
+server.show(format("Signal: %d dBm", imp.rssi()));
+
PROGRAM_SERIAL_SPEED <- 115200; //the baud for UNO programming
//Duemilanove 328P requires 57600, 168P based programm at 19200 baud
@@ -24,35 +39,55 @@ SYNC_CHECK_PROG <- 0x53;
STK_LOAD_ADDRESS <- 0x55;
STK_LEAVE_PROGMODE <- 0x51;
+agent.on("programModeBegin", function(t){
+ server.log("got told to do a program by the agent");
+ prog <- ArduinoProgrammer();
+ //make sure we make it a permanent class to avoid garbage collection until everything is better...
+ prog.programAVR();
+ //deltete prog here, such that it is garage collected...
+});
+
class ArduinoProgrammer {
- constructor(target, hex_info){
+
+ resetPin = hardware.pin7;
+ serial = hardware.uart12.configure(PROGRAM_SERIAL_SPEED, 8, PARITY_NONE, 1, NO_CTSRTS);
+ statusLEDPin = hardware.pin8;
+ progLEDPin = hardware.pin9;
+
attempt = 0; //the programming attempt we are currently on
+
+ constructor(){
//configure hardware for our usage
hardware.pin7.configure(DIGITAL_OUT_OD_PULLUP) //this will be our reset pin
- resetPin = hardware.pin7;
- serial = hardware.uart12.configure(PROGRAM_SERIAL_SPEED, 8, PARITY_NONE, 1, NO_CTSRTS);
- hex_info = hex_info;
- target = target;
+ hardware.pin8.configure(DIGITAL_OUT) //this will be our LED pin
+ hardware.pin9.configure(DIGITAL_OUT) //this will be our LED pin
+
+ //blank out the LEDs to start with...
+ progLEDPin.write(0);
+ statusLEDPin.write(0);
+
+ agent.on("next_chunk", program.bindenv(this));
}
function programAVR(){
server.log("Starting AVR programming process now");
try{
resetAVR();
enable_programming();
- verify_signature();
+ //verify_signature();
program();
server.log("Successfully programmed AVR with new .hex file");
}
catch (error) {
server.log("ERROR. Programming failed due to "+error);
attempt++;
if (attempt<3){
- programAVR(); //attempt to program again, but only if this is our second or less attempt
+ program(); //attempt to program again, but only if this is our second or less attempt
}
}
}
function resetAVR(){
+ progLEDPin.write(1); //let the user know a program is in progress
resetPin.write(0); //pull pin7 low to reset the system
imp.sleep(0.25); //and wait .25s to ensure the AVR resets
resetPin.write(1); //
@@ -74,11 +109,12 @@ class ArduinoProgrammer {
}
function enable_programming(){
- response = send_command(PROG-ENABLE);
+ 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";
}
+ server.log("arduino ready for programming!");
}
function exit_programming(){
@@ -87,10 +123,27 @@ class ArduinoProgrammer {
//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";
}
+ progLEDPin.write(0); //let the user know a program is finished
+ agent.send("avr reflash success", "great success!");
}
- function program(){
- extractAddressAndData(hex_info);
+ function program(chunk){
+ statusLEDPin.write(1);
+ local finished = 0;
+ for (local i=0; i<len(chunk); i++){
+ local progResult = progLine(chunk[i]);
+ if(progResult == "exitProgMode"){
+ finished = 1;
+ break;
+ }
+ }
+ statusLEDPin.write(0);
+ if (!finished){
+ agent.send("next_chunk", "please");
+ }
+ else{
+ exit_programming();
+ }
}
function verify_signature(){
@@ -104,124 +157,21 @@ class ArduinoProgrammer {
return 1;
//everything checked out!
}
-
-}
-
-//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){
- 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
+ function progLine(hexLine){
+ //program each individual line of the code with this!
+ if (hexLine.recordType = '0'){
+ //record is data, program chip...
+ send_command(STK_LOAD_ADDRESS + hexLine.address);
+ //#55#00#00#20 STK_LOAD_ADDRESS, 0װ000(address location)
+ //now write the data to the address...
+ send_command(STK_PROGRAM_PAGE + byteCount + 'F' + hexLine.dataPayload);
+ //STK_PROGRAM_PAGE, 0װ080 (page size), ҆Ҩflash memory), data bytesŬSYNC_CRC_EOP
+ imp.sleep(0.045); //wait 4.5ms until the flash location has been written to
+ return 1;
}
- 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 if (hexLine.recordType = '1'){
+ //finalize programming...
+ return "exitProgMode";
}
- 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;
}
Oops, something went wrong.

0 comments on commit 67f1349

Please sign in to comment.