A fork of mAVRISP by Aaron Berk. This version does not use a local file system to hold the AVR program. Instead it uses a serial connection to a PC and a python script to send the AVR program to the mbed.

Dependencies:   mbed

Fork of mAVRISP by Aaron Berk

Revision:
4:ceee1eb7062e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AVR910_Serial.cpp	Sat Jan 31 22:44:09 2015 +0000
@@ -0,0 +1,336 @@
+/**
+ * @author Aaron Berk, Jeroen Voogd
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2010 Aaron Berk
+ * Copyright (c) 2015 Jeroen Voogd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * Program AVR chips with the AVR910 ISP (in-system programming) protocol,
+ * using an mbed. The version of Aaron Berk used a local file system, this version
+ * useses a python script to feed the data via a serial connection.
+ *
+ * AVR910 Application Note:
+ *
+ * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf
+ */
+
+/**
+ * Includes
+ */
+#include "AVR910_Serial.h"
+
+Serial debug(USBTX, USBRX);
+
+AVR910::AVR910(PinName mosi,
+               PinName miso,
+               PinName sclk,
+               PinName nReset) : spi_(mosi, miso, sclk), nReset_(nReset)
+{
+
+    //Slow frequency as default to ensure no errors from
+    //trying to run it too fast. Increase as appropriate.
+    spi_.frequency(32000);
+    spi_.format(8, 0);
+
+    int response = 0;
+
+    //Enter serial programming mode by pulling reset line low.
+    nReset_ = 0;
+
+    //Wait 20ms before issuing first command.
+    wait_ms(20);
+
+    //Issue a programming enable command.
+    response = enableProgramming();
+
+    //TODO: introduce a timeout.
+    while (response < 0) {
+
+        //Give nReset a positive pulse.
+        nReset_ = 1;
+        wait_ms(20);
+        nReset_ = 0;
+        wait_ms(20);
+
+        //Issue another programming enable.
+        response = enableProgramming();
+    }
+}
+
+
+int AVR910::programData(char* myData, int dataSize, int pageSize, int numPages)
+{
+
+    //Clear memory contents.
+    chipErase();
+
+    char pageOffset = 0;
+    int  pageNumber = 0;
+    int  c          = 0;
+    int  highLow    = 0;
+
+    //In this version we're always dealing with paged memory.
+
+    for (int i=0; i<dataSize; i++) {
+        c = myData[i];
+        //Page is fully loaded, time to write it to flash.
+        if (pageOffset == (pageSize)) {
+            writeFlashMemoryPage(pageNumber);
+
+            pageNumber++;
+            if (pageNumber > numPages) {
+                break;
+            }
+            pageOffset = 0;
+        }
+
+        //Write low byte.
+        if (highLow == 0) {
+            loadMemoryPage(WRITE_LOW_BYTE, pageOffset, c);
+            highLow = 1;
+        }
+        //Write high byte.
+        else {
+            loadMemoryPage(WRITE_HIGH_BYTE, pageOffset, c);
+            highLow = 0;
+            pageOffset++;
+        }
+
+    }
+
+    //We might have partially filled up a page.
+    writeFlashMemoryPage(pageNumber);
+
+    int success = -1;
+    success = checkMemoryData(pageNumber, myData, dataSize);
+
+    //Leave serial programming mode by pulling reset line high.
+    nReset_ = 1;
+
+    return success;
+
+}
+void AVR910::setFrequency(int frequency)
+{
+
+    spi_.frequency(frequency);
+
+}
+
+int AVR910::enableProgramming(void)
+{
+
+    int response = 0;
+    int error    = 0;
+
+    //Programming Enable Command: 0xAC, 0x53, 0x00, 0x00
+    //Byte two echo'd back in byte three.
+    spi_.write(0xAC);
+
+    spi_.write(0x53);
+
+    response = spi_.write(0x00);
+
+    if (response == 0x53) {
+        error =  0;
+    } else {
+        error = -1;
+    }
+
+    response = spi_.write(0x00);
+    
+    return error;
+
+}
+
+void AVR910::poll(void)
+{
+
+    int response = 0;
+
+    do {
+        spi_.write(0xF0);
+        spi_.write(0x00);
+        spi_.write(0x00);
+        response = spi_.write(0x00);
+    } while ((response & 0x01) != 0);
+
+}
+
+int AVR910::readVendorCode(void)
+{
+
+    int response = 0;
+
+    //Issue read signature byte command.
+    //Address 0x00 is vendor code.
+    spi_.write(0x30);
+    spi_.write(0x00);
+    spi_.write(0x00);
+    response = spi_.write(0x00);
+   
+    return response;
+
+}
+
+int AVR910::readPartFamilyAndFlashSize(void)
+{
+
+    int response = 0;
+
+    //Issue read signature byte command.
+    //Address 0x01 is part family and flash size code.
+    spi_.write(0x30);
+    spi_.write(0x00);
+    spi_.write(0x01);
+    response = spi_.write(0x00);
+
+    return response;
+
+}
+
+int AVR910::readPartNumber(void)
+{
+
+    int response = 0;
+
+    //Issue read signature byte command.
+    //Address 0x02 is part number code.
+    spi_.write(0x30);
+    spi_.write(0x00);
+    spi_.write(0x02);
+    response = spi_.write(0x00);
+
+    return response;
+
+}
+
+void AVR910::chipErase(void)
+{
+
+    //Issue chip erase command.
+    spi_.write(0xAC);
+    spi_.write(0x80);
+    spi_.write(0x00);
+    spi_.write(0x00);
+
+    poll();
+
+    //Temporarily release reset line.
+    nReset_ = 1;
+    nReset_ = 0;
+
+}
+
+void AVR910::loadMemoryPage(int highLow, char address, char data)
+{
+
+    spi_.write(highLow);
+    spi_.write(0x00);
+    spi_.write(address & 0x3F);
+    spi_.write(data);
+
+    poll();
+
+}
+
+void AVR910::writeFlashMemoryByte(int highLow, int address, char data)
+{
+
+    spi_.write(highLow);
+    spi_.write(address & 0xFF00 >> 8);
+    spi_.write(address & 0x00FF);
+    spi_.write(data);
+
+}
+
+void AVR910::writeFlashMemoryPage(char pageNumber)
+{
+
+    spi_.write(0x4C);
+    spi_.write((pageNumber >> 2) & 0x3F);
+    spi_.write((pageNumber & 0x03) << 6);
+    spi_.write(0x00);
+
+    poll();
+
+}
+
+char AVR910::readProgramMemory(int highLow, char pageNumber, char pageOffset)
+{
+
+    int response = 0;
+
+    spi_.write(highLow);
+    spi_.write((pageNumber >> 2) & 0x3F);
+    spi_.write(((pageNumber & 0x03) << 6) | (pageOffset & 0x3F));
+    response = spi_.write(0x00);
+
+    poll();
+
+    return response;
+
+}
+
+
+int AVR910::checkMemoryData(int numPages, char* myData, int dataSize)
+{
+    
+    int success  = 0;
+    int response = 0;
+    char c       = 0;
+
+    // start at the beginning of the original data
+    int dpoint=0;
+    
+    for (int i = 0; i <= numPages; i++) {
+        for (int j = 0; j < PAGE_SIZE; j++) {
+
+            c = myData[dpoint];
+            //Read program memory low byte.
+            response = readProgramMemory(READ_LOW_BYTE, i, j);
+            if ( c != response ) {
+                success = -1;
+            }
+            
+            // next data item to check, break if all data has been checked
+            dpoint++;
+            if (dpoint==dataSize) break;
+            c = myData[dpoint];
+            
+            //Read program memory high byte.
+            response = readProgramMemory(READ_HIGH_BYTE, i, j);
+            if ( c != response ) {
+                success = -1;
+            }
+            
+            // next data item to check, break if all data has been checked
+            dpoint++;
+            if (dpoint==dataSize) break;
+        }
+    }
+
+    return success;
+
+}