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.
Fork of mAVRISP by
Revision 4:ceee1eb7062e, committed 2015-01-31
- Comitter:
- jeroenmbed
- Date:
- Sat Jan 31 22:44:09 2015 +0000
- Parent:
- 3:df6782d01720
- Commit message:
- Cleaned up.
Changed in this revision
diff -r df6782d01720 -r ceee1eb7062e AVR910.cpp --- a/AVR910.cpp Sat Jan 31 21:54:05 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,516 +0,0 @@ -/** - * @author Aaron Berk - * - * @section LICENSE - * - * Copyright (c) 2010 Aaron Berk - * - * 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. - * - * AVR910 Application Note: - * - * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf - */ - -/** - * Includes - */ -#include "AVR910.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(5000); - 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(); - //printf("R=%d\n\r",response); - - //Simple debugging to see if we get trapped - //in an infinite loop. - - //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(); - // printf("R=%d\n\r",response); - - } - - -} - -int AVR910::program(FILE* binary, int pageSize, int numPages) -{ - - //Clear memory contents. - chipErase(); - - char pageOffset = 0; - int pageNumber = 0; - int address = 0; - int c = 0; - int highLow = 0; - - //We're dealing with paged memory. - if (numPages > 1) { - - while ((c = getc(binary)) != EOF) { - - //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're dealing with non-paged memory. - else { - - while ((c = getc(binary)) != EOF) { - - //Write low byte. - if (highLow == 0) { - writeFlashMemoryByte(WRITE_LOW_FLASH_BYTE, address, c); - highLow = 1; - } - //Write high byte. - else { - writeFlashMemoryByte(WRITE_HIGH_FLASH_BYTE, address, c); - highLow = 0; - address++; - - //Page size is our memory size in the non-paged memory case. - //Therefore if we've gone beyond our size break because we - //don't have any more room. - if (address > pageSize) { - break; - } - - } - - } - - } - - //We might have partially filled up a page. - writeFlashMemoryPage(pageNumber); - - int success = -1; - success = checkMemory(pageNumber, binary); - - //Leave serial programming mode by pulling reset line high. - nReset_ = 1; - - return success; - -} - -int AVR910::programData(char* myData, int fileSize, int pageSize, int numPages) -{ - - //Clear memory contents. - chipErase(); - - char pageOffset = 0; - int pageNumber = 0; - int address = 0; - int c = 0; - int highLow = 0; - - //We're dealing with paged memory. -// if (numPages > 1) { - - //while ((c = getc(binary)) != EOF) { - for (int i=0; i<fileSize; i++) { - c = myData[i]; - printf("p %d: 0x%02x\n",i, 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're dealing with non-paged memory. -// else { -// -// while ((c = getc(binary)) != EOF) { -// -// //Write low byte. -// if (highLow == 0) { -// writeFlashMemoryByte(WRITE_LOW_FLASH_BYTE, address, c); -// highLow = 1; -// } -// //Write high byte. -// else { -// writeFlashMemoryByte(WRITE_HIGH_FLASH_BYTE, address, c); -// highLow = 0; -// address++; -// -// //Page size is our memory size in the non-paged memory case. -// //Therefore if we've gone beyond our size break because we -// //don't have any more room. -// if (address > pageSize) { -// break; -// } -// -// } -// -// } - -// } - - //We might have partially filled up a page. - writeFlashMemoryPage(pageNumber); - - int success = -1; - //success = checkMemory(pageNumber, binary); - printf("Going to check memory\n"); - success = checkMemoryData(pageNumber, myData, fileSize); - - //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. - response = spi_.write(0xAC); - //printf("enableProgramming resp (should be ??) = %x\n\r",response); - - response = spi_.write(0x53); - //printf("enableProgramming resp (should be 0xAC) = %x\n\r",response); - - response = spi_.write(0x00); - //printf("enableProgramming resp (should be 0x53) = %x\n\r",response); - - if (response == 0x53) { - error = 0; - } else { - error = -1; - } - - response = spi_.write(0x00); - //printf("enableProgramming resp (should be 0x00) = %x\n\r",response); - - 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); - //printf("r1=%d\n\r",spi_.write(0x00)); - //printf("r2=%d\n\r",spi_.write(0x00)); - response = spi_.write(0x00); - //printf("r3=%d\n\r",response); - - 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::checkMemory(int numPages, FILE* binary) -{ - - int success = 0; - int response = 0; - char c = 0; - - //Go back to the beginning of the binary file. - fseek(binary, 0, SEEK_SET); - - for (int i = 0; i < numPages; i++) { - for (int j = 0; j < PAGE_SIZE; j++) { - c = getc(binary); - //Read program memory low byte. - response = readProgramMemory(READ_LOW_BYTE, i, j); - //debug.printf("Low byte: 0x%02x\n", response); - if ( c != response ) { - // debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response); - // debug.printf("Correct byte is 0x%02x\n", c); - success = -1; - } - - c = getc(binary); - //Read program memory high byte. - response = readProgramMemory(READ_HIGH_BYTE, i, j); - //debug.printf("High byte: 0x%02x\n", response); - if ( c != response ) { - // debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response); - // debug.printf("Correct byte is 0x%02x\n", c); - success = -1; - } - } - } - - return success; - -} - - -int AVR910::checkMemoryData(int numPages, char* myData, int fileSize) -{ - - int success = 0; - int response = 0; - char c = 0; - - //Go back to the beginning of the binary file. - //fseek(binary, 0, SEEK_SET); - int dpoint=0; - printf("about to start checking (numPages=%d pagesize=%d)\n",numPages, PAGE_SIZE); - for (int i = 0; i <= numPages; i++) { - for (int j = 0; j < PAGE_SIZE; j++) { - - //c = getc(binary); - c = myData[dpoint]; - //Read program memory low byte. - response = readProgramMemory(READ_LOW_BYTE, i, j); - //debug.printf("Low byte: 0x%02x\n", response); - printf("dpoint=%d Page %i low byte %i: 0x%02x (should be 0x%02x)\n", dpoint-1, i, j, response,c); - if ( c != response ) { - // debug.printf("Page %i low byte %i: 0x%02x\n", i, j, response); - // debug.printf("Correct byte is 0x%02x\n", c); - success = -1; - } - - //c = getc(binary); - dpoint++; - if (dpoint==fileSize) break; - c = myData[dpoint]; - //Read program memory high byte. - response = readProgramMemory(READ_HIGH_BYTE, i, j); - printf("dpoint=%d Page %i high byte %i: 0x%02x (should be 0x%02x)\n", dpoint-1, i, j, response,c); - - //debug.printf("High byte: 0x%02x\n", response); - if ( c != response ) { - // debug.printf("Page %i high byte %i: 0x%02x\n", i, j, response); - //debug.printf("Correct byte is 0x%02x\n", c); - success = -1; - } - dpoint++; - if (dpoint==fileSize) break; - } - } - - return success; - -}
diff -r df6782d01720 -r ceee1eb7062e AVR910.h --- a/AVR910.h Sat Jan 31 21:54:05 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ -/** - * @author Aaron Berk - * - * @section LICENSE - * - * Copyright (c) 2010 Aaron Berk - * - * 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. - * - * AVR910 Application Note: - * - * http://www.atmel.com/dyn/resources/prod_documents/doc0943.pdf - */ - -#ifndef MBED_AVR910_H -#define MBED_AVR910_H - -/** - * Includes - */ -#include "mbed.h" - -/** - * Defines - */ - -#define PATH_TO_BINARY "local/T.bin" - -//Commands -#define ATMEL_VENDOR_CODE 0x1E -#define DEVICE_LOCKED 0x00 -#define WRITE_HIGH_BYTE 0x48 -#define WRITE_LOW_BYTE 0x40 -#define READ_HIGH_BYTE 0x28 -#define READ_LOW_BYTE 0x20 -#define WRITE_HIGH_FLASH_BYTE 0x68 -#define WRITE_LOW_FLASH_BYTE 0x60 - -#define PAGE_SIZE ATMEGA328P_PAGESIZE -#define NUM_PAGES ATMEGA328P_NUM_PAGES - -//ATMega328P -#define ATMEGA328P_PAGESIZE 64 //Size in words. -#define ATMEGA328P_NUM_PAGES 256 - -/** - * AVR910 ISP - */ -class AVR910 { - -public: - - /** - * Constructor. - * - * @param mosi mbed pin for MOSI SPI line. - * @param miso mbed pin for MISO SPI line. - * @param sclk mbed pin for SCLK SPI line. - * @param nReset mbed pin for not reset line on the ISP interface. - * - * Sends an enable programming command, allowing device registers to be - * read and commands sent. - */ - AVR910(PinName mosi, PinName miso, PinName sclk, PinName nReset); - - /** - * Program the AVR microcontroller connected to the mbed. - * - * Sends a chip erase command followed by writing the binary to the AVR - * page buffer and writing the page buffer to flash memory whenever it is - * full. - * - * @param binary File pointer to the binary file to be loaded onto the - * AVR microcontroller. - * @param pageSize The size of one page on the device in words. If the - * device does not use paged memory, set this as the size - * of memory of the device in words. - * @param numPages The number of pages on the device. If the device does - * not use paged memory, set this to 1 (default). - * - * @return 0 => AVR microcontroller programmed successfully. - * -1 => Problem during programming. - */ - int program(FILE* binary, int pageSize, int numPages = 1); - int programData(char* myData, int fileSize, int pageSize, int numPages = 1); - - /** - * Set the frequency of the SPI communication. - * - * (Wrapper for SPI::frequency) - * - * @param frequency Frequency of the SPI communication in hertz. - */ - void setFrequency(int frequency); - - /** - * Read the vendor code of the device. - * - * @return The vendor code - should be 0x1E for Atmel. - * 0x00 -> Device is locked. - */ - int readVendorCode(void); - - /** - * Read the part family and flash size of the device. - * - * @return Code indicating the family of AVR microcontrollers the device comes - * from and how much flash memory it contains. - * 0xFF -> Device code erased or target missing. - * 0x01 -> Device is locked. - */ - int readPartFamilyAndFlashSize(void); - - /** - * Read the part number. - * - * @return Code identifying the part number. - * 0xFF -> Device code erased or target missing. - * 0x02 -> Device is locked. - */ - int readPartNumber(void); - -private: - - /** - * Issue an enable programming command to the AVR microcontroller. - * - * @param 0 to indicate programming was enabled successfully. - * -1 to indicate programming was not enabled. - */ - int enableProgramming(void); - - /** - * Poll the device until it has finished its current operation. - */ - void poll(void); - - /** - * Issue a chip erase command to the AVR microcontroller. - */ - void chipErase(void); - - /** - * Load a byte into the memory page buffer. - * - * @param highLow Indicate whether the byte being loaded is a high or low - * byte. - * @param data The data byte to load. - */ - void loadMemoryPage(int highLow, char address, char data); - - /** - * Write a byte into the flash memory. - * - * @param highLow Indicate whether the byte being loaded is a high or low - * byte. - * @param address The address to load the byte at. - * @param data The data byte to load. - */ - void writeFlashMemoryByte(int highLow, int address, char data); - - /** - * Write the memory page buffer to flash memory. - * - * @param pageNumber The page number to write to in flash memory. - */ - void writeFlashMemoryPage(char pageNumber); - - /** - * Read a byte from program memory. - * - * @param highLow Indicate whether the byte being read is a low or high byte. - * @param pageNumber The page number to read from. - * @param pageOffset Address of byte in the page. - * - * @return The byte at the specified memory location. - */ - char readProgramMemory(int highLow, char pageNumber, char pageOffset); - - /** - * Check the binary has been written correctly. - * - * @param numPages The number of pages written to the AVR microcontroller. - * @param binary File pointer to the binary used. - * - * @return 0 -> No inconsistencies between binary file and AVR flash memory. - * -1 -> Binary file was not written correctly. - */ - int checkMemory(int numPages, FILE* binary); - int checkMemoryData(int numPages, char* myData, int fileSize); - - SPI spi_; - DigitalOut nReset_; - -}; - -#endif /* AVR910_H */
diff -r df6782d01720 -r ceee1eb7062e AVR910_Serial.cpp --- /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; + +}
diff -r df6782d01720 -r ceee1eb7062e AVR910_Serial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AVR910_Serial.h Sat Jan 31 22:44:09 2015 +0000 @@ -0,0 +1,216 @@ +/** + * * @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 + */ + +#ifndef MBED_AVR910_H +#define MBED_AVR910_H + +/** + * Includes + */ +#include "mbed.h" + +/** + * Defines + */ + +//Commands +#define ATMEL_VENDOR_CODE 0x1E +#define DEVICE_LOCKED 0x00 +#define WRITE_HIGH_BYTE 0x48 +#define WRITE_LOW_BYTE 0x40 +#define READ_HIGH_BYTE 0x28 +#define READ_LOW_BYTE 0x20 +#define WRITE_HIGH_FLASH_BYTE 0x68 +#define WRITE_LOW_FLASH_BYTE 0x60 + +#define PAGE_SIZE ATMEGA328P_PAGESIZE +#define NUM_PAGES ATMEGA328P_NUM_PAGES + +//ATMega328P +#define ATMEGA328P_PAGESIZE 64 //Size in words. +#define ATMEGA328P_NUM_PAGES 256 + +/** + * AVR910 ISP + */ +class AVR910 { + +public: + + /** + * Constructor. + * + * @param mosi mbed pin for MOSI SPI line. + * @param miso mbed pin for MISO SPI line. + * @param sclk mbed pin for SCLK SPI line. + * @param nReset mbed pin for not reset line on the ISP interface. + * + * Sends an enable programming command, allowing device registers to be + * read and commands sent. + */ + AVR910(PinName mosi, PinName miso, PinName sclk, PinName nReset); + + /** + * Program the AVR microcontroller connected to the mbed. + * + * Sends a chip erase command followed by writing the binary to the AVR + * page buffer and writing the page buffer to flash memory whenever it is + * full. + * @param myData The char array with the bytes of the program to be flashed. + * @param dataSize The number of bytes to be flashed + * @param pageSize The size of one page on the device in words. If the + * device does not use paged memory, set this as the size + * of memory of the device in words. + * @param numPages The number of pages on the device. If the device does + * not use paged memory, set this to 1 (default). + * + * @return 0 => AVR microcontroller programmed successfully. + * -1 => Problem during programming. + */ + int programData(char* myData, int dataSize, int pageSize, int numPages = 1); + + /** + * Set the frequency of the SPI communication. + * + * (Wrapper for SPI::frequency) + * + * @param frequency Frequency of the SPI communication in hertz. + */ + void setFrequency(int frequency); + + /** + * Read the vendor code of the device. + * + * @return The vendor code - should be 0x1E for Atmel. + * 0x00 -> Device is locked. + */ + int readVendorCode(void); + + /** + * Read the part family and flash size of the device. + * + * @return Code indicating the family of AVR microcontrollers the device comes + * from and how much flash memory it contains. + * 0xFF -> Device code erased or target missing. + * 0x01 -> Device is locked. + */ + int readPartFamilyAndFlashSize(void); + + /** + * Read the part number. + * + * @return Code identifying the part number. + * 0xFF -> Device code erased or target missing. + * 0x02 -> Device is locked. + */ + int readPartNumber(void); + +private: + + /** + * Issue an enable programming command to the AVR microcontroller. + * + * @param 0 to indicate programming was enabled successfully. + * -1 to indicate programming was not enabled. + */ + int enableProgramming(void); + + /** + * Poll the device until it has finished its current operation. + */ + void poll(void); + + /** + * Issue a chip erase command to the AVR microcontroller. + */ + void chipErase(void); + + /** + * Load a byte into the memory page buffer. + * + * @param highLow Indicate whether the byte being loaded is a high or low + * byte. + * @param data The data byte to load. + */ + void loadMemoryPage(int highLow, char address, char data); + + /** + * Write a byte into the flash memory. + * + * @param highLow Indicate whether the byte being loaded is a high or low + * byte. + * @param address The address to load the byte at. + * @param data The data byte to load. + */ + void writeFlashMemoryByte(int highLow, int address, char data); + + /** + * Write the memory page buffer to flash memory. + * + * @param pageNumber The page number to write to in flash memory. + */ + void writeFlashMemoryPage(char pageNumber); + + /** + * Read a byte from program memory. + * + * @param highLow Indicate whether the byte being read is a low or high byte. + * @param pageNumber The page number to read from. + * @param pageOffset Address of byte in the page. + * + * @return The byte at the specified memory location. + */ + char readProgramMemory(int highLow, char pageNumber, char pageOffset); + + /** + * Check the binary has been written correctly. + * + * @param numPages The number of pages written to the AVR microcontroller. + * @param myData The char array with the bytes of the program to be flashed. + * @param dataSize The number of bytes to be flashed + * + * @return 0 -> No inconsistencies between binary file and AVR flash memory. + * -1 -> Binary file was not written correctly. + */ + int checkMemoryData(int numPages, char* myData, int dataSize); + + SPI spi_; + DigitalOut nReset_; + +}; + +#endif /* AVR910_H */
diff -r df6782d01720 -r ceee1eb7062e main.cpp --- a/main.cpp Sat Jan 31 21:54:05 2015 +0000 +++ b/main.cpp Sat Jan 31 22:44:09 2015 +0000 @@ -1,29 +1,27 @@ /** * Program an AVR with an mbed. + * The mbed is connected to an ATMEGA328 via ISP. + * The PC has a serial connection to the mbed. + * The AVR program on the PC is send via the serial connection to the mbed using a python script. + * The mbed then programs the ATMEGA328 via ISP. */ -#include "AVR910.h" +#include "AVR910_Serial.h" +#include "mbed.h" -//LocalFileSystem local("local"); +// serial connection to a pc Serial pc(USBTX, USBRX); -//AVR910 mAVRISP(PA_7, PA_6, PA_5, PB_6); //mosi, miso, sclk, nreset. -//AVR910 mAVRISP(PB_5, PB_4, PB_3, PA_10); //mosi, miso, sclk, nreset. +// ISP programmer AVR910 mAVRISP(PB_15, PB_14, PB_13, PB_2); //mosi, miso, sclk, nreset. -DigitalOut working(LED1); - - int main() { - working = 1; int success = -1; int response = 0; - pc.printf("Starting\n"); - //Read the vendor code [0x1E == Atmel]. response = mAVRISP.readVendorCode(); - printf("vendorcode=%d\n",response); + if (response == ATMEL_VENDOR_CODE) { pc.printf("Microcontroller is an Atmel [0x%02x]\n", response); } else if (response == DEVICE_LOCKED) { @@ -58,58 +56,44 @@ pc.printf("Part number code is: 0x%02x\n", response); } - //Open binary file to write to AVR. - //FILE *fp = fopen(PATH_TO_BINARY, "rb"); + // signal the python script it can start sending the file size printf("@"); - + int hs, ls; while (!pc.readable()); hs = pc.getc(); - printf("hs=%d\n",hs); while (!pc.readable()); ls = pc.getc(); - printf("ls=%d\n",ls); - int fileSize = (hs<<8) + ls; - printf ("file size = %d\n", fileSize); + int dataSize = (hs<<8) + ls; + // signal the python script it can start sending the file printf("#"); - + char *myFile; - myFile = new char [fileSize]; + myFile = new char [dataSize]; int readChar=0; - while (readChar < fileSize) { + while (readChar < dataSize) { if (pc.readable()) { myFile[readChar]=pc.getc(); readChar++; } } - for (int i=0; i<fileSize; i++) { - printf("r %d: 0x%02x\n",i, myFile[i]); - } - wait_ms(1000); - success = mAVRISP.programData(myFile, fileSize, ATMEGA328P_PAGESIZE, ATMEGA328P_NUM_PAGES); -// if (fp == NULL) { -// pc.printf("Failed to open binary. Please check the file path\n"); -// return -1; -// } else { -// //Program it! -// pc.printf("Binary file opened successfully\n"); -// success = mAVRISP.program(fp, -// ATMEGA328P_PAGESIZE, -// ATMEGA328P_NUM_PAGES); -// fclose(fp); -// } + // program the atmega + success = mAVRISP.programData(myFile, dataSize, ATMEGA328P_PAGESIZE, ATMEGA328P_NUM_PAGES); if (success < 0) { printf("Programming failed.\n"); } else { printf("Programming was successful!\n"); } + + // signal the python script it can stop + printf("$"); } -/* Python file for on the pc: +/* Python script to be run on the pc: import serial import sys import os @@ -124,21 +108,18 @@ if s.readable(): c = s.read() if '@' in c: - print "Start sending file size\n" hs = (fileSize>>8) & 0xff s.write(chr(hs)) ls = fileSize & 0xff s.write(chr(ls)) - if '#' in c: - print "Start sending file\n" + elif '#' in c: with open(fileName, "rb") as f: byte = f.read(1) while byte != "": -# while not s.writable(): -# pass -# print "send: 0x",format(ord(byte),'02x') s.write(byte) byte = f.read(1) + elif '$' in c: + break else: sys.stdout.write(c) */ @@ -151,15 +132,21 @@ int main(void) { // Set Port D pins as all outputs -DDRD = 0xff; + DDRD = 0xff; // Set all Port D pins as HIGH -while (1) { -PORTD = 0xFF; -_delay_ms(500.); -PORTD = 0x00; -_delay_ms(500.); + while (1) { + PORTD = 0xFF; + _delay_ms(500.); + PORTD = 0x00; + _delay_ms(500.); + } + return 1; } -return 1; -} + +The avr test file needs to be compiled, linked (make + make hex) to get a .hex file. +This hex needs to be transformed into a .bin file via hex2bin. +Make sure the mbed is up and running with the code in this file. +Then uploaded the .bin via the python script: python scriptName programName.bin +A reset of the mbed board may be needed. */ \ No newline at end of file