diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRBootloader.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRBootloader.cpp new file mode 100644 index 00000000..ae0fa6d7 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRBootloader.cpp @@ -0,0 +1,976 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRBootloader.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing an interface to the AVR bootloader + * described in Application Note AVR109. + * This class is derived from AVRPRogrammer. + * + * + ****************************************************************************/ +#include "AVRBootloader.hpp" + +#include +#include + +#define MEM_PROGRESS_GRANULARITY 256 // For use with progress indicator. + + +/* Constructor */ +AVRBootloader::AVRBootloader( CommChannel * _comm ) : + AVRProgrammer::AVRProgrammer( _comm ) +{ + /* No code here */ +} + + +/* Destructor */ +AVRBootloader::~AVRBootloader() +{ + /* No code here */ +} + + +bool AVRBootloader::enterProgrammingMode() +{ + return true; // Always OK for bootloader. +} + + +bool AVRBootloader::leaveProgrammingMode() +{ + return true; // Always OK for bootloader. +} + + +bool AVRBootloader::chipErase() +{ + /* Send command 'e' */ + comm->sendByte( 'e' ); + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Chip erase failed! " + "Programmer did not return CR after 'e'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::readOSCCAL( long pos, long * value ) +{ + return false; // Indicate unsupported command. +} + + +bool AVRBootloader::readSignature( long * sig0, long * sig1, long * sig2 ) +{ + /* Send command 's' */ + comm->sendByte( 's' ); + comm->flushTX(); + + /* Get actual signature */ + *sig2 = comm->getByte(); + *sig1 = comm->getByte(); + *sig0 = comm->getByte(); +} + + +bool AVRBootloader::checkSignature( long sig0, long sig1, long sig2 ) +{ + long sig[3]; + + /* Get signature */ + readSignature( sig, sig+1, sig+2 ); + + /* Compare signature */ + if( sig[0] != sig0 || sig[1] != sig1 || sig[2] != sig2 ) + { + ostringstream msg; + msg << "Signature does not match selected device! "; + msg << "Actual signature: (" << hex + << "0x" << setw(2) << sig[0] << " " + << "0x" << setw(2) << sig[1] << " " + << "0x" << setw(2) << sig[2] << ") " + << "Signature from XML-file: (" << hex + << "0x" << setw(2) << sig0 << " " + << "0x" << setw(2) << sig1 << " " + << "0x" << setw(2) << sig2 << ")."; + + throw new ErrorMsg( msg.str() ); + } + + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeFlashByte( long address, long value ) +{ + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Move data if at odd address */ + if( address & 0x01 ) // Odd address? + value = (value << 8) | 0x00ff; // Move to high byte of one flash word. + else + value |= 0xff00; // Ensure no-write for high byte. + + /* Send low and high byte */ + writeFlashLowByte( value & 0xff ); + writeFlashHighByte( value >> 8 ); + + /* Issue page write */ + setAddress( address >> 1 ); // The address could be autoincremented. + writeFlashPage(); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeEEPROMByte( long address, long value ) +{ + if( address >= 0x10000 ) + throw new ErrorMsg( "EEPROM addresses above 64k are currently not supported!" ); + + setAddress( address ); + + /* Send data */ + comm->sendByte( 'D' ); + comm->sendByte( value ); + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing byte to EEPROM failed! " + "Programmer did not return CR after 'D'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeFlash( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + /* Check that pagesize is set */ + if( pagesize == -1 ) + throw new ErrorMsg( "Programmer pagesize is not set!" ); + + /* Check block write support */ + comm->sendByte( 'b' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + { + Util.log( "Using block mode...\r\n" ); + return writeFlashBlock( data ); // Finished writing. + } + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start >> 1 ); // Flash operations use word addresses. + + /* Need to write one odd byte first? */ + address = start; + if( address & 1 ) + { + /* Use only high byte */ + writeFlashLowByte( 0xff ); // No-write in low byte. + writeFlashHighByte( data->getData( address ) ); + address++; + + /* Need to write page? */ + if( (address % pagesize) == 0 || + address > end ) // Just passed page limit or no more bytes to write? + { + setAddress( (address-2) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + setAddress( address >> 1 ); + } + } + + /* Write words */ + while( (end-address+1) >= 2 ) // More words left? + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address >> 1 ); + + /* Write words */ + writeFlashLowByte( data->getData( address ) ); + writeFlashHighByte( data->getData( address+1 ) ); + address += 2; + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + /* Need to write page? */ + if( (address % pagesize) == 0 || + address > end ) // Just passed a page limit or no more bytes to write? + { + setAddress( (address-2) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + setAddress( address >> 1 ); + } + } + + /* Need to write one even byte before finished? */ + if( address == end ) + { + /* Use only low byte */ + writeFlashLowByte( data->getData( address ) ); + writeFlashHighByte( 0xff ); // No-write in high byte. + address+=2; + + /* Write page */ + setAddress( (address-2) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeFlashBlock( HEXFile * data ) +{ + long start, end; // Data address range. + long blocksize; // Bootloader block size. + long bytecount; + long address; + + /* Get block size, assuming command 'b' just issued and 'Y' has been read */ + blocksize = (comm->getByte() << 8) | comm->getByte(); + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Need to write one odd byte first? */ + address = start; + if( address & 1 ) + { + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Use only high byte */ + writeFlashLowByte( 0xff ); // No-write in low byte. + writeFlashHighByte( data->getData( address ) ); + address++; + + /* Need to write page? */ + if( (address % pagesize) == 0 || + address > end ) // Just passed page limit or no more bytes to write? + { + setAddress( (address-2) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + setAddress( address >> 1 ); + } + } + + /* Need to write from middle to end of block first? */ + if( (address % blocksize) > 0 ) // In the middle of a block? + { + bytecount = blocksize - (address % blocksize); // Bytes left in block. + + if( (address+bytecount-1) > end ) // Is that past the write range? + { + bytecount = end-address+1; // Bytes left in write range. + bytecount &= ~0x01; // Adjust to word count. + } + + if( bytecount > 0 ) + { + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Start Flash block write */ + comm->sendByte( 'B' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'F' ); // Flash memory. + + while( bytecount > 0 ) + { + comm->sendByte( data->getData( address ) ); + address++; + bytecount--; + } + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash block failed! " + "Programmer did not return CR after 'BxxF'-command." ); + + Util.progress( "#" ); // Advance progress indicator. + } + } + + /* More complete blocks to write? */ + while( (end-address+1) >= blocksize ) + { + bytecount = blocksize; + + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Start Flash block write */ + comm->sendByte( 'B' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'F' ); // Flash memory. + + while( bytecount > 0 ) + { + comm->sendByte( data->getData( address ) ); + address++; + bytecount--; + } + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash block failed! " + "Programmer did not return CR after 'BxxF'-command." ); + + Util.progress( "#" ); // Advance progress indicator. + } + + /* Any bytes left in last block */ + if( (end-address+1) >= 1 ) + { + bytecount = (end-address+1); // Get bytes left to write. + if( bytecount & 1 ) + bytecount++; // Align to next word boundary. + + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Start Flash block write */ + comm->sendByte( 'B' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'F' ); // Flash memory. + + while( bytecount > 0 ) + { + if( address > end ) + comm->sendByte( 0xff ); // Don't write outside write range. + else + comm->sendByte( data->getData( address ) ); + + address++; + bytecount--; + } + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash block failed! " + "Programmer did not return CR after 'BxxF'-command." ); + + Util.progress( "#" ); // Advance progress indicator. + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::readFlash( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + if( pagesize == -1 ) + throw new ErrorMsg( "Programmer pagesize is not set!" ); + + /* Check block read support */ + comm->sendByte( 'b' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + { + Util.log( "Using block mode...\r\n" ); + return readFlashBlock( data ); // Finished writing. + } + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start >> 1 ); // Flash operations use word addresses. + + /* Need to read one odd byte first? */ + address = start; + if( address & 1 ) + { + /* Read both, but use only high byte */ + comm->sendByte( 'R' ); + comm->flushTX(); + + data->setData( address, comm->getByte() ); // High byte. + comm->getByte(); // Dont use low byte. + address++; + } + + /* Get words */ + while( (end-address+1) >= 2 ) + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address >> 1 ); + + /* Get words */ + comm->sendByte( 'R' ); + comm->flushTX(); + + data->setData( address+1, comm->getByte() ); // High byte. + data->setData( address, comm->getByte() ); // Low byte. + address += 2; + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + }; + + /* Need to read one even byte before finished? */ + if( address == end ) + { + /* Read both, but use only low byte */ + comm->sendByte( 'R' ); + comm->flushTX(); + + comm->getByte(); // Dont use high byte. + data->setData( address, comm->getByte() ); // Low byte. + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::readFlashBlock( HEXFile * data ) +{ + long start, end; // Data address range. + long blocksize; // Bootloader block size. + long bytecount; + long address; + + /* Get block size, assuming command 'b' just issued and 'Y' has been read */ + blocksize = (comm->getByte() << 8) | comm->getByte(); + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Need to read one odd byte first? */ + address = start; + if( address & 1 ) + { + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Use only high word */ + comm->sendByte( 'R' ); + comm->flushTX(); + + data->setData( address, comm->getByte() ); // High byte. + comm->getByte(); // Low byte. + address++; + } + + /* Need to read from middle to end of block first? */ + if( (address % blocksize) > 0 ) // In the middle of a block? + { + bytecount = blocksize - (address % blocksize); // Bytes left in block. + + if( (address+bytecount-1) > end ) // Is that past the read range? + { + bytecount = end-address+1; // Bytes left in read range. + bytecount &= ~0x01; // Adjust to word count. + } + + if( bytecount > 0 ) + { + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Start Flash block read */ + comm->sendByte( 'g' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'F' ); // Flash memory. + + while( bytecount > 0 ) + { + data->setData( address, comm->getByte() ); + address++; + bytecount--; + } + + Util.progress( "#" ); // Advance progress indicator. + } + } + + /* More complete blocks to read? */ + while( (end-address+1) >= blocksize ) + { + bytecount = blocksize; + + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Start Flash block read */ + comm->sendByte( 'g' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'F' ); // Flash memory. + + while( bytecount > 0 ) + { + data->setData( address, comm->getByte() ); + address++; + bytecount--; + } + + Util.progress( "#" ); // Advance progress indicator. + } + + /* Any bytes left in last block */ + if( (end-address+1) >= 1 ) + { + bytecount = (end-address+1); // Get bytes left to read. + if( bytecount & 1 ) + bytecount++; // Align to next word boundary. + + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Start Flash block read */ + comm->sendByte( 'g' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'F' ); // Flash memory. + + while( bytecount > 0 ) + { + if( address > end ) + comm->getByte(); // Don't read outside write range. + else + data->setData( address, comm->getByte() ); + + address++; + bytecount--; + } + + Util.progress( "#" ); // Advance progress indicator. + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeEEPROM( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + /* Check block write support */ + comm->sendByte( 'b' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + { + Util.log( "Using block mode...\r\n" ); + return writeEEPROMBlock( data ); // Finished writing. + } + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start ); + + /* Send data */ + address = start; + do + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address ); + + /* Send byte */ + comm->sendByte( 'D' ); + comm->sendByte( data->getData( address ) ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing byte to EEPROM failed! " + "Programmer did not return CR after 'D'-command." ); + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + address++; + } while( address <= end ); + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeEEPROMBlock( HEXFile * data ) +{ + long start, end; // Data address range. + long blocksize; // Bootloader block size. + long bytecount; + long address; + + /* Get block size, assuming command 'b' just issued and 'Y' has been read */ + blocksize = (comm->getByte() << 8) | comm->getByte(); + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Send data */ + address = start; + while( address <= end ) // More bytes to write? + { + bytecount = blocksize; // Try a full block. + + if( (address+bytecount-1) > end ) // Is that past the write range? + { + bytecount = end-address+1; // Bytes left in write range. + } + + setAddress( address ); + + /* Start EEPROM block write */ + comm->sendByte( 'B' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'E' ); // EEPROM memory. + + while( bytecount > 0 ) + { + comm->sendByte( data->getData( address ) ); + comm->flushTX(); + + address++; + bytecount--; + } + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing EEPROM block failed! " + "Programmer did not return CR after 'BxxE'-command." ); + + Util.progress( "#" ); // Advance progress indicator. + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::readEEPROM( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + /* Check block write support */ + comm->sendByte( 'b' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + { + Util.log( "Using block mode...\r\n" ); + return readEEPROMBlock( data ); // Finished writing. + } + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start ); + + /* Read data */ + address = start; + do + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address ); + + /* Get byte */ + comm->sendByte( 'd' ); + comm->flushTX(); + + data->setData( address, comm->getByte() ); + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + address++; + } while( address <= end ); + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::readEEPROMBlock( HEXFile * data ) +{ + long start, end; // Data address range. + long blocksize; // Bootloader block size. + long bytecount; + long address; + + /* Get block size, assuming command 'b' just issued and 'Y' has been read */ + blocksize = (comm->getByte() << 8) | comm->getByte(); + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Read data */ + address = start; + while( address <= end ) // More bytes to read? + { + bytecount = blocksize; // Try a full block. + + if( (address+bytecount-1) > end ) // Is that past the read range? + { + bytecount = end-address+1; // Bytes left in read range. + } + + setAddress( address ); + + /* Start EEPROM block read */ + comm->sendByte( 'g' ); + comm->sendByte( (bytecount>>8) & 0xff ); // Size, MSB first. + comm->sendByte( bytecount & 0xff ); + comm->sendByte( 'E' ); // EEPROM memory. + + while( bytecount > 0 ) + { + data->setData( address, comm->getByte() ); + address++; + bytecount--; + } + + Util.progress( "#" ); // Advance progress indicator. + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeLockBits( long bits ) +{ + /* Send command 'l' */ + comm->sendByte( 'l' ); + comm->sendByte( bits & 0xff ); + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing lock bits failed! " + "Programmer did not return CR after 'l'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::readLockBits( long * bits ) +{ + /* Send command 'r' */ + comm->sendByte( 'r' ); + comm->flushTX(); + + /* Get data */ + *bits = comm->getByte(); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeFuseBits( long bits ) +{ + return false; // Indicate unsupported command. +} + + +bool AVRBootloader::readFuseBits( long * bits ) +{ + long lowfuse, highfuse; + + /* Send command 'N' */ + comm->sendByte( 'N' ); + comm->flushTX(); + + /* Get high fuse bits */ + highfuse = comm->getByte(); + + /* Send command 'F' */ + comm->sendByte( 'F' ); + comm->flushTX(); + + /* Get low fuse bits */ + lowfuse = comm->getByte(); + + *bits = (highfuse << 8) | lowfuse; + + return true; // Indicate supported command. +} + + +bool AVRBootloader::writeExtendedFuseBits( long bits ) +{ + return false; // Indicate unsupported command. +} + + +bool AVRBootloader::readExtendedFuseBits( long * bits ) +{ + /* Send command 'Q' */ + comm->sendByte( 'Q' ); + comm->flushTX(); + + /* Get data */ + *bits = comm->getByte(); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::programmerSoftwareVersion( long * major, long * minor ) +{ + /* Send command 'V' to get software version */ + comm->sendByte( 'V' ); + comm->flushTX(); + + /* Get data */ + *major = comm->getByte(); + *minor = comm->getByte(); + + return true; // Indicate supported command. +} + + +bool AVRBootloader::programmerHardwareVersion( long * major, long * minor ) +{ + return false; // Indicate unsupported command. +} + + +void AVRBootloader::setAddress( long address ) +{ + /* Set current address */ + if( address < 0x10000 ) { + comm->sendByte( 'A' ); + comm->sendByte( (address >> 8) & 0xff ); + comm->sendByte( address & 0xff ); + comm->flushTX(); + } else { + comm->sendByte( 'H' ); + comm->sendByte( (address >> 16) & 0xff ); + comm->sendByte( (address >> 8) & 0xff ); + comm->sendByte( address & 0xff ); + comm->flushTX(); + } + + /* Should return CR */ + if( comm->getByte() != '\r' ) { + throw new ErrorMsg( "Setting address for programming operations failed! " + "Programmer did not return CR after 'A'-command." ); + } +} + + +void AVRBootloader::writeFlashLowByte( long value ) +{ + comm->sendByte( 'c' ); + comm->sendByte( value ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash low byte failed! " + "Programmer did not return CR after 'c'-command." ); +} + + +void AVRBootloader::writeFlashHighByte( long value ) +{ + comm->sendByte( 'C' ); + comm->sendByte( value ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash high byte failed! " + "Programmer did not return CR after 'C'-command." ); +} + + +void AVRBootloader::writeFlashPage() +{ + comm->sendByte( 'm' ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash page failed! " + "Programmer did not return CR after 'm'-command." ); +} + + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRBootloader.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRBootloader.hpp new file mode 100644 index 00000000..df7bfa88 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRBootloader.hpp @@ -0,0 +1,84 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRBootloader.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing an interface to the AVR bootloader + * described in Application Note AVR109. + * This class is derived from AVRPRogrammer. + * + * + ****************************************************************************/ +#ifndef AVRBOOTLOADER_HPP +#define AVRBOOTLOADER_HPP + +using namespace std; + +#include "AVRProgrammer.hpp" +#include "Utility.hpp" + +class AVRBootloader : public AVRProgrammer +{ + protected: + virtual void setAddress( long address ); + virtual void writeFlashLowByte( long value ); // Alwyas low byte first... + virtual void writeFlashHighByte( long value ); // ...then high byte. + virtual void writeFlashPage(); + + virtual bool writeFlashBlock( HEXFile * data ); + virtual bool readFlashBlock( HEXFile * data ); + virtual bool writeEEPROMBlock( HEXFile * data ); + virtual bool readEEPROMBlock( HEXFile * data ); + + public: + /* Constructor */ + AVRBootloader( CommChannel * _comm ); + + /* Destructor */ + ~AVRBootloader(); + + /* Methods */ + virtual bool enterProgrammingMode(); + virtual bool leaveProgrammingMode(); + + virtual bool chipErase(); + + virtual bool readOSCCAL( long pos, long * value ); + virtual bool readSignature( long * sig0, long * sig1, long * sig2 ); + virtual bool checkSignature( long sig0, long sig1, long sig2 ); + + virtual bool writeFlashByte( long address, long value ); + virtual bool writeEEPROMByte( long address, long value ); + + virtual bool writeFlash( HEXFile * data ); + virtual bool readFlash( HEXFile * data ); + + virtual bool writeEEPROM( HEXFile * data ); + virtual bool readEEPROM( HEXFile * data ); + + virtual bool writeLockBits( long bits ); + virtual bool readLockBits( long * bits ); + + virtual bool writeFuseBits( long bits ); + virtual bool readFuseBits( long * bits ); + virtual bool writeExtendedFuseBits( long bits ); + virtual bool readExtendedFuseBits( long * bits ); + + virtual bool programmerSoftwareVersion( long * major, long * minor ); + virtual bool programmerHardwareVersion( long * major, long * minor ); +}; + + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRDevice.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRDevice.cpp new file mode 100644 index 00000000..c7aa8852 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRDevice.cpp @@ -0,0 +1,157 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRDevice.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 4017 $ + * Date : $Date: 2008-06-02 14:26:03 +0200 (ma, 02 jun 2008) $ + * Updated by : $Author: khole $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class containing information of device memory sizes etc. + * It also provides funcitons for reading these parameters from + * the PartDescriptionFiles supplied with AVR Studio 4. + * + * + ****************************************************************************/ +#include "AVRDevice.hpp" + + +/* Constructor */ +AVRDevice::AVRDevice( const string & _deviceName ) : + deviceName( _deviceName ) +{ + flashSize = + eepromSize = 0; + hasFuseBits = false; + hasExtendedFuseBits = false; + signature0 = + signature1 = + signature2 = 0; + pagesize = -1; +} + + +/* Destructor */ +AVRDevice::~AVRDevice() +{ + /* no code here */ +} + +/* Read parameters from AVR Studio XML files */ +void AVRDevice::readParametersFromAVRStudio( vector & searchpath ) +{ + string path; + string signature; + string cache; + +#ifndef NOREGISTRY + /* Locate the directory containing the XML files from the Windows registry database */ + try + { + path = Util.getRegistryValue( "SOFTWARE\\Atmel\\AVRTools\\", "AVRToolsPath" ); + path += "\\PartDescriptionFiles"; + searchpath.push_back( path ); + } catch( ErrorMsg * e ) + { + delete e; + } +#endif + + /* Search for file */ + path.erase(); + int i; + for( i = 0; i < searchpath.size(); i++ ) + { + path = searchpath[i] + "\\" + deviceName + ".xml"; + if( Util.fileExists( path ) ) + break; + } + + if( i == searchpath.size() ) + throw new ErrorMsg( "Device XML file not found in search path!" ); + + /* Parse the file for required info */ + Util.log( "Parsing '" + path + "'...\r\n" ); + XMLFile f( path ); // Load XML info + + flashSize = atoi( f.getValue( "AVRPART\\MEMORY\\PROG_FLASH" ).c_str() ); + eepromSize = atoi( f.getValue( "AVRPART\\MEMORY\\EEPROM" ).c_str() ); + + cache += ""; + cache += f.getValue( "AVRPART\\MEMORY\\PROG_FLASH" ); + cache += ""; + cache += f.getValue( "AVRPART\\MEMORY\\EEPROM" ); + cache += ""; + + if( f.exists( "AVRPART\\MEMORY\\BOOT_CONFIG" ) ) + { + pagesize = atoi( f.getValue( "AVRPART\\MEMORY\\BOOT_CONFIG\\PAGESIZE" ).c_str() ); + pagesize <<= 1; // We want pagesize in bytes. + + cache += ""; + cache += f.getValue( "AVRPART\\MEMORY\\BOOT_CONFIG\\PAGESIZE" ); + cache += ""; + } + + cache += ""; + + if( f.exists( "AVRPART\\FUSE" ) ) + { + hasFuseBits = true; + + cache += ""; + + if( f.exists( "AVRPART\\FUSE\\EXTENDED" ) ) + { + hasExtendedFuseBits = true; + cache += ""; + } + + cache += ""; + } + + signature = f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR000" ); + signature.erase( 0, 1 ); // Remove the $ character. + signature0 = Util.convertHex( signature ); + + signature = f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR001" ); + signature.erase( 0, 1 ); // Remove the $ character. + signature1 = Util.convertHex( signature ); + + signature = f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR002" ); + signature.erase( 0, 1 ); // Remove the $ character. + signature2 = Util.convertHex( signature ); + + cache += ""; + cache += f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR000" ); + cache += ""; + cache += f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR001" ); + cache += ""; + cache += f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR002" ); + cache += "\r\n"; + + /* Save cached file to application directory */ + Util.log( "Saving cached XML parameters...\r\n" ); + Util.saveString( cache, searchpath[1] + "\\" + deviceName + ".xml" ); +} + + +void AVRDevice::getSignature( long * sig0, long * sig1, long * sig2 ) +{ + if( sig0 == NULL || sig1 == NULL || sig2 == NULL ) + throw new ErrorMsg( "Cannot copy signature bytes to NULL-pointers!" ); + + *sig0 = signature0; + *sig1 = signature1; + *sig2 = signature2; +} + + +/* end of file */ diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRDevice.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRDevice.hpp new file mode 100644 index 00000000..7d5a8390 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRDevice.hpp @@ -0,0 +1,69 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRDevice.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class containing information of device memory sizes etc. + * It also provides funcitons for reading these parameters from + * the PartDescriptionFiles supplied with AVR Studio 4. + * + * + ****************************************************************************/ +#ifndef AVRDEVICE_HPP +#define AVRDEVICE_HPP + +using namespace std; + + +#include +#include +#include "Utility.hpp" +#include "XMLParser.hpp" +#include "ErrorMsg.hpp" + +class AVRDevice +{ + protected: + string deviceName; // The name of the device, eg. ATmega128. + + long flashSize; // Size of Flash memory in bytes. + long eepromSize; // Size of EEPROM memory in bytes. + bool hasFuseBits; // Does this device have fuse bits at all? + bool hasExtendedFuseBits; // Does this device have extended fuses? + long signature0; + long signature1; + long signature2; // The three signature bytes, read from XML PartDescriptionFiles. + long pagesize; // Flash page size. + + public: + /* Constructor */ + AVRDevice( const string & _deviceName ); + + /* Destructor */ + ~AVRDevice(); + + /* Methods */ + void readParametersFromAVRStudio( vector & searchpath ); + + long getFlashSize() { return flashSize; } + long getEEPROMSize() { return eepromSize; } + long getPageSize() { return pagesize; } + bool getFuseStatus() { return hasFuseBits; } + bool getXFuseStatus() { return hasExtendedFuseBits; } + + void getSignature( long * sig0, long * sig1, long * sig2 ); +}; + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRInSystemProg.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRInSystemProg.cpp new file mode 100644 index 00000000..3104cbb0 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRInSystemProg.cpp @@ -0,0 +1,714 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRInSystemProg.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing an interface to the AVR ISP described + * in Application Note AVR910. This class is derived from AVRPRogrammer. + * + * + ****************************************************************************/ +#include "AVRInSystemProg.hpp" + +#include +#include + +#define MEM_PROGRESS_GRANULARITY 256 // For use with progress indicator. + + +/* Constructor */ +AVRInSystemProg::AVRInSystemProg( CommChannel * _comm ) : + AVRProgrammer::AVRProgrammer( _comm ) +{ + /* No code here */ +} + + +/* Destructor */ +AVRInSystemProg::~AVRInSystemProg() +{ + /* No code here */ +} + + +bool AVRInSystemProg::enterProgrammingMode() +{ + /* Must select a device from the AVRISP device code table first */ + comm->sendByte( 'T' ); + comm->sendByte( 0x64 ); // Select ATmega163, any device in the table will do. + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Entering programming mode failed! " + "Programmer did not return CR after 'T'-command." ); + + /* Send command 'P' */ + comm->sendByte( 'P' ); + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Entering programming mode failed! " + "Programmer did not return CR after 'P'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::leaveProgrammingMode() +{ + /* Send command 'L' */ + comm->sendByte( 'L' ); + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Leaving programming mode failed! " + "Programmer did not return CR after 'L'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::chipErase() +{ + /* Send command 'e' */ + comm->sendByte( 'e' ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Chip erase failed! " + "Programmer did not return CR after 'e'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readOSCCAL( long pos, long * value ) +{ + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0x38 ); + comm->sendByte( 0x00 ); + comm->sendByte( pos ); + comm->sendByte( 0x00 ); // Dummy. + comm->flushTX(); + + *value = comm->getByte(); + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "OSCCAL value readout failed! " + "Programmer did not return CR after '.'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readSignature( long * sig0, long * sig1, long * sig2 ) +{ + /* Send command 's' */ + comm->sendByte( 's' ); + comm->flushTX(); + + /* Get actual signature */ + *sig2 = comm->getByte(); + *sig1 = comm->getByte(); + *sig0 = comm->getByte(); +} + + +bool AVRInSystemProg::checkSignature( long sig0, long sig1, long sig2 ) +{ + long sig[3]; + + /* Get signature */ + readSignature( sig, sig+1, sig+2 ); + + /* Compare signature */ + if( sig[0] != sig0 || sig[1] != sig1 || sig[2] != sig2 ) + { + ostringstream msg; + msg << "Signature does not match selected device! "; + msg << "Actual signature: (" << hex + << "0x" << setw(2) << sig[0] << " " + << "0x" << setw(2) << sig[1] << " " + << "0x" << setw(2) << sig[2] << ") " + << "Signature from XML-file: (" << hex + << "0x" << setw(2) << sig0 << " " + << "0x" << setw(2) << sig1 << " " + << "0x" << setw(2) << sig2 << ")."; + + throw new ErrorMsg( msg.str() ); + } + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeFlashByte( long address, long value ) +{ + if( address >= 0x20000 ) + throw new ErrorMsg( "Flash addresses above 128k are currently not supported!" ); + + setAddress( address >> 1 ); // Flash operations use word addresses. + + /* Move data if at odd address */ + if( address & 0x01 ) // Odd address? + value = (value << 8) | 0x00ff; // Move to high byte of one flash word. + else + value |= 0xff00; // Ensure no-write for high byte. + + /* Send low and high byte */ + writeFlashLowByte( value & 0xff ); + writeFlashHighByte( value >> 8 ); + + /* Issue page write if required */ + if( pagesize != -1 ) + { + setAddress( address >> 1 ); // The address could be autoincremented. + writeFlashPage(); + } + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeEEPROMByte( long address, long value ) +{ + if( address >= 0x10000 ) + throw new ErrorMsg( "EEPROM addresses above 64k are currently not supported!" ); + + setAddress( address ); + + /* Send data */ + comm->sendByte( 'D' ); + comm->sendByte( value ); + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing byte to EEPROM failed! " + "Programmer did not return CR after 'D'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeFlash( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + /* Check that pagesize is set */ + if( pagesize == -1 ) + throw new ErrorMsg( "Programmer pagesize is not set!" ); + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start >> 1 ); // Flash operations use word addresses. + + /* Need to write one odd byte first? */ + address = start; + if( address & 1 ) + { + /* Use only high byte */ + writeFlashLowByte( 0xff ); // No-write in low byte. + writeFlashHighByte( data->getData( address ) ); + + address++; + + /* Need to write page? */ + if( pagesize != -1 ) + { + if( !(address % pagesize) ) // Just passed page limit? + { + setAddress( (address-1) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + setAddress( address >> 1 ); + } + } + } + + /* Write words */ + do + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address >> 1 ); + + /* Write words */ + writeFlashLowByte( data->getData( address ) ); + writeFlashHighByte( data->getData( address+1 ) ); + + address += 2; + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + /* Need to write page? */ + if( pagesize != -1 ) + { + if( (address % pagesize) == 0 ) // Just passed a page boundary? + { + setAddress( (address-2) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + setAddress( address >> 1 ); + } + } + } while( address < end ); + + /* Need to write one even byte before finished? */ + if( address == end ) + { + /* Use only low byte */ + writeFlashLowByte( data->getData( address ) ); + writeFlashHighByte( 0xff ); // No-write in high byte. + } + + /* Need to write page? */ + if( pagesize != -1 ) + { + if( address == end || // One extra byte written... + (end+1)%pagesize != 0 ) // ...or end is not on page boundary. + { + setAddress( (address-2) >> 1 ); // Set to an address inside the page. + writeFlashPage(); + } + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readFlash( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + if( pagesize == -1 ) + throw new ErrorMsg( "Programmer pagesize is not set!" ); + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start >> 1 ); // Flash operations use word addresses. + + /* Need to read one odd byte first? */ + address = start; + if( address & 1 ) + { + /* Read both, but use only high byte */ + comm->sendByte( 'R' ); + comm->flushTX(); + + data->setData( address, comm->getByte() ); // High byte. + comm->getByte(); // Dont use low byte. + + address++; + } + + /* Get words */ + do + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address >> 1 ); + + /* Get words */ + comm->sendByte( 'R' ); + comm->flushTX(); + + data->setData( address+1, comm->getByte() ); // High byte. + data->setData( address, comm->getByte() ); // Low byte. + + address += 2; + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + } while( address < end ); + + /* Need to read one even byte before finished? */ + if( address == end ) + { + /* Read both, but use only low byte */ + comm->sendByte( 'R' ); + comm->flushTX(); + + comm->getByte(); // Dont use high byte. + data->setData( address-1, comm->getByte() ); // Low byte. + } + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeEEPROM( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start ); + + /* Send data */ + address = start; + do + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address ); + + /* Send byte */ + comm->sendByte( 'D' ); + comm->sendByte( data->getData( address ) ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing byte to EEPROM failed! " + "Programmer did not return CR after 'D'-command." ); + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + address++; + } while( address <= end ); + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readEEPROM( HEXFile * data ) +{ + long start, end; // Data address range. + bool autoincrement; // Bootloader supports address autoincrement? + long address; + + /* Get range from HEX file */ + start = data->getRangeStart(); + end = data->getRangeEnd(); + + /* Check autoincrement support */ + comm->sendByte( 'a' ); + comm->flushTX(); + + if( comm->getByte() == 'Y' ) + autoincrement = true; + else + autoincrement = false; + + /* Set initial address */ + setAddress( start ); + + /* Send data */ + address = start; + do + { + /* Need to set address again? */ + if( !autoincrement ) + setAddress( address ); + + /* Get byte */ + comm->sendByte( 'd' ); + comm->flushTX(); + + data->setData( address, comm->getByte() ); + + if( (address % MEM_PROGRESS_GRANULARITY) == 0 ) + Util.progress( "#" ); // Advance progress indicator. + + address++; + } while( address <= end ); + + Util.progress( "\r\n" ); // Finish progress indicator. + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeLockBits( long bits ) +{ + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0xac ); + comm->sendByte( 0xe0 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( bits ); + + comm->flushTX(); + comm->getByte(); // Ignore return code from SPI communication. + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Writing lock bits failed! " + "Programmer did not return CR after '.'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readLockBits( long * bits ) +{ + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0x58 ); + comm->sendByte( 0x00 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( 0x00 ); // Dummy. + comm->flushTX(); + + *bits = comm->getByte(); + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Lock byte readout failed! " + "Programmer did not return CR after '.'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeFuseBits( long bits ) +{ + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0xac ); + comm->sendByte( 0xa0 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( bits & 0xff ); + comm->flushTX(); + + comm->getByte(); // Ignore return code from SPI communication. + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Low fuse byte programming failed! " + "Programmer did not return CR after '.'-command." ); + + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0xac ); + comm->sendByte( 0xa8 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( bits >> 8 ); + comm->flushTX(); + + comm->getByte(); // Ignore return code from SPI communication. + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "High fuse byte programming failed! " + "Programmer did not return CR after '.'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readFuseBits( long * bits ) +{ + long low, high; + + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0x50 ); + comm->sendByte( 0x00 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( 0x00 ); // Dummy. + comm->flushTX(); + + low = comm->getByte(); + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Low fuse byte readout failed! " + "Programmer did not return CR after '.'-command." ); + + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0x58 ); + comm->sendByte( 0x08 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( 0x00 ); // Dummy. + comm->flushTX(); + + high = comm->getByte(); + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Low fuse byte readout failed! " + "Programmer did not return CR adter '.'-command." ); + + /* Put low and high together */ + *bits = (high << 8) | low; + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::writeExtendedFuseBits( long bits ) +{ + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0xac ); + comm->sendByte( 0xa4 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( bits ); + comm->flushTX(); + + comm->getByte(); // Ignore return code from SPI communication. + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Extended fuse byte programming failed! " + "Programmer did not return CR after '.'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::readExtendedFuseBits( long * bits ) +{ + /* Use AVRISP's 4-byte universal command */ + comm->sendByte( '.' ); + comm->sendByte( 0x50 ); + comm->sendByte( 0x08 ); + comm->sendByte( 0x00 ); // Dummy. + comm->sendByte( 0x00 ); // Dummy. + comm->flushTX(); + + *bits = comm->getByte(); + + if( comm->getByte() != '\r' ) // Check return code from command. + throw new ErrorMsg( "Extended fuse byte readout failed! " + "Programmer did not return CR after '.'-command." ); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::programmerSoftwareVersion( long * major, long * minor ) +{ + /* Send command 'V' to get software version */ + comm->sendByte( 'V' ); + comm->flushTX(); + + /* Get data */ + *major = comm->getByte(); + *minor = comm->getByte(); + + return true; // Indicate supported command. +} + + +bool AVRInSystemProg::programmerHardwareVersion( long * major, long * minor ) +{ + /* Send command 'v' to get hardware version */ + comm->sendByte( 'v' ); + comm->flushTX(); + + /* Get data */ + *major = comm->getByte(); + *minor = comm->getByte(); + + return true; // Indicate supported command. +} + + +void AVRInSystemProg::setAddress( long address ) +{ + /* Set current address */ + comm->sendByte( 'A' ); + comm->sendByte( address >> 8 ); // High byte of address. + comm->sendByte( address & 0xff ); // Low byte. + comm->flushTX(); + + /* Should return CR */ + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Setting address for programming operations failed! " + "Programmer did not return CR after 'A'-command." ); +} + + +void AVRInSystemProg::writeFlashLowByte( long value ) +{ + comm->sendByte( 'c' ); + comm->sendByte( value ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash low byte failed! " + "Programmer did not return CR after 'c'-command." ); +} + + +void AVRInSystemProg::writeFlashHighByte( long value ) +{ + comm->sendByte( 'C' ); + comm->sendByte( value ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash high byte failed! " + "Programmer did not return CR after 'C'-command." ); +} + + +void AVRInSystemProg::writeFlashPage() +{ + comm->sendByte( 'm' ); + comm->flushTX(); + + if( comm->getByte() != '\r' ) + throw new ErrorMsg( "Writing Flash page failed! " + "Programmer did not return CR after 'm'-command." ); +} + + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRInSystemProg.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRInSystemProg.hpp new file mode 100644 index 00000000..ba94cf42 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRInSystemProg.hpp @@ -0,0 +1,78 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRInSystemProg.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing an interface to the AVR ISP described + * in Application Note AVR910. This class is derived from AVRPRogrammer. + * + * + ****************************************************************************/ +#ifndef AVRINSYSTEMPROG_HPP +#define AVRINSYSTEMPROG_HPP + +using namespace std; + +#include "AVRProgrammer.hpp" +#include "Utility.hpp" + +class AVRInSystemProg : public AVRProgrammer +{ + protected: + void setAddress( long address ); + void writeFlashLowByte( long value ); // Alwyas low byte first... + void writeFlashHighByte( long value ); // ...then high byte. + void writeFlashPage(); + + public: + /* Constructor */ + AVRInSystemProg( CommChannel * _comm ); + + /* Destructor */ + ~AVRInSystemProg(); + + /* Methods */ + virtual bool enterProgrammingMode(); + virtual bool leaveProgrammingMode(); + + virtual bool chipErase(); + + virtual bool readOSCCAL( long pos, long * value ); + virtual bool readSignature( long * sig0, long * sig1, long * sig2 ); + virtual bool checkSignature( long sig0, long sig1, long sig2 ); + + virtual bool writeFlashByte( long address, long value ); + virtual bool writeEEPROMByte( long address, long value ); + + virtual bool writeFlash( HEXFile * data ); + virtual bool readFlash( HEXFile * data ); + + virtual bool writeEEPROM( HEXFile * data ); + virtual bool readEEPROM( HEXFile * data ); + + virtual bool writeLockBits( long bits ); + virtual bool readLockBits( long * bits ); + + virtual bool writeFuseBits( long bits ); + virtual bool readFuseBits( long * bits ); + virtual bool writeExtendedFuseBits( long bits ); + virtual bool readExtendedFuseBits( long * bits ); + + virtual bool programmerSoftwareVersion( long * major, long * minor ); + virtual bool programmerHardwareVersion( long * major, long * minor ); +}; + + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVROSP.dev b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVROSP.dev new file mode 100644 index 00000000..753e61f7 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVROSP.dev @@ -0,0 +1,169 @@ +[Project] +FileName=AVROSP.dev +Name=AVROSP +UnitCount=12 +Type=1 +Ver=1 +ObjFiles= +Includes= +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker= +IsCpp=1 +Icon= +ExeOutput= +ObjectOutput= +OverrideOutput=0 +OverrideOutputName=AVROSP.exe +HostApplication= +Folders= +CommandLine= -dATmega16 -if\temp\rnd8KB.hex -pf +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=000000000000000100 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit2] +FileName=CommChannel.cpp +CompileCpp=1 +Folder=Serialtest +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=ErrorMsg.cpp +CompileCpp=1 +Folder=Serialtest +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=JobInfo.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=AVRDevice.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=HEXParser.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=XMLParser.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=AVRBootloader.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=AVRProgrammer.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=Utility.cpp +CompileCpp=1 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=SerialPort.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=AVRInSystemProg.cpp +CompileCpp=1 +Folder=AVROSP +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRProgrammer.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRProgrammer.cpp new file mode 100644 index 00000000..e4e851a9 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRProgrammer.cpp @@ -0,0 +1,70 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRProgrammer.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : An abstract class containing a framework for a generic + * programmer for AVR parts. Reading and writing Flash, EEPROM + * lock bits and all fuse bits and reading OSCCAL and reading + * signature bytes are supported. + * + * + ****************************************************************************/ +#include "AVRProgrammer.hpp" + + +/* Constructor */ +AVRProgrammer::AVRProgrammer( CommChannel * _comm ) : + pagesize( -1 ) +{ + if( _comm == NULL ) + throw new ErrorMsg( "NULL pointer provided for communication channel!" ); + + comm = _comm; +} + + +/* Destructor */ +AVRProgrammer::~AVRProgrammer() +{ + /* No code here */ +} + + +string AVRProgrammer::readProgrammerID( CommChannel * _comm ) +{ + string id( "1234567" ); // Reserve 7 characters. + + if( _comm == NULL ) + throw new ErrorMsg( "NULL pointer provided for communication channel!" ); + + /* Synchonize with programmer */ + for( int i = 0; i < 10; i++ ) + _comm->sendByte( 27 ); // Send ESC + + /* Send 'S' command to programmer */ + _comm->sendByte( 'S' ); + _comm->flushTX(); + + /* Read 7 characters */ + for( long i = 0; i < id.size(); i++ ) + { + id[i] = _comm->getByte(); + } + + return id; +} + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRProgrammer.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRProgrammer.hpp new file mode 100644 index 00000000..8921e589 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/AVRProgrammer.hpp @@ -0,0 +1,84 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : AVRProgrammer.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : An abstract class containing a framework for a generic + * programmer for AVR parts. Reading and writing Flash, EEPROM + * lock bits and all fuse bits and reading OSCCAL and reading + * signature bytes are supported. + * + * + ****************************************************************************/ +#ifndef AVRPROGRAMMER_HPP +#define AVRPROGRAMMER_HPP + +using namespace std; + +#include "ErrorMsg.hpp" +#include "HEXParser.hpp" +#include "CommChannel.hpp" + +class AVRProgrammer +{ + protected: + long pagesize; // Flash page size. + CommChannel * comm; + + public: + /* Constructor */ + AVRProgrammer( CommChannel * _comm ); + + /* Destructor */ + ~AVRProgrammer(); + + /* Static member */ + static string readProgrammerID( CommChannel * _comm ); // Reads 7-character ID. + + /* Methods */ + void setPagesize( long _pagesize ) { pagesize = _pagesize; } + + virtual bool enterProgrammingMode() = 0; + virtual bool leaveProgrammingMode() = 0; + + virtual bool chipErase() = 0; + + virtual bool readOSCCAL( long pos, long * value ) = 0; + virtual bool readSignature( long * sig0, long * sig1, long * sig2 ) = 0; + virtual bool checkSignature( long sig0, long sig1, long sig2 ) = 0; + + virtual bool writeFlashByte( long address, long value ) = 0; + virtual bool writeEEPROMByte( long address, long value ) = 0; + + virtual bool writeFlash( HEXFile * data ) = 0; + virtual bool readFlash( HEXFile * data ) = 0; + + virtual bool writeEEPROM( HEXFile * data ) = 0; + virtual bool readEEPROM( HEXFile * data ) = 0; + + virtual bool writeLockBits( long bits ) = 0; + virtual bool readLockBits( long * bits ) = 0; + + virtual bool writeFuseBits( long bits ) = 0; + virtual bool readFuseBits( long * bits ) = 0; + virtual bool writeExtendedFuseBits( long bits ) = 0; + virtual bool readExtendedFuseBits( long * bits ) = 0; + + virtual bool programmerSoftwareVersion( long * major, long * minor ) = 0; + virtual bool programmerHardwareVersion( long * major, long * minor ) = 0; +}; + + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/CommChannel.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/CommChannel.cpp new file mode 100644 index 00000000..091b69f7 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/CommChannel.cpp @@ -0,0 +1,38 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : CommChannel.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : An abstract class for general byte-by-byte communication. + * Serialport, USB, TCP/IP or similar implementations can be derived + * from this class to create a technology-independent + * communication interface. + * + * This abstract class does not provide any constructor as it is + * too specific for this generalized class. Derived classes should + * implement their own constructors for specific communication devices. + * + * + ****************************************************************************/ +#include "CommChannel.hpp" + + +/* Destructor */ +CommChannel::~CommChannel() +{ + /* no code here */ +} + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/CommChannel.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/CommChannel.hpp new file mode 100644 index 00000000..6f48f756 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/CommChannel.hpp @@ -0,0 +1,61 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : CommChannel.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : An abstract class for general byte-by-byte communication. + * Serialport, USB, TCP/IP or similar implementations can be derived + * from this class to create a technology-independent + * communication interface. + * + * This abstract class does not provide any constructor as it is + * too specific for this generalized class. Derived classes should + * implement their own constructors for specific communication devices. + * + * + ****************************************************************************/ +#ifndef COMMCHANNEL_HPP +#define COMMCHANNEL_HPP + +using namespace std; + +class CommChannel +{ + public: + // Destructor + virtual ~CommChannel() = 0; + + // Open the communication channel. + virtual void openChannel() = 0; + + // Close the communication channel. + virtual void closeChannel() = 0; + + // Transmit a single byte. + virtual void sendByte( long data ) = 0; + + // Receive a single byte. + virtual long getByte() = 0; + + // Flush the transmit buffer. + virtual void flushTX() = 0; + + // Flush the receive buffer. + virtual void flushRX() = 0; + + // Transmit multiple bytes. + virtual void sendMultiple( unsigned char * data, long bufsize ) = 0; +}; + +#endif diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/ErrorMsg.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/ErrorMsg.cpp new file mode 100644 index 00000000..957f574c --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/ErrorMsg.cpp @@ -0,0 +1,46 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : ErrorMsg.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing a container for general error messages. This + * class can be thrown as an exception. + * + * + ****************************************************************************/ +#include "ErrorMsg.hpp" + + +ErrorMsg::ErrorMsg( const string & _message ) : + message( _message ) +{ + // No code here. +} + + +/* Destructor */ +ErrorMsg::~ErrorMsg() +{ + // No code here. +} + + +/* Get message */ +const string & ErrorMsg::What() +{ + return message; +} + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/ErrorMsg.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/ErrorMsg.hpp new file mode 100644 index 00000000..f38da763 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/ErrorMsg.hpp @@ -0,0 +1,49 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : ErrorMsg.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing a container for general error messages. This + * class can be thrown as an exception. + * + * + ****************************************************************************/ +#ifndef ERRORMSG_HPP +#define ERRORMSG_HPP + +using namespace std; + +#include +#include +#include + + +class ErrorMsg +{ + protected: + string message; // Contains the error message. + + public: + // Constructors taking the string as parameter. + ErrorMsg( const string & _message ); + + // Destructor + ~ErrorMsg(); + + // Function returning the error msg. + virtual const string & What(); +}; + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/HEXParser.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/HEXParser.cpp new file mode 100644 index 00000000..1dd2a2a8 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/HEXParser.cpp @@ -0,0 +1,364 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : HEXParser.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A simple Intel HEX file format reader/writer. + * + * + ****************************************************************************/ +#include "HEXParser.hpp" + + +/* Internal struct for managing HEX records */ +struct HEXRecord // Intel HEX file record +{ + unsigned char length; // Record length in number of data bytes. + unsigned long offset; // Offset address. + unsigned char type; // Record type. + unsigned char * data; // Optional data bytes. +}; + + +void HEXFile::writeRecord( ofstream & f, HEXRecord * recp ) +{ + unsigned char checksum; + long recordPos; // Position inside record data field + + /* Calculate checksum */ + checksum = recp->length; + checksum += (unsigned char) ((recp->offset >> 8) & 0xff); + checksum += (unsigned char) (recp->offset & 0xff); + checksum += recp->type; + + /* Write record header */ + f.fill('0'); + f << ":" << hex + << setw(2) << (long) recp->length + << setw(4) << (long) recp->offset + << setw(2) << (long) recp->type; + + /* Write data bytes */ + for( recordPos = 0; recordPos < recp->length; recordPos++ ) + { + checksum += recp->data[ recordPos ]; // Further checksum calculation + f << hex << setw(2) << (long) recp->data[ recordPos ]; + } + + /* Write checksum */ + checksum = 0 - checksum; // Final checksum preparation + f << setw(2) << (long) checksum << endl; + + /* Check for errors */ + if( !f.good() ) + throw new ErrorMsg( "Error writing HEX record to file!" ); +} + + +void HEXFile::parseRecord( const string & hexLine, HEXRecord * recp ) +{ + unsigned char checksum; + long recordPos; // Position inside record data fields. + + if( hexLine.size() < 11 ) // At least 11 characters. + throw new ErrorMsg( "Wrong HEX file format, missing fields! " + "Line from file was: (" + hexLine + ")." ); + + /* Check format for line */ + if( hexLine[0] != ':' ) // Always start with colon. + throw new ErrorMsg( "Wrong HEX file format, does not start with colon! " + "Line from file was: (" + hexLine + ")." ); + + /* Parse length, offset and type */ + recp->length = Util.convertHex( hexLine.substr( 1, 2 ) ); + recp->offset = Util.convertHex( hexLine.substr( 3, 4 ) ); + recp->type = Util.convertHex( hexLine.substr( 7, 2 ) ); + + /* We now know how long the record should be */ + if( hexLine.size() < (11+recp->length*2) ) + throw new ErrorMsg( "Wrong HEX file format, missing fields! " + "Line from file was: (" + hexLine + ")." ); + + /* Process checksum */ + checksum = recp->length; + checksum += (unsigned char) ((recp->offset >> 8) & 0xff); + checksum += (unsigned char) (recp->offset & 0xff); + checksum += recp->type; + + /* Parse data fields */ + if( recp->length ) + { + recp->data = new unsigned char[ recp->length ]; + + /* Read data from record */ + for( recordPos = 0; recordPos < recp->length; recordPos++ ) + { + recp->data[ recordPos ] = Util.convertHex( hexLine.substr( 9 + recordPos*2, 2 ) ); + checksum += recp->data[ recordPos ]; + } + } + + /* Correct checksum? */ + checksum += Util.convertHex( hexLine.substr( 9 + recp->length*2, 2 ) ); + if( checksum != 0 ) + { + throw new ErrorMsg( "Wrong checksum for HEX record! " + "Line from file was: (" + hexLine + ")." ); + } +} + + + +/* Constructor */ +HEXFile::HEXFile( long buffersize, long value ) +{ + if( buffersize <= 0 ) + throw new ErrorMsg( "Cannot have zero-size HEX buffer!" ); + + data = new unsigned char[ buffersize ]; + + if( !data ) + throw new ErrorMsg( "Memory allocation failed for HEX-line-buffer!" ); + + size = buffersize; + + clearAll( value ); +} + + +/* Destructor */ +HEXFile::~HEXFile() +{ + if( data ) delete data; +} + + +void HEXFile::readFile( const string & _filename ) +{ + ifstream f; + string hexLine; // Contains one line of the HEX file. + HEXRecord rec; // Temp record. + + long baseAddress; // Base address for extended addressing modes. + long dataPos; // Data position in record. + + /* Attempt to open file */ + f.open( _filename.c_str(), ios::in ); + if( !f ) + throw new ErrorMsg( "Error opening HEX file for input!" ); + + /* Prepare */ + baseAddress = 0; + start = size; + end = 0; + + /* Parse records */ + f >> hexLine; // Read one line. + while( !f.eof() ) + { + Util.progress( "#" ); // Advance progress indicator. + + /* Process record according to type */ + parseRecord( hexLine, &rec ); + + switch( rec.type ) + { + case 0x00 : // Data record ? + /* Copy data */ + if( baseAddress + rec.offset + rec.length > size ) + throw new ErrorMsg( "HEX file defines data outside buffer limits! " + "Make sure file does not contain data outside device " + "memory limits. " + "Line from file was: (" + hexLine + ")." ); + + for( dataPos = 0; dataPos < rec.length; dataPos++ ) + data[ baseAddress + rec.offset + dataPos ] = rec.data[ dataPos ]; + + /* Update byte usage */ + if( baseAddress + rec.offset < start ) + start = baseAddress + rec.offset; + + if( baseAddress + rec.offset + rec.length - 1 > end ) + end = baseAddress + rec.offset + rec.length - 1; + + break; + + + case 0x02 : // Extended segment address record ? + baseAddress = (rec.data[0] << 8) | rec.data[1]; + baseAddress <<= 4; + break; + + case 0x03 : // Start segment address record ? + break; // Ignore it, since we have no influence on execution start address. + + case 0x04 : // Extended linear address record ? + baseAddress = (rec.data[0] << 8) | rec.data[1]; + baseAddress <<= 16; + break; + + case 0x05 : // Start linear address record ? + break; // Ignore it, since we have no influence on exectuion start address. + + case 0x01 : // End of file record ? + f.close(); + Util.progress( "\r\n" ); // Finish progress indicator. + return; + + default: + throw new ErrorMsg( "Unsupported HEX record format! " + "Line from file was: (" + hexLine + ")." ); + } + + f >> hexLine; // Read next line. + } + + + /* We should not end up here */ + throw new ErrorMsg( "Premature end of file encountered! Make sure file " + "contains an EOF-record." ); +} + + +void HEXFile::writeFile( const string & _filename ) +{ + ofstream f; + HEXRecord rec; // Temp record. + + long baseAddress; // Absolute data position. + long offset; // Offset from base address. + long dataPos; // Position inside data record. + + enum + { + _first, + _writing, + _passed64k + } status; // Write status, see usage below. + + /* Attempt to create file */ + f.open( _filename.c_str(), ios::out ); + if( !f ) + throw new ErrorMsg( "Error opening HEX file for output!" ); + + /* Prepare */ + status = _first; + rec.data = new unsigned char[ 16 ]; // Use only 16 byte records. + + baseAddress = start & ~0xffff; // 64K aligned address. + offset = start & 0xffff; // Offset from the aligned address. + dataPos = 0; + + /* Write first base address record to HEX file */ + rec.length = 2; + rec.offset = 0; + rec.type = 0x02; + rec.data[1] = 0x00; + rec.data[0] = baseAddress >> 12; // Give 4k page index. + writeRecord( f, &rec ); // Write the HEX record to file. + + + /* Write all bytes in used range */ + do + { + /* Put data into record */ + rec.data[ dataPos ] = data[ baseAddress + offset + dataPos ]; + dataPos++; + + /* Check if we need to write out the current data record */ + if( offset + dataPos >= 0x10000 || // Reached 64k boundary? + dataPos >= 16 || // Data record full? + baseAddress + offset + dataPos > end ) // End of used range reached? + { + /* Write current data record */ + rec.length = dataPos; + rec.offset = offset; + rec.type = 0x00; // Data record. + + Util.progress( "#" ); // Advance progress indicator. + writeRecord( f, &rec ); + + offset += dataPos; + dataPos = 0; + } + + /* Check if we have passed a 64k boundary */ + if( offset + dataPos >= 0x10000 ) + { + /* Update address pointers */ + offset -= 0x10000; + baseAddress += 0x10000; + + /* Write new base address record to HEX file */ + rec.length = 2; + rec.offset = 0; + rec.type = 0x02; + rec.data[0] = baseAddress >> 12; // Give 4k page index. + rec.data[1] = 0x00; + + writeRecord( f, &rec ); // Write the HEX record to file. + } + } while( baseAddress + offset + dataPos <= end ); + + + /* Write EOF record */ + rec.length = 0; + rec.offset = 0; + rec.type = 0x01; + + writeRecord( f, &rec ); + + f.close(); + Util.progress( "\r\n" ); // Finish progress indicator. +} + + +void HEXFile::setUsedRange( long _start, long _end ) +{ + if( _start < 0 || _end >= size || _start > _end ) + throw new ErrorMsg( "Invalid range! Start must be 0 or larger, end must be " + "inside allowed memory range." ); + + start = _start; + end = _end; +} + + +void HEXFile::clearAll( long value ) +{ + for( long i = 0; i < size; i++ ) + data[i] = (unsigned char) (value & 0xff); +} + + +long HEXFile::getData( long address ) +{ + if( address < 0 || address >= size ) + throw new ErrorMsg( "Address outside legal range!" ); + + return data[ address ]; +} + + +void HEXFile::setData( long address, long value ) +{ + if( address < 0 || address >= size ) + throw new ErrorMsg( "Address outside legal range!" ); + + data[ address ] = (unsigned char) (value & 0xff); +} + + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/HEXParser.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/HEXParser.hpp new file mode 100644 index 00000000..46406c6e --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/HEXParser.hpp @@ -0,0 +1,67 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : HEXParser.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A simple Intel HEX file format reader/writer. + * + * + ****************************************************************************/ +#ifndef HEXPARSER_HPP +#define HEXPARSER_HPP + +using namespace std; + +#include "ErrorMsg.hpp" +#include "Utility.hpp" +#include +#include +#include + +struct HEXRecord; // Preliminary definition. + +class HEXFile +{ + protected: + unsigned char * data; // Holds the data bytes. + long start, end; // Used data range. + long size; // Size of databuffer. + + void writeRecord( ofstream & f, HEXRecord * recp ); + void parseRecord( const string & hexLine, HEXRecord * recp ); + + public: + /* Constructor */ + HEXFile( long buffersize, long value = 0xff ); + + /* Destructor */ + ~HEXFile(); + + /* Methods */ + void readFile( const string & _filename ); // Read data from HEX file. + void writeFile( const string & _filename ); // Write data to HEX file. + + void setUsedRange( long _start, long _end ); // Sets the used range. + void clearAll( long value = 0xff ); // Set databuffer to this value. + + long getRangeStart() { return start; } + long getRangeEnd() { return end; } + long getData( long address ); + void setData( long address, long value ); + long getSize() { return size; } +}; + + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/JobInfo.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/JobInfo.cpp new file mode 100644 index 00000000..58feff69 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/JobInfo.cpp @@ -0,0 +1,1297 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : JobInfo.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class holding information on what the AVR Open-Source Programmer + * should do. The information is derived from the command-line. + * + * + ****************************************************************************/ +#include "JobInfo.hpp" + +#include + +#define VERSIONSTRING "$Revision: 1163 $" // For use in later text output. + +#define TIMEOUT 5 +#define TIMEOUTSTRING "5" + + +JobInfo::JobInfo() +{ + /* Initialize variables */ + showHelp = false; + silentMode = false; + noProgressIndicator = false; + readSignature = false; + chipErase = false; + getHWrevision = false; + getSWrevision = false; + programFlash = false; + programEEPROM = false; + readFlash = false; + readEEPROM = false; + verifyFlash = false; + verifyEEPROM = false; + readLockBits = false; + readFuseBits = false; + readOSCCAL = false; + + deviceName.erase(); + inputFileFlash.erase(); + inputFileEEPROM.erase(); + outputFileFlash.erase(); + outputFileEEPROM.erase(); + + OSCCAL_Parameter = -1; + OSCCAL_FlashAddress = -1; + OSCCAL_EEPROMAddress = -1; + + programLockBits = -1; + verifyLockBits = -1; + + programFuseBits = -1; + programExtendedFuseBits = -1; + verifyFuseBits = -1; + verifyExtendedFuseBits = -1; + + memoryFillPattern = -1; + + flashStartAddress = -1; + flashEndAddress = -1; + + eepromStartAddress = -1; + eepromEndAddress = -1; + + comPort = -1; +} + + + +void JobInfo::parseCommandline( int argc, char *argv[] ) +{ + char * param; // Temp string ptr for holding current parsed parameter. + int comma; // Temp position for comma separator in address ranges. + + /* Get application directory */ + string ownpath = argv[0]; + int slash_pos = ownpath.find_last_of( "\\/" ); // Search for last og / or \. + if( slash_pos == string::npos ) // Not found? + { + ownpath.assign( "." ); // The current directory is the AVROSP EXE path also. + } else + { + ownpath.erase( slash_pos ); // Remove from and including the last slash separator. + } + + searchpath.push_back( "." ); // Add current directory also. + searchpath.push_back( ownpath ); // Save for later. + + if( argc <= 1 ) + { + showHelp = true; + return; + } + + /* Iterate through cmdline parameters */ + for( int i = 1; i < argc; i++ ) + { + param = argv[i]; + + /* Allow parameters to start with '-' */ + if( param[0] != '-' ) + throw new ErrorMsg( "All parameters must start with '-'!" ); + + if( strlen( param ) <= 1 ) + throw new ErrorMsg( "Parameters cannot be just the minus without any characters!" ); + + /* Now for the parsing... */ + switch( param[1] ) + { + case 'a' : // Address range specified. + if( strlen( param ) <= 2 ) + throw new ErrorMsg( "Cannot use -a without memory type!" ); + + if( strlen( param ) <= 5 ) + throw new ErrorMsg( "Cannot use -a without start and end address!" ); + + /* Find comma position and set it to '0' to help hex conversion */ + comma = 2; + while( (param[comma] != 0) && (param[comma] != ',') ) + comma++; + + if( comma == strlen( param ) ) // No comma found? + throw new ErrorMsg( "No comma separator found in -a parameter!" ); + + param[comma] = 0; // It is now two separate strings for hex conversion. + + /* Convert limits */ + switch( param[2] ) + { + case 'f' : // Flash address range. + try + { + flashStartAddress = convertHex( param + 3 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Number format error in start limit for -af parameter!" ); + } + + try + { + flashEndAddress = convertHex( param + comma + 1 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Number format error in end limit for -af parameter!" ); + } + + if( flashEndAddress < flashStartAddress ) + throw new ErrorMsg( "Cannot have Flash end limit less than start limit!" ); + + break; + + case 'e' : // EEPROM address range. + try + { + eepromStartAddress = convertHex( param + 3 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Number format error in start limit for -ae parameter!" ); + } + + try + { + eepromEndAddress = convertHex( param + comma + 1 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Number format error in end limit for -ae parameter!" ); + } + + if( eepromEndAddress < eepromStartAddress ) + throw new ErrorMsg( "Cannot have EEPROM end limit less than start limit!" ); + + break; + + default: + throw new ErrorMsg( "Unknown choice for -a, use -af or -ae!" ); + + } + + break; + + + case 'b' : // Get revision. + if( strlen( param ) != 3 ) + throw new ErrorMsg( "Specify SW og HW revision, not just -b!" ); + + switch( param[2] ) + { + case 'h' : // Hardware revision. + getHWrevision = true; + break; + + case 's' : // Software revision. + getSWrevision = true; + break; + + default: + throw new ErrorMsg( "Unknown choice for -b, use -bs or -bh!" ); + } + + break; + + + case 'c' : // Specify COM port. + if( strlen( param ) != 6 ) + throw new ErrorMsg( "COM port parameter syntax is -cCOMx!" ); + + if( param[2] != 'C' || param[3] != 'O' || param[4] != 'M' ) + throw new ErrorMsg( "COM port parameter syntax is -cCOMx!" ); + + if( param[5] < '1' || param[5] > '8' ) + throw new ErrorMsg( "Use COM1 to COM8!" ); + + comPort = param[5] - '0'; // Convert COM port digit to number. + break; + + + case 'd' : // Device name specified. + if( strlen( param ) <= 2 ) + throw new ErrorMsg( "Cannot use -d without the device name!" ); + + /* Copy device name string to class variable */ + deviceName.assign( param + 2 ); + break; + + + case 'e' : // Chip erase before programming. + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -e needs no extra arguments!" ); + + chipErase = true; + break; + + + case 'E' : // Set extended fuse bits. + if( strlen( param ) != 4 ) + throw new ErrorMsg( "Use two hex digits for the -E parameter!" ); + + try + { + programExtendedFuseBits = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -E parameter!" ); + } + + break; + + + case 'f' : // Set fuse bits. + if( strlen( param ) != 6 ) + throw new ErrorMsg( "Use four hex digits for the -f parameter!" ); + + try + { + programFuseBits = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -f parameter!" ); + } + + break; + + + case 'F' : // Verify fuse bits. + if( strlen( param ) != 6 ) + throw new ErrorMsg( "Use four hex digits for the -F parameter!" ); + + try + { + verifyFuseBits = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -F parameter!" ); + } + + break; + + + case 'g' : // Silent operation. + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -g needs no extra arguments!" ); + + silentMode = true; + break; + + + case 'G' : // Verify extended fuse bits. + if( strlen( param ) != 4 ) + throw new ErrorMsg( "Use two hex digits for the -G parameter!" ); + + try + { + verifyExtendedFuseBits = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -G parameter!" ); + } + + break; + + + case 'h' : // Help screen. + case '?' : // Help screen. + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -h and -? needs no extra arguments!" ); + + showHelp = true; + break; + + + case 'i' : // Input file specified. + if( strlen( param ) <= 2 ) + throw new ErrorMsg( "Cannot use -i without memory type!" ); + + if( strlen( param ) <= 3 ) + throw new ErrorMsg( "Cannot use -i without file name!" ); + + /* Copy file name string to correct class variable */ + switch( param[2] ) + { + case 'f' : // Flash input file. + inputFileFlash.assign( param + 3 ); + break; + + case 'e' : // EEPROM input file. + inputFileEEPROM.assign( param + 3 ); + break; + + default: + throw new ErrorMsg( "Unknown choice for -i, use -if or -ie!" ); + } + + break; + + + case 'l' : // Set lock bits. + if( strlen( param ) != 4 ) + throw new ErrorMsg( "Use two hex digits for the -l parameter!" ); + + try + { + programLockBits = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -l parameter!" ); + } + + break; + + + case 'L' : // Verify lock bits. + if( strlen( param ) != 4 ) + throw new ErrorMsg( "Use two hex digits for the -l parameter!" ); + + try + { + verifyLockBits = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -L parameter!" ); + } + + break; + + + case 'o' : // Output file specified. + if( strlen( param ) <= 2 ) + throw new ErrorMsg( "Cannot use -o without memory type!" ); + + if( strlen( param ) <= 3 ) + throw new ErrorMsg( "Cannot use -o without file name!" ); + + /* Copy file name string to correct class variable */ + switch( param[2] ) + { + case 'f' : // Flash output file. + outputFileFlash.assign( param + 3 ); + break; + + case 'e' : // EEPROM output file. + outputFileEEPROM.assign( param + 3 ); + break; + + default: + throw new ErrorMsg( "Unknown choice for -o, use -of or -oe!" ); + } + + break; + + + case 'O' : // Read OSCCAL byte. + switch( strlen( param ) ) + { + case 2 : // No value specified, use first OSCCAL byte. + readOSCCAL = true; + OSCCAL_Parameter = 0; // First OSCCAL byte. + break; + + case 3 : // Byte index specified. + case 4 : + readOSCCAL = true; + try + { + OSCCAL_Parameter = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -O parameter!" ); + } + + break; + + + case 5 : // Direct value specified. + if( param[2] != '#' ) + throw new ErrorMsg( "Use one or two hex digits for -O and two for -O#!" ); + + readOSCCAL = false; + try + { + OSCCAL_Parameter = convertHex( param + 3 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -O# parameter!" ); + } + + break; + + default: + throw new ErrorMsg( "Invalid use of -O or -O# parameter!" ); + } + + break; + + + case 'p' : // Program data. + if( strlen( param ) != 3 ) + throw new ErrorMsg( "Specify memory type, not just -p!" ); + + switch( param[2] ) + { + case 'f' : // Program Flash memory. + programFlash = true; + break; + + case 'e' : // Program EEPROM memory. + programEEPROM = true; + break; + + case 'b' : // Both. + programFlash = true; + programEEPROM = true; + break; + + default: + throw new ErrorMsg( "Unknown choice for -p, use -pf, -pe or -pb!" ); + } + + break; + + + case 'q' : // Read all fuse bits. + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -q needs no extra arguments!" ); + + readFuseBits = true; + break; + + + case 'r' : // Read data. + if( strlen( param ) != 3 ) + throw new ErrorMsg( "Specify memory type, not just -r!" ); + + switch( param[2] ) + { + case 'f' : // Read Flash memory. + readFlash = true; + break; + + case 'e' : // Read EEPROM memory. + readEEPROM = true; + break; + + case 'b' : // Both. + readFlash = true; + readEEPROM = true; + break; + + default: + throw new ErrorMsg( "Unknown choice for -r, use -rf, -re or -rb!" ); + } + + break; + + + case 's' : // Read signature byte. + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -s needs no extra arguments!" ); + + readSignature = true; + break; + + + case 'S' : // Write OSCCAL byte to memory. + if( strlen( param ) <= 2 ) + throw new ErrorMsg( "Cannot use -S without memory type!" ); + + if( strlen( param ) <= 3 ) + throw new ErrorMsg( "Cannot use -S without byte address!" ); + + switch( param[2] ) + { + case 'f' : // Write to Flash address. + try + { + OSCCAL_FlashAddress = convertHex( param + 3 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Cannot convert hex number for -Sf parameter!" ); + } + break; + + case 'e' : // Write to EEPROM address. + try + { + OSCCAL_EEPROMAddress = convertHex( param + 3 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Cannot convert hex number for -Se parameter!" ); + } + break; + + default: + throw new ErrorMsg( "Unknown choice for -S, use -Sf or -Se!" ); + } + + break; + + + case 'v' : // Verify data. + if( strlen( param ) != 3 ) + throw new ErrorMsg( "Specify memory type, not just -v!" ); + + switch( param[2] ) + { + case 'f' : // Verify Flash memory. + verifyFlash = true; + break; + + case 'e' : // Verify EEPROM memory. + verifyEEPROM = true; + break; + + case 'b' : // Both. + verifyFlash = true; + verifyEEPROM = true; + break; + + default: + throw new ErrorMsg( "Unknown choice for -v, use -vf, -ve or -vb!" ); + } + + break; + + + case 'x' : // Fill unspecified memory. + if( strlen( param ) != 4 ) + throw new ErrorMsg( "Use two hex digits for the -x parameter!" ); + + try + { + memoryFillPattern = convertHex( param + 2 ); + } + catch( ErrorMsg * e ) + { + delete e; + throw new ErrorMsg( "Hex number format error for -x parameter!" ); + } + + break; + + + case 'y' : // Read lock bits. + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -y needs no extra arguments!" ); + + readLockBits = true; + break; + + + case 'z' : // No progress indicator? + if( strlen( param ) != 2 ) + throw new ErrorMsg( "Parameter -z needs no extra arguments!" ); + + noProgressIndicator = true; + break; + + + default: + throw new ErrorMsg( "Unknow parameter!" ); + } + } +} + + +void JobInfo::help() +{ + cout + << "Command Line Switches:" << endl + << " [-d device name] [-if infile] [-ie infile] [-of outfile] [-oe outfile]" << endl + << " [-s] [-O index] [-O#value] [-Sf addr] [-Se addr] [-e] [-p f|e|b]" << endl + << " [-r f|e|b] [-v f|e|b] [-l value] [-L value] [-y] [-f value] [-E value]" << endl + << " [-F value] [-G value] [-q] [-x value] [-af start,stop] [-ae start,stop]" << endl + << " [-c port] [-b h|s] [-g] [-z] [-h|?]" << endl + << endl + << "Parameters:" << endl + << "d Device name. Must be applied when programming the device." << endl + << "if Name of FLASH input file. Required for programming or verification" << endl + << " of the FLASH memory. The file format is Intel Extended HEX." << endl + << "ie Name of EEPROM input file. Required for programming or verification" << endl + << " of the EEPROM memory. The file format is Intel Extended HEX." << endl + << "of Name of FLASH output file. Required for readout of the FLASH memory." << endl + << " The file format is Intel Extended HEX." << endl + << "oe Name of EEPROM output file. Required for readout of the EEPROM" << endl + << " memory. The file format is Intel Extended HEX." << endl + << "s Read signature bytes." << endl; + getch(); + cout + << "O Read oscillator calibration byte. 'index' is optional." << endl + << "O# User-defined oscillator calibration value." << endl + << "Sf Write oscillator cal. byte to FLASH memory. 'addr' is byte address." << endl + << "Se Write oscillator cal. byte to EEPROM memory. 'addr' is byte address." << endl + << "e Erase device. If applied with another programming parameter, the" << endl + << " device will be erased before any other programming takes place." << endl + << "p Program device; FLASH (f), EEPROM (e) or both (b). Corresponding" << endl + << " input files are required." << endl + << "r Read out device; FLASH (f), EEPROM (e) or both (b). Corresponding" << endl + << " output files are required" << endl + << "v Verify device; FLASH (f), EEPROM (e) or both (b). Can be used with" << endl + << " -p or alone. Corresponding input files are required." << endl + << "l Set lock byte. 'value' is an 8-bit hex. value." << endl + << "L Verify lock byte. 'value' is an 8-bit hex. value to verify against." << endl + << "y Read back lock byte." << endl + << "f Set fuse bytes. 'value' is a 16-bit hex. value describing the" << endl + << " settings for the upper and lower fuse bytes." << endl + << "E Set extended fuse byte. 'value' is an 8-bit hex. value describing the" << endl + << " extend fuse settings." << endl + << "F Verify fuse bytes. 'value' is a 16-bit hex. value to verify against." << endl; + getch(); + cout + << "G Verify extended fuse byte. 'value' is an 8-bit hex. value to" << endl + << " verify against." << endl + << "q Read back fuse bytes." << endl + << "x Fill unspecified locations with a value (00-ff). The default is" << endl + << " to not program locations not specified in the input files." << endl + << "af FLASH address range. Specifies the address range of operations. The" << endl + << " default is the entire FLASH. Byte addresses in hex." << endl + << "ae EEPROM address range. Specifies the address range of operations." << endl + << " The default is the entire EEPROM. Byte addresses in hex." << endl + << "c Select communication port; 'COM1' to 'COM8'. If this parameter is" << endl + << " omitted the program will scan the COM ports for a programmer." << endl + << "b Get revisions; hardware revision (h) and software revision (s)." << endl + << "g Silent operation." << endl + << "z No progress indicator. E.g. if piping to a file for log purposes, use" << endl + << " this option to avoid the characters used for the indicator." << endl + << "h|? Help information (overrides all other settings)." << endl + << endl + << "Example:" << endl + << " AVROSP -dATmega128 -ifmyapp.hex -pf" << endl; +} + + +long JobInfo::convertHex( char * txt ) +{ + string t( txt ); + return Util.convertHex( t ); +} + + +void JobInfo::doJob() +{ + long scanCOM; + SerialPort * com; + AVRProgrammer * prog; + AVRDevice * avr; + string programmerID; + long sig0, sig1, sig2; // Signature bytes. + + /* Set correct silent and progress indicator status */ + if( silentMode ) + { + Util.muteLog(); + Util.muteProgress(); // Silent also includes progress indicator. + } + + if( noProgressIndicator ) + Util.muteProgress(); + + /* Application header text */ + Util.log( "AVR Open-source Programmer " VERSIONSTRING " (C) 2004 Atmel Corp.\n\r\n\r" ); + + /* Show help screen? */ + if( showHelp ) + { + help(); + return; + } + + Util.log( "Serial port timeout set to " TIMEOUTSTRING " sec.\r\n" ); + + /* Need to scan for COM port? */ + if( comPort == -1 ) + { + Util.log( "Scanning COM ports for supported programmer...\n\r" ); + + for( scanCOM = 1; scanCOM <= 8; scanCOM++ ) + { + Util.progress( "COM" + Util.convertLong( scanCOM ) + "...\r\n" ); + + try + { + /* Try to communicate */ + com = NULL; + com = new SerialPort( scanCOM, TIMEOUT ); + com->openChannel(); + programmerID = AVRProgrammer::readProgrammerID( com ); + + /* Contact! Check ID... Add custom handler signatures here */ + if( programmerID == "AVRBOOT" || programmerID == "AVR ISP" ) + { + break; + } + + delete com; + Util.progress( programmerID + " found - not supported!\r\n" ); + } + catch( ErrorMsg * e ) + { + /* No contact on COM port, skip to next */ + if( com != NULL ) delete com; + delete e; + } + } + + /* Exit if no supported programmers found */ + if( scanCOM > 8 ) + { + Util.log( "No supported programmers found!\r\n" ); + return; + } + + comPort = scanCOM; + + } else // ... COM port is specified + { + /* Try to communicate, errors will propagate to caller */ + com = new SerialPort( comPort, TIMEOUT ); + com->openChannel(); + programmerID = AVRProgrammer::readProgrammerID( com ); + + /* Contact! Check ID */ + if( programmerID != "AVRBOOT" && programmerID != "AVR ISP" ) + throw new ErrorMsg( "Programmer not supported!" ); + } + + Util.log( "Found " + programmerID + " on COM" + Util.convertLong( comPort ) + "!\r\n" ); + + /* Create programmer interface object, add custom handlers here */ + if( programmerID == "AVRBOOT" ) + { + prog = new AVRBootloader( com ); + } + + if( programmerID == "AVR ISP" ) + { + prog = new AVRInSystemProg( com ); + } + + Util.log( "Entering programming mode...\r\n" ); + prog->enterProgrammingMode(); // Ignore return code. + + /* Do device independent operations */ + doDeviceIndependent( prog ); + + /* Finished if no device name is specified */ + if( deviceName.size() == 0 ) + { + Util.log( "Device name not specified!\r\n" ); + return; + } + + /* Parse XML part description file */ + avr = new AVRDevice( deviceName ); + Util.log( "Parsing XML file for device parameters...\r\n" ); + Util.parsePath( searchpath ); + avr->readParametersFromAVRStudio( searchpath ); + + /* Verify that the device signature matches the signature from the XML file */ + avr->getSignature( &sig0, &sig1, &sig2 ); + if( prog->checkSignature( sig0, sig1, sig2 ) ) + Util.log( "Signature matches device!\r\n" ); + + /* Do device dependent operations */ + doDeviceDependent( prog, avr ); + + /* Clean up */ + Util.log( "Leaving programming mode...\r\n" ); + prog->leaveProgrammingMode(); // Ignore return code. + + delete avr; + delete prog; + delete com; +} + + +void JobInfo::doDeviceIndependent( AVRProgrammer * prog ) +{ + long sig0, sig1, sig2; // Signature bytes. + long minor, major; // Minor and major programmer revision. + + /* Read signature? */ + if( readSignature ) + { + Util.log( "Reading signature bytes: " ); + if( !prog->readSignature( &sig0, &sig1, &sig2 ) ) + throw new ErrorMsg( "Signature readout is not supported by this programmer!" ); + + /* No pass through Util, since user wants the info */ + cout.fill( '0' ); + cout << hex + << "0x" << setw(2) << sig0 << " " + << "0x" << setw(2) << sig1 << " " + << "0x" << setw(2) << sig2 << endl; + } + + /* Get software version? */ + if( getSWrevision ) + { + Util.log( "Reading programmer software revision: " ); + if( !prog->programmerSoftwareVersion( &major, &minor ) ) + throw new ErrorMsg( "Software revision readout is not supported by this programmer!" ); + + /* No pass through Util, since user wants the info */ + cout << (char) (major & 0xff) << "." << (char) (minor & 0xff) << endl; + } + + /* Get software version? */ + if( getHWrevision ) + { + Util.log( "Reading programmer hardware revision: " ); + if( !prog->programmerHardwareVersion( &major, &minor ) ) + throw new ErrorMsg( "Hardware revision readout is not supported by this programmer!" ); + + /* No pass through Util, since user wants the info */ + cout << (char) (major & 0xff) << "." << (char) (minor & 0xff) << endl; + } +} + + +void JobInfo::doDeviceDependent( AVRProgrammer * prog, AVRDevice * avr ) +{ + HEXFile * hex; + HEXFile * hex_v; // Used for verifying memory contents. + long pos; // Used when comparing data. + long bits; // Used for lock and fuse bits. + + /* Set programmer pagesize */ + prog->setPagesize( avr->getPageSize() ); + + /* Check if specified address limits are within device range */ + if( flashEndAddress != -1 ) + { + if( flashEndAddress >= avr->getFlashSize() ) + throw new ErrorMsg( "Specified Flash address range is outside device address space!" ); + } else + { + flashStartAddress = 0; + flashEndAddress = avr->getFlashSize() - 1; + } + + if( eepromEndAddress != -1 ) + { + if( eepromEndAddress >= avr->getEEPROMSize() ) + throw new ErrorMsg( "Specified EEPROM address range is outside device address space!" ); + } else + { + eepromStartAddress = 0; + eepromEndAddress = avr->getEEPROMSize() - 1; + } + + + /* Read out Flash contents? */ + if( readFlash ) + { + /* Check that filename has been specified */ + if( outputFileFlash.size() == 0 ) + throw new ErrorMsg( "Cannot read Flash without output file specified!" ); + + /* Prepare the file */ + hex = new HEXFile( avr->getFlashSize() ); + hex->setUsedRange( flashStartAddress, flashEndAddress ); + + /* Read data and save file */ + Util.log( "Reading Flash contents...\r\n" ); + if( !prog->readFlash( hex ) ) + throw new ErrorMsg( "Flash readout is not supported by this programmer!" ); + Util.log( "Writing HEX output file...\r\n" ); + hex->writeFile( outputFileFlash ); + + delete hex; + } + + + /* Read out EEPROM contents? */ + if( readEEPROM ) + { + /* Check that filename has been specified */ + if( outputFileEEPROM.size() == 0 ) + throw new ErrorMsg( "Cannot read EEPROM without output file specified!" ); + + /* Prepare the file */ + hex = new HEXFile( avr->getEEPROMSize() ); + hex->setUsedRange( eepromStartAddress, eepromEndAddress ); + + /* Read data and save file */ + Util.log( "Reading EEPROM contents...\r\n" ); + if( !prog->readEEPROM( hex ) ) + throw new ErrorMsg( "EEPROM readout is not supported by this programmer!" ); + Util.log( "Writing HEX output file...\r\n" ); + hex->writeFile( outputFileEEPROM ); + + delete hex; + } + + + /* Read lock bits? */ + if( readLockBits ) + { + Util.log( "Reading lock bits...\r\n" ); + if( !prog->readLockBits( &bits ) ) + throw new ErrorMsg( "Lock bit readout is not supported by this programmer!" ); + cout << "0x" << std::hex << setw(2) << bits << endl; + } + + + /* Read fuse bits (both ordinary and extended)? */ + if( readFuseBits ) + { + if( !avr->getFuseStatus() ) + throw new ErrorMsg( "Selected device has no fuse bits!" ); + + Util.log( "Reading fuse bits...\r\n" ); + if( !prog->readFuseBits( &bits ) ) + throw new ErrorMsg( "Fuse bit readout is not supported by this programmer!" ); + cout << "0x" << std::hex << setw(4) << bits << endl; + + if( avr->getXFuseStatus() ) + { + if( !prog->readExtendedFuseBits( &bits ) ) + throw new ErrorMsg( "Extended fuse bit readout is not supported by this programmer!" ); + cout << "0x" << std::hex << setw(2) << bits << endl; + } + } + + + /* Erase chip before programming anything? */ + if( chipErase ) + { + Util.log( "Erasing chip contents...\r\n" ); + if( !prog->chipErase() ) + throw new ErrorMsg( "Chip erase is not supported by this programmer!" ); + } + + + /* Prepare input hex file for flash */ + if( programFlash || verifyFlash ) + { + /* Check that filename has been specified */ + if( inputFileFlash.size() == 0 ) + throw new ErrorMsg( "Cannot program or verify Flash without input file specified!" ); + + /* Prepare the file */ + hex = new HEXFile( avr->getFlashSize() ); + + /* Fill if wanted */ + if( memoryFillPattern != -1 ) + hex->clearAll( memoryFillPattern ); + + /* Read file */ + Util.log( "Reading HEX input file for flash operations...\r\n" ); + hex->readFile( inputFileFlash ); + + /* Check limits */ + if( hex->getRangeStart() > flashEndAddress || + hex->getRangeEnd() < flashStartAddress ) + throw new ErrorMsg( "HEX file defines data outside specified range!" ); + + if( memoryFillPattern == -1 ) + { + if( hex->getRangeStart() > flashStartAddress ) + flashStartAddress = hex->getRangeStart(); + + if( hex->getRangeEnd() < flashEndAddress ) + flashEndAddress = hex->getRangeEnd(); + } + + hex->setUsedRange( flashStartAddress, flashEndAddress ); + } + + + /* Program new Flash contents? */ + if( programFlash ) + { + /* Program data */ + Util.log( "Programming Flash contents...\r\n" ); + if( !prog->writeFlash( hex ) ) + throw new ErrorMsg( "Flash programming is not supported by this programmer!" ); + } + + + /* Verify Flash contents? */ + if( verifyFlash ) + { + /* Prepare HEX file for comparision */ + hex_v = new HEXFile( avr->getFlashSize() ); + + /* Compare to Flash */ + Util.log( "Reading Flash contents...\r\n" ); + hex_v->setUsedRange( hex->getRangeStart(), hex->getRangeEnd() ); + if( !prog->readFlash( hex_v ) ) + throw new ErrorMsg( "Flash readout is not supported by this programmer!" ); + + /* Compare data */ + Util.log( "Comparing Flash data...\r\n" ); + + for( pos = hex->getRangeStart(); pos <= hex->getRangeEnd(); pos++ ) + { + if( hex->getData( pos ) != hex_v->getData( pos ) ) + { + cout << "Unequal at address 0x" << std::hex << pos << "!" << endl; + break; + } + } + + if( pos > hex->getRangeEnd() ) // All equal? + { + cout << "Equal!" << endl; + } + + delete hex_v; + } + + if( programFlash || verifyFlash ) + delete hex; + + + /* Prepare input hex file for EEPROM */ + if( programEEPROM || verifyEEPROM ) + { + /* Check that filename has been specified */ + if( inputFileEEPROM.size() == 0 ) + throw new ErrorMsg( "Cannot program or verify EEPROM without input file specified!" ); + + /* Prepare the file */ + hex = new HEXFile( avr->getEEPROMSize() ); + + /* Fill if wanted */ + if( memoryFillPattern != -1 ) + hex->clearAll( memoryFillPattern ); + + /* Read file and program contents */ + Util.log( "Reading HEX input file for EEPROM operations...\r\n" ); + hex->readFile( inputFileEEPROM ); + + /* Check limits */ + if( hex->getRangeStart() > eepromEndAddress || + hex->getRangeEnd() < eepromStartAddress ) + throw new ErrorMsg( "HEX file defines data outside specified range!" ); + + if( memoryFillPattern == -1 ) + { + if( hex->getRangeStart() > eepromStartAddress ) + eepromStartAddress = hex->getRangeStart(); + + if( hex->getRangeEnd() < eepromEndAddress ) + eepromEndAddress = hex->getRangeEnd(); + } + + hex->setUsedRange( eepromStartAddress, eepromEndAddress ); + } + + + /* Program new EEPROM contents? */ + if( programEEPROM ) + { + /* Program data */ + Util.log( "Programming EEPROM contents...\r\n" ); + if( !prog->writeEEPROM( hex ) ) + throw new ErrorMsg( "EEPROM programming is not supported by this programmer!" ); + } + + /* Verify EEPROM contents? */ + if( verifyEEPROM ) + { + /* Prepare HEX file for comparision */ + hex_v = new HEXFile( avr->getEEPROMSize() ); + + /* Compare to EEPROM */ + Util.log( "Reading EEPROM contents...\r\n" ); + hex_v->setUsedRange( hex->getRangeStart(), hex->getRangeEnd() ); + if( !prog->readEEPROM( hex_v ) ) + throw new ErrorMsg( "EEPROM readout is not supported by this programmer!" ); + + /* Compare data */ + Util.log( "Comparing EEPROM data...\r\n" ); + for( pos = hex->getRangeStart(); pos <= hex->getRangeEnd(); pos++ ) + { + if( hex->getData( pos ) != hex_v->getData( pos ) ) + { + cout << "Unequal at address 0x" << std::hex << pos << "!" << endl; + break; + } + } + + if( pos > hex->getRangeEnd() ) // All equal? + { + cout << "Equal!" << endl; + } + + delete hex_v; + } + + if( programEEPROM || verifyEEPROM ) + delete hex; + + + /* Program lock bits */ + if( programLockBits != -1 ) + { + Util.log( "Programming lock bits...\r\n" ); + if( !prog->writeLockBits( programLockBits ) ) + throw new ErrorMsg( "Lock bit programming is not supported by this programmer!" ); + } + + + /* Program fuse bits */ + if( programFuseBits != -1 ) + { + if( !avr->getFuseStatus() ) + throw new ErrorMsg( "Selected device has no fuse bits!" ); + + Util.log( "Programming fuse bits...\r\n" ); + if( !prog->writeFuseBits( programFuseBits ) ) + throw new ErrorMsg( "Fuse bit programming is not supported by this programmer!" ); + } + + + /* Program extended fuse bits */ + if( programExtendedFuseBits != -1 ) + { + if( !avr->getXFuseStatus() ) + throw new ErrorMsg( "Selected device has no extended fuse bits!" ); + + Util.log( "Programming extended fuse bits...\r\n" ); + if( !prog->writeExtendedFuseBits( programExtendedFuseBits ) ) + throw new ErrorMsg( "Extended fuse bit programming is not supported by this programmer!" ); + } + + + /* Verify lock bits */ + if( verifyLockBits != -1 ) + { + Util.log( "Verifying lock bits...\r\n" ); + if( !prog->readLockBits( &bits ) ) + throw new ErrorMsg( "Lock bit readout is not supported by this programmer!" ); + if( bits == verifyLockBits ) + cout << "Equal!" << endl; + else + cout << "Unequal!" << endl; + } + + + /* Verify fuse bits */ + if( verifyFuseBits != -1 ) + { + if( !avr->getFuseStatus() ) + throw new ErrorMsg( "Selected device has no fuse bits!" ); + + Util.log( "Verifying fuse bits...\r\n" ); + if( !prog->readFuseBits( &bits ) ) + throw new ErrorMsg( "Fuse bit readout is not supported by this programmer!" ); + if( bits == verifyFuseBits ) + cout << "Equal!" << endl; + else + cout << "Unequal!" << endl; + } + + + /* Verify extended fuse bits */ + if( verifyExtendedFuseBits != -1 ) + { + if( !avr->getXFuseStatus() ) + throw new ErrorMsg( "Selected device has no extended fuse bits!" ); + + Util.log( "Verifying extended fuse bits...\r\n" ); + if( !prog->readExtendedFuseBits( &bits ) ) + throw new ErrorMsg( "Extended fuse bit readout is not supported by this programmer!" ); + if( bits == verifyExtendedFuseBits ) + cout << "Equal!" << endl; + else + cout << "Unequal!" << endl; + } + + + /* Read osccal value? */ + if( OSCCAL_Parameter != -1 ) + { + /* Output to log if read from device */ + if( readOSCCAL ) + { + Util.log( "Reading OSCCAL from device...\r\n" ); + pos = OSCCAL_Parameter; + if( !prog->readOSCCAL( pos, &OSCCAL_Parameter ) ) + throw new ErrorMsg( "OSCCAL parameter readout is not supported by this programmer!" ); + cout << "0x" << std::hex << setw(2) << OSCCAL_Parameter << endl; + } + } + + + /* Write OSCCAL to Flash? */ + if( OSCCAL_FlashAddress != -1 ) + { + if( OSCCAL_Parameter == -1 ) + throw new ErrorMsg( "OSCCAL value not specified!" ); + + Util.log( "Programming OSCCAL value to Flash...\r\n" ); + if( !prog->writeFlashByte( OSCCAL_FlashAddress, OSCCAL_Parameter ) ) + throw new ErrorMsg( "Flash programming is not supported by this programmer!" ); + } + + + /* Write OSCCAL to EEPROM? */ + if( OSCCAL_EEPROMAddress != -1 ) + { + if( OSCCAL_Parameter == -1 ) + throw new ErrorMsg( "OSCCAL value not specified!" ); + + Util.log( "Programming OSCCAL value to EEPROM...\r\n" ); + if( !prog->writeEEPROMByte( OSCCAL_EEPROMAddress, OSCCAL_Parameter ) ) + throw new ErrorMsg( "EEPROM programming is not supported by this programmer!" ); + } + +} + + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/JobInfo.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/JobInfo.hpp new file mode 100644 index 00000000..0ad5ea45 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/JobInfo.hpp @@ -0,0 +1,105 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : JobInfo.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class holding information on what the AVR Open-Source Programmer + * should do. The information is derived from the command-line. + * + * + ****************************************************************************/ +#ifndef JOBINFO_HPP +#define JOBINFO_HPP + +using namespace std; + +#include +#include +#include +#include +#include "ErrorMsg.hpp" +#include "AVRProgrammer.hpp" +#include "AVRBootloader.hpp" +#include "AVRInSystemProg.hpp" +#include "AVRDevice.hpp" +#include "SerialPort.hpp" +#include "Utility.hpp" + + +class JobInfo +{ + protected: + long convertHex( char * txt ); + void help(); + void doDeviceIndependent( AVRProgrammer * prog ); + void doDeviceDependent( AVRProgrammer * prog, AVRDevice * avr ); + + + bool showHelp; // Show help screen? + bool silentMode; // No text output? + bool noProgressIndicator; // Do not show progress indicators? + bool readSignature; // Output signature bytes to screen? + bool chipErase; // Erase chip before any programming operations? + bool getHWrevision; // Get hardware revision of programmer? + bool getSWrevision; // Get software revision of programmer? + bool programFlash; // Flash programming desired? + bool programEEPROM; // E2 programming desired? + bool readFlash; // Flash readout desired? + bool readEEPROM; // E2 readout desired? + bool verifyFlash; // Flash verification desired? + bool verifyEEPROM; // E2 verification desired? + bool readLockBits; // Lock bit readout desired? + bool readFuseBits; // Fuse bit readout desired? + bool readOSCCAL; // Read or use specified OSCCAL value, if -O is used? + + string deviceName; // Specified device name. + string inputFileFlash; // Input file for Flash writing and verification. + string inputFileEEPROM; // Input file for E2 writing and verification. + string outputFileFlash; // Output file for Flash readout. + string outputFileEEPROM; // Output file for E2 readout. + + long OSCCAL_Parameter; // Value of the -O parameter, -1 if unspecified. + + long OSCCAL_FlashAddress; // Where to put OSCCAL value in flash, -1 if not. + long OSCCAL_EEPROMAddress; // Where to put OSCCAL value in E2, -1 if not. + + long programLockBits; // Change lock bits to this value, -1 if not. + long verifyLockBits; // Verify lock bits against this value, -1 if not. + + long programFuseBits; // Change fuse bits to this value, -1 if not. + long programExtendedFuseBits; // Same as above for extended fuse bits. + long verifyFuseBits; // Verify fuse bits against this value, -1 if not. + long verifyExtendedFuseBits; // Same as above for extended fuse bits. + + long memoryFillPattern; // Fill unspecified locations, -1 if not. + + long flashStartAddress; // Limit Flash operations, -1 if not. + long flashEndAddress; // ...to this address, inclusive, -1 if not. + + long eepromStartAddress; // Same as above for E2. + long eepromEndAddress; // ... + + long comPort; // Desired COM port to use, -1 if unspecified. + + vector searchpath; // Search path for XML-files. + + public: + JobInfo(); // Constructor + + void parseCommandline( int argc, char *argv[] ); + void doJob(); +}; + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/SerialPort.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/SerialPort.cpp new file mode 100644 index 00000000..f8de7470 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/SerialPort.cpp @@ -0,0 +1,194 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : SerialPort.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing serial communication through the PC COM port. + * This class is derived from the CommChannel abstract class. + * + * + ****************************************************************************/ +#include "SerialPort.hpp" + + +/* Constructor */ +SerialPort::SerialPort( long _portNumber, long _timeout ) +{ + if( _timeout < 0 ) + throw new ErrorMsg( "Negative COM-port timeout not allowed!" ); + + if( _portNumber < 1 || _portNumber > 8 ) + throw new ErrorMsg( "Only COM1 to COM8 is supported!" ); + + /* Initialize internal parameters */ + portNumber = _portNumber; + timeout = _timeout; + channelOpen = false; +} + + +/* Destructor */ +SerialPort::~SerialPort() +{ + closeChannel(); +} + + +/* Open the communication channel */ +void SerialPort::openChannel() +{ + char comName[] = "COMx"; + COMMTIMEOUTS comTimeouts; + + /* Check if channel already open */ + if( channelOpen ) + throw new ErrorMsg( "Channel already open! Cannot open port twice." ); + + /* Generate COM filename and attempt open */ + comName[3] = '0' + portNumber; + serialHandle = CreateFile( comName, GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + + /* Print error and return if failed opening port */ + if( serialHandle == INVALID_HANDLE_VALUE ) + throw new ErrorMsg( "Error opening COM port!" ); + + channelOpen = true; + + /* Store old COM port settings */ + if( !GetCommTimeouts( serialHandle, &oldComTimeouts ) ) + throw new ErrorMsg( "Error reading COM port settings!" ); + + /* Get another copy of the COM settings, and change them */ + if( !GetCommTimeouts( serialHandle, &comTimeouts ) ) + throw new ErrorMsg( "Error reading COM port settings!" ); + + comTimeouts.ReadIntervalTimeout = MAXDWORD; + comTimeouts.ReadTotalTimeoutConstant = 0; + comTimeouts.ReadTotalTimeoutMultiplier = 0; + + /* Apply new settings */ + if( !SetCommTimeouts( serialHandle, &comTimeouts ) ) + throw new ErrorMsg( "Error changing COM port settings!" ); +} + + +/* Close the communication channel */ +void SerialPort::closeChannel() +{ + if( !channelOpen ) + return; + + /* Restore old COM parameters */ + if( !SetCommTimeouts( serialHandle, &oldComTimeouts ) ) + throw new ErrorMsg( "Error changing COM port settings!" ); + + /* Release port */ + if( serialHandle != INVALID_HANDLE_VALUE ) + if( !CloseHandle( serialHandle ) ) + throw new ErrorMsg( "Error closing COM port!" ); + + channelOpen = false; +} + + + +/* Transmit a single byte */ +void SerialPort::sendByte( long data ) +{ + DWORD written; + + /* Check if channel is open */ + if( !channelOpen ) + throw new ErrorMsg( "Channel not open! Cannot send to unopened channel." ); + + /* Attempt writing */ + if( !WriteFile( serialHandle, &data, 1, &written, NULL ) ) + throw new ErrorMsg( "Error writing byte to COM port!" ); +} + + +/* Receive a single byte */ +long SerialPort::getByte() +{ + time_t startTime; + startTime = time( NULL ); // Read current time in seconds + DWORD readnum; + unsigned char data; + + /* Check if channel is open */ + if( !channelOpen ) + throw new ErrorMsg( "Channel not open! Cannot read from unopened channel." ); + + /* Attempt receiving byte until timeout limit exceeded */ + do + { + /* Read byte from port */ + if( !ReadFile( serialHandle, &data, 1, &readnum, NULL ) ) + { + throw new ErrorMsg( "Error reading byte from COM port!" ); + } + + if( readnum == 1 ) + return ((long) data) & 0xff; + + } while( time(NULL) - startTime < timeout ); + + /* Timeout */ + throw new ErrorMsg( "Timeout during COM-port read operation!" ); +} + + +/* Flush the transmit buffer */ +void SerialPort::flushTX() +{ + /* Check if channel is open */ + if( !channelOpen ) + throw new ErrorMsg( "Channel not open! Cannot flush an unopened channel." ); + + /* Purge data from write buffer */ + if( !PurgeComm( serialHandle, PURGE_TXCLEAR ) ) + throw new ErrorMsg( "Error flushing COM port TX buffer!" ); +} + + +/* Flush the receive buffer */ +void SerialPort::flushRX() +{ + /* Check if channel is open */ + if( !channelOpen ) + throw new ErrorMsg( "Channel not open! Cannot flush an unopened channel." ); + + /* Purge data from write buffer */ + if( !PurgeComm( serialHandle, PURGE_RXCLEAR ) ) + throw new ErrorMsg( "Error flushing COM port RX buffer!" ); +} + + +/* Transmit multiple bytes */ +void SerialPort::sendMultiple( unsigned char * data, long bufsize ) +{ + DWORD written; + + /* Check if channel is open */ + if( !channelOpen ) + throw new ErrorMsg( "Channel not open! Cannot write to unopened channel." ); + + /* Attempt writing */ + if( !WriteFile( serialHandle, data, bufsize, &written, NULL ) ) + throw new ErrorMsg( "Error writing multiple bytes to COM port!" ); +} + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/SerialPort.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/SerialPort.hpp new file mode 100644 index 00000000..5d4d99af --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/SerialPort.hpp @@ -0,0 +1,75 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : SerialPort.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class providing serial communication through the PC COM port. + * This class is derived from the CommChannel abstract class. + * + * + ****************************************************************************/ +#ifndef SERIALPORT_HPP +#define SERIALPORT_HPP + +using namespace std; + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include "CommChannel.hpp" +#include "ErrorMsg.hpp" + + +class SerialPort : public CommChannel +{ + protected: + long portNumber; // COMx port number. + long timeout; // Desired timeout limit when receiving data. + HANDLE serialHandle; // Win32 device handle for the com port. + COMMTIMEOUTS oldComTimeouts; // Store old serial port timeout parameters. + bool channelOpen; // Is channel open? + + public: + // Constructor taking port number, baudrate and + // timeout limit as parameters. + SerialPort( long portnumber, long timeout ); + + // Destructor. + ~SerialPort(); + + // Open the communication channel. + virtual void openChannel(); + + // Close the communication channel. + virtual void closeChannel(); + + // Transmit a single byte. + virtual void sendByte( long data ); + + // Receive a single byte. + virtual long getByte(); + + // Flush the transmit buffer. + virtual void flushTX(); + + // Flush the receive buffer. + virtual void flushRX(); + + // Transmit multiple bytes. + virtual void sendMultiple( unsigned char * data, long bufsize ); +}; + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/Utility.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/Utility.cpp new file mode 100644 index 00000000..d1916184 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/Utility.cpp @@ -0,0 +1,181 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : Utility.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class holding misc. utility methods used in AVROSP. + * + * + ****************************************************************************/ +#include "Utility.hpp" + +#include +#include +#include + +/* Global object */ +Utility Util; + + +/* Constructor */ +Utility::Utility() : + noLog( false ), + noProgress( false ) +{ + /* No code here */ +} + + +/* Destructor */ +Utility::~Utility() +{ + /* No code here */ +} + + + +void Utility::log( const string & txt ) +{ + if( !noLog ) + cout << txt; +} + + +void Utility::progress( const string & txt ) +{ + if( !noProgress ) + cout << txt; +} + + +long Utility::convertHex( const string & txt ) +{ + long result = 0; + long digit; + long i; + + if( txt.size() == 0 ) + throw new ErrorMsg( "Cannot convert zero-length hex-string to number!" ); + + if( txt.size() > 8 ) + throw new ErrorMsg( "Hex conversion overflow! Too many hex digits in string." ); + + + for( i = 0; i < txt.size(); i++ ) + { + /* Convert hex digit */ + if( txt[i] >= '0' && txt[i] <= '9' ) + digit = txt[i] - '0'; + else if( txt[i] >= 'a' && txt[i] <= 'f' ) + digit = txt[i] - 'a' + 10; + else if( txt[i] >= 'A' && txt[i] <= 'F' ) + digit = txt[i] - 'A' + 10; + else + throw new ErrorMsg( "Invalid hex digit found!" ); + + /* Add digit as least significant 4 bits of result */ + result = (result << 4) | digit; + } + + return result; +} + + +string Utility::convertLong( long num, long radix ) +{ + char buf[18]; + string res; + + itoa( num, buf, radix ); + res = buf; + return res; +} + + +void Utility::parsePath( vector & list ) +{ + /* Get environment variable and parse if it exists */ + char * pathptr = getenv( "PATH" ); + if( pathptr != NULL && pathptr[0] != 0 ) { + string path = pathptr; + int pos; + + while( (pos = path.find_first_of( ";" )) < path.length() ) { + list.push_back( path.substr( 0, pos ) ); + path.erase( 0, pos+1 ); + } + + list.push_back( path ); // Last directory. + } +} + + +bool Utility::fileExists( string filename ) +{ + /* Attempt to open file */ + ifstream f; + f.open( filename.c_str(), ios::in ); + if( !f ) { + return false; + } else { + f.close(); + return true; + } +} + + +void Utility::saveString( string txt, string filename ) +{ + ofstream f; + + f.open( filename.c_str(), ios::out ); + if( !f ) + throw new ErrorMsg( "Error opening HEX file for output!" ); + + f << txt; + + f.close(); +} + + +#ifndef NOREGISTRY +string Utility::getRegistryValue( const string & path, const string & value ) +{ + /* Code modified from MSDN */ + const long BUFSIZE=1000; + string result; + HKEY hKey; + char szAVRPath[BUFSIZE]; + DWORD dwBufLen=BUFSIZE; + LONG lRet; + + /* Open key */ + lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_QUERY_VALUE, &hKey ); + if( lRet != ERROR_SUCCESS ) + throw new ErrorMsg( "Error when opening registry key: (" + path + ")!" ); + + /* Get value */ + lRet = RegQueryValueEx( hKey, value.c_str(), NULL, NULL, (LPBYTE) szAVRPath, &dwBufLen); + if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) ) + throw new ErrorMsg( "Error when reading key value: (" + value + ")!" ); + + /* Clean up and return result */ + RegCloseKey( hKey ); + result = szAVRPath; + return result; +} +#endif + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/Utility.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/Utility.hpp new file mode 100644 index 00000000..68520100 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/Utility.hpp @@ -0,0 +1,70 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : Utility.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A class holding misc. utility methods used in AVROSP. + * + * + ****************************************************************************/ +#ifndef UTILITY_HPP +#define UTILITY_HPP + +using namespace std; + +#ifndef NOREGISTRY +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include +#include +#include "ErrorMsg.hpp" + +class Utility +{ + protected: + bool noLog; + bool noProgress; + + public: + /* Constructor */ + Utility(); + + /* Destructor */ + ~Utility(); + + /* Methods */ + void muteLog() { noLog = true; } + void muteProgress() { noProgress = true; } + + void log( const string & txt ); + void progress( const string & txt ); + + long convertHex( const string & txt ); + string convertLong( long num, long radix = 10 ); + + void parsePath( vector & list ); + bool fileExists( string filename ); + void saveString( string txt, string filename ); + +#ifndef NOREGISTRY + string getRegistryValue( const string & path, const string & value ); +#endif +}; + +extern Utility Util; + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/XMLParser.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/XMLParser.cpp new file mode 100644 index 00000000..85ff124b --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/XMLParser.cpp @@ -0,0 +1,637 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : XMLParser.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 3419 $ + * Date : $Date: 2008-02-22 09:56:34 +0100 (fr, 22 feb 2008) $ + * Updated by : $Author: khole $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A simple XML DOM-like parser. It builds a complete tree from + * the XML file. IT supports
tags, but not tag attributes. + * + * + ****************************************************************************/ +#include "XMLParser.hpp" + +/* Private classes */ + +enum XMLNodeType +{ + xml_node, + xml_subtree +}; + +/* Abstract class. XMLTree and XMLNode is derived from this class */ +class XMLAbstractNode +{ + protected: + string name; // Name of this node. + XMLNodeType type; + + public: + /* Constructor */ + XMLAbstractNode( const string & _name, XMLNodeType _type ); + + /* Destructor */ + ~XMLAbstractNode(); + + /* Methods */ + const string & getName(); + XMLNodeType getType(); + + bool isName( const string & _name ); // Compare name to _name. + + virtual void print() = 0; +}; + + +/* Class describing a subtree, derived from XMLAbstractNode */ +class XMLTree : public XMLAbstractNode +{ + protected: + list nodes; // Nodes contained in this tree. + + public: + /* Constructor */ + XMLTree( const string & _name ); + + /* Destructor */ + ~XMLTree(); + + /* Methods */ + void addNode( XMLAbstractNode * newnode ); + bool containsNode( const string & _name ); // Searches for name in list. + XMLAbstractNode * getNode( const string & _name ); + + void print(); +}; + + +/* Class describing an ordinary string-valued node, derived from XMLAbstractNode */ +class XMLNode : public XMLAbstractNode +{ + protected: + string value; // String value. + + public: + /* Constructor */ + XMLNode( const string & _name, const string & _value ); + + /* Destructor */ + ~XMLNode(); + + /* Methods */ + bool isEmpty(); // Contains an empty string? + const string & getValue(); + + void print(); +}; + + + + +void XMLFile::removeComments( string & txt ) +{ + long pos = 0; // Everything up to this point is clean. + + long startFoundAt; // Comment start and end found at these positions. + long endFoundAt; + + /* Search and remove all comment tags */ + do + { + /* Search for comment start */ + startFoundAt = txt.find( "", startFoundAt ); + + /* Error if start but no end is found */ + if( endFoundAt == string::npos ) + throw new ErrorMsg( "Unclosed comment tag encountered! " + "Comment start-tag ''." ); + + /* Remove comment tag */ + txt.erase( startFoundAt, endFoundAt - startFoundAt + 3 ); + + pos = startFoundAt; // Prepare for next search. + + } while( pos < txt.size() ); +} + +void XMLFile::removeStartXML( string & txt ) +{ + long pos = 0; // Everything up to this point is clean. + + long startFoundAt; // Comment start and end found at these positions. + long endFoundAt; + + /* Search and remove the ", startFoundAt ); + + /* Remove tag */ + txt.erase( startFoundAt, endFoundAt - startFoundAt ); +} + + +void XMLFile::removeAttributes( string & txt ) +{ + long pos; // Everything up to this point is clean. + + long startFoundAt; // Tag start and end found at these positions. + long endFoundAt; + + long spaceFoundAt; // Space before attribute found at this position. + long slashFoundAt; // Ending slash found at this position. + + + /* Convert all whitespace to plain spaces, just to make things easier */ + for( pos = 0; pos < txt.size(); pos++ ) + { + if( txt[pos] == '\n' || txt[pos] == '\r' || txt[pos] == '\t' ) + txt.replace( pos, 1, " " ); + } + + pos = 0; + + /* Search and clean all tags */ + do + { + /* Search for tag start */ + startFoundAt = txt.find( "<", pos ); + + /* Exit loop if no tag is found */ + if( startFoundAt == string::npos ) + break; + + /* Search for comment end */ + endFoundAt = txt.find( ">", startFoundAt ); + + /* Error if start but no end is found */ + if( endFoundAt == string::npos ) + throw new ErrorMsg( "Unclosed tag encountered! " + "Tag start token '<' found, but not " + "closing '>'." ); + + /* Remove whitespace before tag name */ + while( txt[startFoundAt+1] == ' ' ) + { + txt.erase( startFoundAt+1, 1 ); // Remove. + endFoundAt--; // String has now shrunk. + } + + /* Search for space before attributes */ + spaceFoundAt = txt.find( " ", startFoundAt ); + if( spaceFoundAt < endFoundAt && spaceFoundAt != string::npos ) // Space found inside tag? + { + // If empty tag, we dont want to remove the / in /> + if ( txt.at(endFoundAt-1) == '/' ) + { + endFoundAt--; + } + + /* Remove attributes */ + txt.erase( spaceFoundAt, endFoundAt - spaceFoundAt ); + endFoundAt -= endFoundAt - spaceFoundAt; // String has now shrunk. + } + + + pos = endFoundAt + 1; // Prepare for next search. + + } while( pos < txt.size() ); +} + + +void XMLFile::readFile( const string & _filename ) +{ + ifstream f; // XML file stream. + string contents; // XML file contents. + string templine; + + /* Attempt to open file */ + f.open( _filename.c_str(), ios::in ); + if( !f ) + throw new ErrorMsg( "Error opening XML file for input!" ); + + /* Read everything into the contents string */ + contents.erase(); + templine.erase(); + do + { + contents += templine + " "; + f >> templine; // This will cause EOF only when reading from the end. + } while( !f.eof() ); + + f.close(); + + /* Remove comments and tag attributes */ + removeComments( contents ); + removeAttributes( contents ); + removeStartXML ( contents ); + + /* Create root node */ + root = new XMLTree( "root" ); + parseFragment( contents, root ); + + Util.progress( "\r\n" ); // Finish progress indicator. +} + + +void XMLFile::parseFragment( string & fragment, XMLTree * parent ) +{ + long startFoundAt; // Tag start and end found at these positions. + long endFoundAt; + + string closingString; // Search string used for finding closing tag. + long closingFoundAt; // Closing tag found at this position. + + string tagName; // These are for recently created nodes. + string tagValue; + + XMLTree * newTree; + XMLNode * newNode; + + long nestedFoundAt; // Nested tags found at this position. + + /* Find top level tags */ + Util.progress( "#" ); // Advance progress indicator. + + while( true ) // Wait for break from inside. + { + /* Find start of tag */ + startFoundAt = fragment.find( "<", 0 ); + if( startFoundAt == string::npos ) // Exit loop if no tags found. + break; + + /* Check if this is a closing tag for a higher level tag pair */ + if( fragment[startFoundAt+1] == '/' ) + break; // Exit loop. + + /* Find end of tag */ + endFoundAt = fragment.find( ">", startFoundAt ); + if( endFoundAt == string::npos ) // Error if end not found. + throw new ErrorMsg( "Unclosed tag encountered! " + "Tag start token '<' found, but no " + "closing '>'." ); + + /* Extract name of tag */ + tagName = fragment.substr( startFoundAt+1, endFoundAt-startFoundAt-1 ); + if( tagName.size() == 0 ) // Error if zero-length tag name. + throw new ErrorMsg( "Unnamed tag encountered! " + "No text between '<' and '>'." ); + + /* Remove tag from fragment */ + fragment.erase( 0, startFoundAt+tagName.size()+2 ); + + /* Check if it is an empty tag */ + if( tagName[tagName.size()-1] == '/' ) + { + /* Create a new empty ordinary node */ + tagName.erase( tagName.size()-1 ); // Remove the slash. + tagValue.erase(); // This tag has no value. + newNode = new XMLNode( tagName, tagValue ); + parent->addNode( newNode ); + } else + { + /* Find the matching closing tag for this pair */ + closingString.erase(); + closingString += ""; + closingFoundAt = fragment.find( closingString, 0 ); + if( closingFoundAt == string::npos ) // Error if not found. + throw new ErrorMsg( "Closing tag not found! " + "Opening tag '<" + tagName + ">' found, " + "but not closing '" + closingString + "'." ); + + /* Check for tags inside this tag pair, indicating a subtree */ + nestedFoundAt = fragment.find( "<", 0 ); + if( nestedFoundAt == closingFoundAt ) // No other tags inside? + { + /* Extract contents within tag pair */ + tagValue = fragment.substr( 0, closingFoundAt ); + + /* Create new ordinary node */ + newNode = new XMLNode( tagName, tagValue ); + parent->addNode( newNode ); + } else + { + /* Create new subtree and parse it's fragment */ + newTree = new XMLTree( tagName ); + parent->addNode( newTree ); + parseFragment( fragment, newTree ); + + /* Check that we can still find the closing tag */ + closingFoundAt = fragment.find( closingString, 0 ); + if( closingFoundAt == string::npos ) + throw new ErrorMsg( "Closing tag not found! " + "Opening tag '<" + tagName + ">' found, " + "but not closing '" + closingString + "'." ); + } + + /* Remove value and closing tag from fragment */ + fragment.erase( 0, closingFoundAt + closingString.size() ); + } + }; +} + + +/* Constructor */ +XMLFile::XMLFile( const string & _filename ) +{ + readFile( _filename ); +} + + +/* Destructor */ +XMLFile::~XMLFile() +{ + if( root != NULL ) + delete root; +} + + +bool XMLFile::exists( const string & path ) +{ + XMLAbstractNode * currentNode = root; + XMLTree * currentTree; + long namePos; // Position for current tag name in path. + long separatorPos; // Position for #-separator following tag name. + string tagName; // Current tag name. + + namePos = 0; + + while( true ) // This will break out from the inside. + { + /* Find separator or set pos to end of text */ + separatorPos = path.find( "\\", namePos ); + if( separatorPos == string::npos ) + separatorPos = path.size(); + + /* Extract tag name and check if it exists */ + tagName = path.substr( namePos, separatorPos-namePos ); + currentTree = (XMLTree *) currentNode; // It is indeed a tree. + if( !currentTree->containsNode( tagName ) ) + return false; // Not found. + + currentNode = currentTree->getNode( tagName ); + + /* Are there more tags in the path? */ + if( separatorPos < path.size() ) + { + /* Now, the current node better be a tree */ + if( currentNode->getType() != xml_subtree ) + { + return false; // Not found. + } else + { + namePos = separatorPos + 1; // Advance position in path. + } + } else + { + break; // Found, exit loop. + } + } + + return true; // Found! +} + + +const string & XMLFile::getValue( const string & path ) +{ + XMLAbstractNode * currentNode = root; + XMLTree * currentTree; + long namePos; // Position for current tag name in path. + long separatorPos; // Position for #-separator following tag name. + string tagName; // Current tag name. + + namePos = 0; + + while( true ) // This will break out from the inside. + { + /* Find separator or set pos to end of text */ + separatorPos = path.find( "\\", namePos ); + if( separatorPos == string::npos ) + separatorPos = path.size(); + + /* Extract tag name and check if it exists */ + tagName = path.substr( namePos, separatorPos-namePos ); + currentTree = (XMLTree *) currentNode; // It is indeed a tree. + if( !currentTree->containsNode( tagName ) ) + throw new ErrorMsg( "Node '" + tagName + "' not found!" ); + + currentNode = currentTree->getNode( tagName ); + + /* Are there more tags in the path? */ + if( separatorPos < path.size() ) + { + /* Now, the current node better be a tree */ + if( currentNode->getType() != xml_subtree ) + { + throw new ErrorMsg( "Illegal path: (" + path + ")!" ); + } else + { + namePos = separatorPos + 1; // Advance position in path. + } + } else + { + break; // Found, exit loop. + } + } + + /* Check that the current node is an ordinary node */ + if( currentNode->getType() != xml_node ) + throw new ErrorMsg( "Node '" + tagName + "' is not an element!" ); + + return ((XMLNode *) currentNode)->getValue(); +} + + +void XMLFile::print() +{ + root->print(); +} + + +/* Constructor */ +XMLAbstractNode::XMLAbstractNode( const string & _name, XMLNodeType _type ) : + name( _name ), + type( _type ) +{ + // Node code here. +} + + +/* Destructor */ +XMLAbstractNode::~XMLAbstractNode() +{ + // No code here. +} + + +const string & XMLAbstractNode::getName() +{ + return name; +} + + +XMLNodeType XMLAbstractNode::getType() +{ + return type; +} + + +bool XMLAbstractNode::isName( const string & _name ) +{ + return (name == _name); +} + + +/* Constructor */ +XMLTree::XMLTree( const string & _name ) : + XMLAbstractNode::XMLAbstractNode( _name, xml_subtree ) +{ + // No code here. +} + + +/* Destructor */ +XMLTree::~XMLTree() +{ + /* Create an iterator for the list */ + list::iterator i; + + /* Destruct all contained nodes */ + for( i = nodes.begin(); i != nodes.end(); i++ ) + { + delete (*i); + } +} + + +void XMLTree::addNode( XMLAbstractNode * newnode ) +{ + nodes.push_back( newnode ); +} + + +bool XMLTree::containsNode( const string & _name ) +{ + /* Create an iterator for the list */ + list::iterator i; + + /* Search for the node with name _name */ + i = nodes.begin(); + + while( i != nodes.end() ) + { + if( (*i)->isName( _name ) ) + return true; + + i++; + } + + return false; +} + + +XMLAbstractNode * XMLTree::getNode( const string & _name ) +{ + /* Create an iterator for the list */ + list::iterator i; + + /* Search for the node with name _name */ + i = nodes.begin(); + + while( i != nodes.end() ) + { + if( (*i)->isName( _name ) ) + return *i; + + i++; + } + + return NULL; +} + + +void XMLTree::print() +{ + /* Create an iterator for the list */ + list::iterator i; + + cout << "TREE[ Name: \"" << name << "\" ]:" << endl; + + /* Search for the node with name _name */ + i = nodes.begin(); + + while( i != nodes.end() ) + { + (*i)->print(); + + i++; + } + + cout << ":END[\"" << name << "\"]" << endl; +} + + +/* Constructor */ +XMLNode::XMLNode( const string & _name, const string & _value ) : + XMLAbstractNode::XMLAbstractNode( _name, xml_node ), + value( _value ) +{ + // No code here. +} + + +/* Destructor */ +XMLNode::~XMLNode() +{ + // Node code here. +} + + +bool XMLNode::isEmpty() +{ + return value.empty(); +} + + +const string & XMLNode::getValue() +{ + return value; +} + + +void XMLNode::print() +{ + cout << "NODE[ Name: \"" << name << "\" Value: \"" << value << "\" ]" << endl; +} + +/* end of file */ + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/XMLParser.hpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/XMLParser.hpp new file mode 100644 index 00000000..5cb2ed92 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/XMLParser.hpp @@ -0,0 +1,65 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : XMLParser.hpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 3419 $ + * Date : $Date: 2008-02-22 09:56:34 +0100 (fr, 22 feb 2008) $ + * Updated by : $Author: khole $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : A simple XML DOM-like parser. It builds a complete tree from + * the XML file. IT supports
tags, but not tag attributes. + * + * + ****************************************************************************/ +#ifndef XMLPARSER_HPP +#define XMLPARSER_HPP + +using namespace std; + +#include "ErrorMsg.hpp" +#include "Utility.hpp" +#include +#include +#include + +class XMLAbstractNode; // Preliminary definitions. +class XMLTree; +class XMLNode; + + +/* Main XML file class. Contains search methods and entire XML tree */ +class XMLFile +{ + protected: + XMLTree * root; // The root node, either a subtree or an ordinary node. + + void XMLFile::removeStartXML( string & txt ); // Remove the start xml tag. + void removeComments( string & txt ); // Remove comment tags. + void removeAttributes( string & txt ); // Remove attributes from tags. + void readFile( const string & _filename ); // Read XML file. + void parseFragment( string & fragment, XMLTree * parent ); + + public: + /* Constructors */ + XMLFile( const string & _filename ); + + /* Destructor */ + ~XMLFile(); + + /* Methods */ + bool exists( const string & path ); // Checks if node exists. + const string & getValue( const string & path ); // Get node value. + + void print(); +}; + +#endif + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/main.cpp b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/main.cpp new file mode 100644 index 00000000..561176ef --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/main.cpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * + * Atmel Corporation + * + * File : main.cpp + * Compiler : Dev-C++ 4.9.8.0 - http://bloodshed.net/dev/ + * Revision : $Revision: 1163 $ + * Date : $Date: 2006-08-02 15:38:16 +0200 (on, 02 aug 2006) $ + * Updated by : $Author: ohlia $ + * + * Support mail : avr@atmel.com + * + * Target platform : Win32 + * + * AppNote : AVR911 - AVR Open-source Programmer + * + * Description : AVROSP main entry function. + * + * + ****************************************************************************/ +#include "JobInfo.hpp" +#include +#include + +using namespace std; + + +int main(int argc, char *argv[]) +{ + JobInfo j; + + try + { + j.parseCommandline( argc, argv ); + j.doJob(); + } + catch( ErrorMsg * e ) + { + cout << endl << "An error occurred:" << endl; + cout << " [" << e->What() << "]" << endl; + + delete e; + } + + return 0; +} + diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/readme.txt b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/readme.txt new file mode 100644 index 00000000..fe938e76 --- /dev/null +++ b/bacnet-stack/ports/bdk-atxx4-mstp/avrosp/readme.txt @@ -0,0 +1,3 @@ +Made with the free Dev-C++ IDE + +http://bloodshed.net/dev/