Move some external files to external/ folder (#744)

It is lot easier to work with automatic formatters if we have external
files in different folder. For some tools we can example just exclude
external all together.

Co-authored-by: Kari Argillander <kari.argillander@fidelix.com>
This commit is contained in:
Kari Argillander
2024-08-29 00:24:48 +03:00
committed by GitHub
parent 3d3e192ae9
commit 599033b7b0
290 changed files with 419 additions and 419 deletions
+976
View File
@@ -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 <sstream>
#include <iomanip>
#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 */
+84
View File
@@ -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
+157
View File
@@ -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<string> & 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 += "<AVRPART><MEMORY><PROG_FLASH>";
cache += f.getValue( "AVRPART\\MEMORY\\PROG_FLASH" );
cache += "</PROG_FLASH><EEPROM>";
cache += f.getValue( "AVRPART\\MEMORY\\EEPROM" );
cache += "</EEPROM>";
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 += "<BOOT_CONFIG><PAGESIZE>";
cache += f.getValue( "AVRPART\\MEMORY\\BOOT_CONFIG\\PAGESIZE" );
cache += "</PAGESIZE></BOOT_CONFIG>";
}
cache += "</MEMORY>";
if( f.exists( "AVRPART\\FUSE" ) )
{
hasFuseBits = true;
cache += "<FUSE>";
if( f.exists( "AVRPART\\FUSE\\EXTENDED" ) )
{
hasExtendedFuseBits = true;
cache += "<EXTENDED></EXTENDED>";
}
cache += "</FUSE>";
}
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 += "<ADMIN><SIGNATURE><ADDR000>";
cache += f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR000" );
cache += "</ADDR000><ADDR001>";
cache += f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR001" );
cache += "</ADDR001><ADDR002>";
cache += f.getValue( "AVRPART\\ADMIN\\SIGNATURE\\ADDR002" );
cache += "</ADDR002></SIGNATURE></ADMIN></AVRPART>\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 */
+69
View File
@@ -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 <string>
#include <vector>
#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<string> & 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
+714
View File
@@ -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 <sstream>
#include <iomanip>
#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 */
@@ -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
+169
View File
@@ -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=
+70
View File
@@ -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 */
+84
View File
@@ -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
+38
View File
@@ -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 */
+61
View File
@@ -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
+46
View File
@@ -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 */
+49
View File
@@ -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 <stdlib.h>
#include <iostream>
#include <string>
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
+364
View File
@@ -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 */
+67
View File
@@ -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 <iostream>
#include <fstream>
#include <iomanip>
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
File diff suppressed because it is too large Load Diff
+105
View File
@@ -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 <iostream>
#include <vector>
#include <string>
#include <iomanip>
#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<string> searchpath; // Search path for XML-files.
public:
JobInfo(); // Constructor
void parseCommandline( int argc, char *argv[] );
void doJob();
};
#endif
+203
View File
@@ -0,0 +1,203 @@
/*****************************************************************************
*
* 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 > 99 )
throw new ErrorMsg( "Only COM1 to COM99 is supported!" );
/* Initialize internal parameters */
portNumber = _portNumber;
timeout = _timeout;
channelOpen = false;
}
/* Destructor */
SerialPort::~SerialPort()
{
closeChannel();
}
/* Open the communication channel */
void SerialPort::openChannel()
{
/* CreateFile expects a constant char, or char from the heap */
static char comName[64] = "COM1";
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 */
if (portNumber < 10) {
comName[3] = '0' + portNumber;
} else if (portNumber < 100) {
/* For COM ports greater than 9 you have to use a special syntax
for CreateFile. The syntax also works for COM ports 1-9. */
/* http://support.microsoft.com/kb/115831 */
snprintf(comName, sizeof(comName), "\\\\.\\COM%ld", 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 */
+75
View File
@@ -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 <windows.h>
#include <time.h>
#include <iostream>
#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
+181
View File
@@ -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 <iostream>
#include <fstream>
#include <stdlib.h>
/* 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<string> & 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 */
+70
View File
@@ -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 <windows.h>
#endif
#include <vector>
#include <string>
#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<string> & 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
+637
View File
@@ -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 <section/> 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<XMLAbstractNode *> 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( "<!--", pos );
/* Exit the search loop if no comment is found */
if( startFoundAt == string::npos )
{
pos = txt.size();
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 comment tag encountered! "
"Comment start-tag '<!--' found, but no "
"closing '-->'." );
/* 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 <?xml tag */
startFoundAt = txt.find( "<?xml", pos );
/* Exit the search loop if not found */
if( startFoundAt == string::npos )
{
pos = txt.size();
return;
}
/* Search for end */
endFoundAt = txt.find( ">", 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 += "</" + tagName + ">";
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<XMLAbstractNode *>::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<XMLAbstractNode *>::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<XMLAbstractNode *>::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<XMLAbstractNode *>::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 */
+65
View File
@@ -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 <section/> tags, but not tag attributes.
*
*
****************************************************************************/
#ifndef XMLPARSER_HPP
#define XMLPARSER_HPP
using namespace std;
#include "ErrorMsg.hpp"
#include "Utility.hpp"
#include <iostream>
#include <fstream>
#include <list>
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
+47
View File
@@ -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 <vector>
#include <string>
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;
}
+3
View File
@@ -0,0 +1,3 @@
Made with the free Dev-C++ IDE
http://bloodshed.net/dev/
+245
View File
@@ -0,0 +1,245 @@
# Hey Emacs, this is a -*- makefile -*-
# AVR-GCC Makefile template, derived from the WinAVR template (which
# is public domain), believed to be neutral to any flavor of "make"
# (GNU make, BSD make, SysV make)
MCU = atmega644p
FORMAT = ihex
TARGET = bootloader
SRC = main.c serial.c
ASRC =
OPT = s
BASEADDR = 0xF800
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS =
#CDEFS += -DREMOVE_FLASH_BYTE_SUPPORT
#CDEFS += -DREMOVE_EEPROM_BYTE_SUPPORT
#CDEFS += -DREMOVE_FUSE_AND_LOCK_BIT_SUPPORT
#CDEFS += -DREMOVE_AVRPROG_SUPPORT
#CDEFS += -DREMOVE_BLOCK_SUPPORT
# Place -I options here
CINCS =
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CTUNING) $(CEXTRA)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
#Additional libraries.
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
PRINTF_LIB =
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
SCANF_LIB =
MATH_LIB = -lm
# External memory options
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#LDMAP = $(LDFLAGS) -Wl,-Map=$(TARGET).map,--cref
LDFLAGS = -Ttext=$(BASEADDR) $(EXTMEMOPTS) $(LDMAP) $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
# Programming support using avrdude. Settings and variables.
# jtag2fast = Atmel JTAG ICE mkII, running at 115200 Bd
# jtag2slow = Atmel JTAG ICE mkII, running at 19200 Bd
# avrispmkII = AVR ISP MKII
#AVRDUDE_PROGRAMMER = jtag2fast
AVRDUDE_PROGRAMMER = avrispmkII
#AVRDUDE_PROGRAMMER = dragon_isp
#AVRDUDE_PROGRAMMER = dragon_jtag
#
# # port--serial or parallel port to which your
# # hardware programmer is attached
# # usb can just be usb
# # /dev/ttya
AVRDUDE_PORT = usb
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
# Disable auto-erase so that the chip can be initially
# programmed with application code, with the bootloader code added second
AVRDUDE_AUTOERASE = -D
AVRDUDE_BASIC = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS = $(AVRDUDE_BASIC)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
AVRDUDE_FLAGS += $(AVRDUDE_AUTOERASE)
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: elf hex eep
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# Program the device.
install: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
$(COFFCONVERT) -O coff-avr $(TARGET).elf $(TARGET).cof
extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $(TARGET).elf $(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Link: create ELF output file from object files.
$(TARGET).elf: $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Target: clean project.
clean:
$(REMOVE) $(TARGET).hex $(TARGET).eep $(TARGET).cof $(TARGET).elf \
$(TARGET).map $(TARGET).sym $(TARGET).lss \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d)
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend
@@ -0,0 +1 @@
<AVRStudio><MANAGEMENT><ProjectName>bootloader</ProjectName><Created>27-May-2009 06:28:56</Created><LastEdit>27-May-2009 06:28:56</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>27-May-2009 06:28:56</Created><Version>4</Version><Build>4, 15, 0, 623</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile></ObjectFile><EntryFile></EntryFile><SaveFolder>D:\code\bacnet-stack\ports\bdk-atxx4-mstp\bootloader\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>JTAGICE mkII</CURRENT_TARGET><CURRENT_PART>ATmega644P.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES/><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>atmega128</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>bootloader.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>0</ISDIRTY><OPTIONS/><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG></AVRGCCPLUGIN><IOView><usergroups/><sort sorted="0" column="0" ordername="1" orderaddress="1" ordergroup="1"/></IOView><Files></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>
+58
View File
@@ -0,0 +1,58 @@
/* definitions generated by preprocessor, copy into defines.h */
#ifndef PPINC
#define _ATMEGA644P /* device select: _ATMEGAxxxx */
#define _B2048 /* boot size select: _Bxxxx (words), powers of two only */
#ifdef __ICCAVR__
#include "iom644.h"
#endif
#if __GNUC__
#include <avr/io.h>
#if (__GNUC__ <= 4) && (__GNUC_MINOR__ < 3)
#if !defined(EEWE) && defined(EEPE)
#define EEWE EEPE
#endif
#if !defined(EEMWE) && defined(EEMPE)
#define EEMWE EEMPE
#endif
#endif
#endif
/* define pin for enter-self-prog-mode */
#define PROGPORT PORTB
#define PROGPIN PINB
#define PROG_NO PB0
/* baud rate register value calculation */
#define CPU_FREQ 18430000
#define BAUD_RATE 115200
#define BRREG_VALUE 9
/* definitions for UART control */
#define BAUD_RATE_LOW_REG UBRR1
#define UART_CONTROL_REG UCSR1B
#define ENABLE_TRANSMITTER_BIT TXEN1
#define ENABLE_RECEIVER_BIT RXEN1
#define UART_STATUS_REG UCSR1A
#define TRANSMIT_COMPLETE_BIT TXC1
#define RECEIVE_COMPLETE_BIT RXC1
#define UART_DATA_REG UDR1
/* definitions for SPM control */
#define SPMCR_REG SPMCSR
#define PAGESIZE 256
#define APP_END 61440
/*#define LARGE_MEMORY */
/* definitions for device recognition */
#define PARTCODE 0
#define SIGNATURE_BYTE_1 0x1E
#define SIGNATURE_BYTE_2 0x96
#define SIGNATURE_BYTE_3 0x0A
/* indicate that preprocessor result is included */
#define PPINC
#endif
+74
View File
@@ -0,0 +1,74 @@
/*****************************************************************************
*
* Atmel Corporation
*
* File : flash.h
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
* Revision : $Revision: 1.7 $
* Date : $Date: Tuesday, June 07, 200 $
* Updated by : $Author: raapeland $
*
* Support mail : avr@atmel.com
*
* Target platform : All AVRs with bootloader support
*
* AppNote : AVR109 - Self-programming
*
* Description : Flash operations for AVR109 Self-programming
****************************************************************************/
#if defined(__ICCAVR__)
/* IAR Embedded Workbench */
#include <inavr.h>
#define _GET_LOCK_BITS() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0001, 0x09 )
#define _GET_LOW_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0000, 0x09 )
#define _GET_HIGH_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0003, 0x09 )
#define _GET_EXTENDED_FUSES() __AddrToZByteToSPMCR_LPM( (void __flash *) 0x0002, 0x09 )
#define _SET_LOCK_BITS(data) __DataToR0ByteToSPMCR_SPM( data, 0x09 )
#define _ENABLE_RWW_SECTION() __DataToR0ByteToSPMCR_SPM( 0x00, 0x11 )
#define _WAIT_FOR_SPM() while( SPMCR_REG & (1<<SPMEN) );
#ifndef LARGE_MEMORY
#define _LOAD_PROGRAM_MEMORY(addr) __load_program_memory( (const unsigned char __flash *) (addr) )
#define _FILL_TEMP_WORD(addr,data) __AddrToZWordToR1R0ByteToSPMCR_SPM( (void __flash *) (addr), data, 0x01 )
#define _PAGE_ERASE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x03 )
#define _PAGE_WRITE(addr) __AddrToZByteToSPMCR_SPM( (void __flash *) (addr), 0x05 )
#else /* LARGE_MEMORY */
#define _LOAD_PROGRAM_MEMORY(addr) __extended_load_program_memory( (const unsigned char __farflash *) (addr) )
#define _FILL_TEMP_WORD(addr,data) __AddrToZ24WordToR1R0ByteToSPMCR_SPM( (void __farflash *) (addr), data, 0x01 )
#define _PAGE_ERASE(addr) __AddrToZ24ByteToSPMCR_SPM( (void __farflash *) (addr), 0x03 )
#define _PAGE_WRITE(addr) __AddrToZ24ByteToSPMCR_SPM( (void __farflash *) (addr), 0x05 )
#endif /* LARGE_MEMORY */
#elif __GNUC__ > 0
/* AVR-GCC/avr-libc */
#include <avr/boot.h>
#include <avr/pgmspace.h>
#if defined(GET_LOCK_BITS) /* avr-libc >= 1.2.5 */
#define _GET_LOCK_BITS() boot_lock_fuse_bits_get(GET_LOCK_BITS)
#define _GET_LOW_FUSES() boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS)
#define _GET_HIGH_FUSES() boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)
#define _GET_EXTENDED_FUSES() boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)
#endif /* defined(GET_LOCK_BITS) */
#define _SET_LOCK_BITS(data) boot_lock_bits_set(~data)
#define _ENABLE_RWW_SECTION() boot_rww_enable()
#define _WAIT_FOR_SPM() boot_spm_busy_wait()
#ifndef LARGE_MEMORY
#define _LOAD_PROGRAM_MEMORY(addr) pgm_read_byte_near(addr)
#else /* LARGE_MEMORY */
#define _LOAD_PROGRAM_MEMORY(addr) pgm_read_byte_far(addr)
#endif /* LARGE_MEMORY */
#define _FILL_TEMP_WORD(addr,data) boot_page_fill(addr, data)
#define _PAGE_ERASE(addr) boot_page_erase(addr)
#define _PAGE_WRITE(addr) boot_page_write(addr)
#else
#error "Don't know your compiler."
#endif
+450
View File
@@ -0,0 +1,450 @@
/*****************************************************************************
*
* Atmel Corporation
*
* File : main.c
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
* Revision : $Revision: 1.7 $
* Date : $Date: Tuesday, June 07, 200 $
* Updated by : $Author: raapeland $
*
* Support mail : avr@atmel.com
*
* Target platform : All AVRs with bootloader support
*
* AppNote : AVR109 - Self-programming
*
* Description : This Program allows an AVR with bootloader capabilities to
* Read/write its own Flash/EEprom. To enter Programming mode
* an input pin is checked. If this pin is pulled low,
*programming mode is entered. If not, normal execution is done from $0000
* "reset" vector in Application area.
*
* Preparations : Use the preprocessor.xls file for obtaining a customized
* defines.h file and linker-file code-segment definition for
* the device you are compiling for.
****************************************************************************/
#include "defines.h"
#include "serial.h"
#include "flash.h"
/* Uncomment the following to save code space */
/*#define REMOVE_AVRPROG_SUPPORT */
/*#define REMOVE_FUSE_AND_LOCK_BIT_SUPPORT */
/*#define REMOVE_BLOCK_SUPPORT */
/*#define REMOVE_EEPROM_BYTE_SUPPORT */
/*#define REMOVE_FLASH_BYTE_SUPPORT */
/*
* GCC doesn't optimize long int arithmetics very clever. As the
* address only needs to be larger than 16 bits for the ATmega128 and
* above (where flash consumptions isn't much of an issue as the
* entire boot loader will still fit even into the smallest possible
* boot loader section), save space by using a 16-bit variable for the
* smaller devices.
*/
#ifdef LARGE_MEMORY
#define ADDR_T unsigned long
#else /* !LARGE_MEMORY */
#define ADDR_T unsigned int
#endif /* LARGE_MEMORY */
#ifndef REMOVE_BLOCK_SUPPORT
unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address);
void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address);
/* BLOCKSIZE should be chosen so that the following holds: BLOCKSIZE*n =
* PAGESIZE, where n=1,2,3... */
#define BLOCKSIZE PAGESIZE
#endif /* REMOVE_BLOCK_SUPPORT */
#ifdef __ICCAVR__
__C_task void main(void)
#else /* ! __ICCAVR__ */
int main(void)
#endif /* __ICCAVR__ */
{
ADDR_T address;
unsigned int temp_int;
unsigned char val;
/* Initialization */
void (*funcptr)(void) =
0x0000; /* Set up function pointer to RESET vector. */
PROGPORT |=
(1 << PROG_NO); /* Enable pull-up on PROG_NO line on PROGPORT. */
initbootuart(); /* Initialize UART. */
/* Branch to bootloader or application code? */
if (!(PROGPIN & (1 << PROG_NO))) { /* If PROGPIN is pulled low, enter
programmingmode. */
/* Main loop */
for (;;) {
val = recchar(); /* Wait for command character. */
/* Check autoincrement status. */
if (val == 'a') {
sendchar('Y'); /* Yes, we do autoincrement. */
}
/* Set address. */
else if (val == 'A') {
/* Set address... */ /* NOTE: Flash addresses are given in
words, not bytes. */
address = (recchar() << 8) |
recchar(); /* Read address high and low byte. */
sendchar('\r'); /* Send OK back. */
}
/* Chip erase. */
else if (val == 'e') {
for (address = 0; address < APP_END; address +=
PAGESIZE) { /* NOTE: Here we use address as a byte-address,
not word-address, for convenience. */
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
_PAGE_ERASE(address);
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
}
sendchar('\r'); /* Send OK back. */
}
#ifndef REMOVE_BLOCK_SUPPORT
/* Check block load support. */
else if (val == 'b') {
sendchar('Y'); /* Report block load supported. */
sendchar((BLOCKSIZE >> 8) & 0xFF); /* MSB first. */
sendchar(BLOCKSIZE & 0xFF); /* Report BLOCKSIZE (bytes). */
}
/* Start block load. */
else if (val == 'B') {
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
val = recchar(); /* Get memtype. */
sendchar(BlockLoad(temp_int, val, &address)); /* Block load. */
}
/* Start block read. */
else if (val == 'g') {
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
val = recchar(); /* Get memtype */
BlockRead(temp_int, val, &address); /* Block read */
}
#endif /* REMOVE_BLOCK_SUPPORT */
#ifndef REMOVE_FLASH_BYTE_SUPPORT
/* Read program memory. */
else if (val == 'R') {
/* Send high byte, then low byte of flash word. */
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
sendchar(_LOAD_PROGRAM_MEMORY((address << 1) + 1));
sendchar(_LOAD_PROGRAM_MEMORY((address << 1) + 0));
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
address++; /* Auto-advance to next Flash word. */
}
/* Write program memory, low byte. */
else if (val == 'c') { /* NOTE: Always use this command before
sending high byte. */
temp_int =
recchar(); /* Get low byte for later _FILL_TEMP_WORD. */
sendchar('\r'); /* Send OK back. */
}
/* Write program memory, high byte. */
else if (val == 'C') {
temp_int |= (recchar() << 8); /* Get and insert high byte. */
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
_FILL_TEMP_WORD(
(address << 1), temp_int); /* Convert word-address to
byte-address and fill. */
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
address++; /* Auto-advance to next Flash word. */
sendchar('\r'); /* Send OK back. */
}
/* Write page. */
else if (val == 'm') {
if (address >= (APP_END >> 1)) { /* Protect bootloader area. */
sendchar('?');
} else {
_WAIT_FOR_SPM();
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
_PAGE_WRITE(address << 1); /* Convert word-address to
byte-address and write. */
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
}
sendchar('\r'); /* Send OK back. */
}
#endif /* REMOVE_FLASH_BYTE_SUPPORT */
#ifndef REMOVE_EEPROM_BYTE_SUPPORT
/* Write EEPROM memory. */
else if (val == 'D') {
_WAIT_FOR_SPM();
EEARL = address; /* Setup EEPROM address. */
EEARH = (address >> 8);
EEDR = recchar(); /* Get byte. */
EECR |= (1 << EEMWE); /* Write byte. */
EECR |= (1 << EEWE);
while (EECR &
(1 << EEWE)) /* Wait for write operation to finish. */
;
address++; /* Auto-advance to next EEPROM byte. */
sendchar('\r'); /* Send OK back. */
}
/* Read EEPROM memory. */
else if (val == 'd') {
EEARL = address; /* Setup EEPROM address. */
EEARH = (address >> 8);
EECR |= (1 << EERE); /* Read byte... */
sendchar(EEDR); /* ...and send it back. */
address++; /* Auto-advance to next EEPROM byte. */
}
#endif /* REMOVE_EEPROM_BYTE_SUPPORT */
#ifndef REMOVE_FUSE_AND_LOCK_BIT_SUPPORT
/* Write lockbits. */
else if (val == 'l') {
_WAIT_FOR_SPM();
_SET_LOCK_BITS(recchar()); /* Read and set lock bits. */
sendchar('\r'); /* Send OK back. */
}
#if defined(_GET_LOCK_BITS)
/* Read lock bits. */
else if (val == 'r') {
_WAIT_FOR_SPM();
sendchar(_GET_LOCK_BITS());
}
/* Read fuse bits. */
else if (val == 'F') {
_WAIT_FOR_SPM();
sendchar(_GET_LOW_FUSES());
}
/* Read high fuse bits. */
else if (val == 'N') {
_WAIT_FOR_SPM();
sendchar(_GET_HIGH_FUSES());
}
/* Read extended fuse bits. */
else if (val == 'Q') {
_WAIT_FOR_SPM();
sendchar(_GET_EXTENDED_FUSES());
}
#endif /* defined(_GET_LOCK_BITS) */
#endif /* REMOVE_FUSE_AND_LOCK_BIT_SUPPORT */
#ifndef REMOVE_AVRPROG_SUPPORT
/* Enter and leave programming mode. */
else if ((val == 'P') || (val == 'L')) {
sendchar('\r'); /* Nothing special to do, just answer OK. */
}
/* Exit bootloader. */
else if (val == 'E') {
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
sendchar('\r');
funcptr(); /* Jump to Reset vector 0x0000 in Application
Section. */
}
/* Get programmer type. */
else if (val == 'p') {
sendchar('S'); /* Answer 'SERIAL'. */
}
/* Return supported device codes. */
else if (val == 't') {
#if PARTCODE + 0 > 0
sendchar(PARTCODE); /* Supports only this device, of course. */
#endif /* PARTCODE */
sendchar(0); /* Send list terminator. */
}
/* Set LED, clear LED and set device type. */
else if ((val == 'x') || (val == 'y') || (val == 'T')) {
recchar(); /* Ignore the command and it's parameter. */
sendchar('\r'); /* Send OK back. */
}
#endif /* REMOVE_AVRPROG_SUPPORT */
/* Return programmer identifier. */
else if (val == 'S') {
sendchar('A'); /* Return 'AVRBOOT'. */
sendchar('V'); /* Software identifier (aka programmer signature)
is always 7 characters. */
sendchar('R');
sendchar('B');
sendchar('O');
sendchar('O');
sendchar('T');
}
/* Return software version. */
else if (val == 'V') {
sendchar('1');
sendchar('5');
}
/* Return signature bytes. */
else if (val == 's') {
sendchar(SIGNATURE_BYTE_3);
sendchar(SIGNATURE_BYTE_2);
sendchar(SIGNATURE_BYTE_1);
}
/* The last command to accept is ESC (synchronization). */
else if (val != 0x1b) { /* If not ESC, then it is unrecognized... */
sendchar('?');
}
} /* end: for(;;) */
} else {
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
funcptr(); /* Jump to Reset vector 0x0000 in Application Section. */
}
} /* end: main */
#ifndef REMOVE_BLOCK_SUPPORT
unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address)
{
unsigned char buffer[BLOCKSIZE];
unsigned int data;
ADDR_T tempaddress;
/* EEPROM memory type. */
if (mem == 'E') {
/* Fill buffer first, as EEPROM is too slow to copy with UART speed */
for (tempaddress = 0; tempaddress < size; tempaddress++)
buffer[tempaddress] = recchar();
/* Then program the EEPROM */
_WAIT_FOR_SPM();
for (tempaddress = 0; tempaddress < size; tempaddress++) {
EEARL = *address; /* Setup EEPROM address */
EEARH = ((*address) >> 8);
EEDR = buffer[tempaddress]; /* Get byte. */
EECR |= (1 << EEMWE); /* Write byte. */
EECR |= (1 << EEWE);
while (EECR & (1 << EEWE)) /* Wait for write operation to finish. */
;
(*address)++; /* Select next EEPROM byte */
}
return '\r'; /* Report programming OK */
}
/* Flash memory type. */
else if (mem ==
'F') { /* NOTE: For flash programming, 'address' is given in words. */
(*address) <<= 1; /* Convert address to bytes temporarily. */
tempaddress = (*address); /* Store address in page. */
do {
data = recchar();
data |= (recchar() << 8);
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
_FILL_TEMP_WORD(*address, data);
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
(*address) += 2; /* Select next word in memory. */
size -= 2; /* Reduce number of bytes to write by two. */
} while (size); /* Loop until all bytes written. */
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
_PAGE_WRITE(tempaddress);
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
(*address) >>= 1; /* Convert address back to Flash words again. */
return '\r'; /* Report programming OK */
}
/* Invalid memory type? */
else {
return '?';
}
}
void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address)
{
/* EEPROM memory type. */
if (mem == 'E') { /* Read EEPROM */
do {
EEARL = *address; /* Setup EEPROM address */
EEARH = ((*address) >> 8);
(*address)++; /* Select next EEPROM byte */
EECR |= (1 << EERE); /* Read EEPROM */
sendchar(EEDR); /* Transmit EEPROM dat ato PC */
size--; /* Decrease number of bytes to read */
} while (size); /* Repeat until all block has been read */
}
/* Flash memory type. */
else if (mem == 'F') {
(*address) <<= 1; /* Convert address to bytes temporarily. */
do {
#ifdef __ICCAVR__
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
long-type address to flash ptr. */
#endif
sendchar(_LOAD_PROGRAM_MEMORY(*address));
sendchar(_LOAD_PROGRAM_MEMORY((*address) + 1));
#ifdef __ICCAVR__
#pragma diag_default = Pe1053 /* Back to default. */
#endif
(*address) += 2; /* Select next word in memory. */
size -= 2; /* Subtract two bytes from number of bytes to read */
} while (size); /* Repeat until all block has been read */
(*address) >>= 1; /* Convert address back to Flash words again. */
}
}
#endif /* REMOVE_BLOCK_SUPPORT */
/* end of file */
+24
View File
@@ -0,0 +1,24 @@
#Extracted from "Part definitions" of preprocessor.xls
#dev include pagesz nrwwpag totpag avr910 sig1 sig2 sig3 baudlo uartc uarts txen rxen txc rxc udr spmcr
ATmega8 iom8.h 32 32 128 0x77 0x1E 0x93 0x07 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega8515 iom8515.h 32 32 128 0x3B 0x1E 0x93 0x06 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega8535 iom8535.h 32 32 128 0x6A 0x1E 0x93 0x08 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega88 iom88.h 32 32 128 0x1E 0x93 0x0A UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega16 iom16.h 64 16 128 0x75 0x1E 0x94 0x03 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega162 iom162.h 64 16 128 0x63 0x1E 0x94 0x04 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCR
ATmega163 iom163.h 64 16 128 0x66 0x1E 0x94 0x02 UBRRLO UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega165 iom165.h 64 16 128 0x1E 0x94 0x07 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega168 iom168.h 64 16 128 0x1E 0x94 0x06 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega169 iom169.h 64 16 128 0x79 0x1E 0x94 0x05 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega32 iom32.h 64 32 256 0x7F 0x1E 0x95 0x02 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega323 iom323.h 64 16 256 0x73 0x1E 0x95 0x01 UBRRL UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCR
ATmega329 iom329.h 64 32 256 0x1E 0x95 0x03 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega3290 iom3290.h 64 32 256 0x1E 0x95 0x04 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega64 iom64.h 128 32 256 0x46 0x1E 0x96 0x02 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCR
ATmega644 iom644.h 128 32 256 0x1E 0x96 0x09 UBRR0 UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega644P iom644.h 128 32 256 0x1E 0x96 0x0A UBRR1 UCSR1B UCSR1A TXEN1 RXEN1 TXC1 RXC1 UDR1 SPMCSR
ATmega649 iom649.h 128 32 256 0x1E 0x96 0x03 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega6490 iom6490.h 128 32 256 0x1E 0x96 0x04 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega128 iom128.h 128 32 512 0x44 0x1E 0x97 0x02 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega128_1 iom128.h 128 32 512 0x44 0x1E 0x97 0x02 UBRR1L UCSR1B UCSR1A TXEN1 RXEN1 TXC1 RXC1 UDR1 SPMCSR
+171
View File
@@ -0,0 +1,171 @@
#! /bin/sh
# Equivalent script to what preprocessor.xls might do.
#
# Run e.g. like
# sh preprocessor.sh ATmega128 4096 PORTD PD4 3686400 9600 > defines.h
#
# Written by Joerg Wunsch, 2005-07-29
PARTFILE=parts.txt
usage()
{
echo "usage: preprocessor.sh device bootsize progport prog_no cpu_freq baud_rate" >& 2
exit 1
}
if [ $# -ne 6 ]
then
usage
fi
if [ ! -f ${PARTFILE} ]
then
echo "part definition file ${PARTFILE} not found" >& 2
exit 1
fi
device="$1"
bootsize="$2"
progport="$3"
prog_no="$4"
cpu_freq="$5"
baud_rate="$6"
# is there a device at all?
if grep -i "^${device} " ${PARTFILE} >/dev/null
then
:
else
echo "device ${device} not found in ${PARTFILE}" >& 2
exit 1
fi
devupper=`echo $device | tr '[a-z]' '[A-Z]'`
# find an awk to use, out of nawk, gawk, or awk
AWK=none
for name in nawk gawk awk
do
set -- `type $name 2>/dev/null`
if [ "x$2" = 'xis' ]
then
AWK=$name
break
fi
done
if [ $AWK = 'none' ]
then
echo "Sorry, no useable awk found" >& 2
exit 1
fi
# OK, now get the individual fields. Unfortunately, the AVR910 device ID
# is optional, and the shell cannot parse that natively. Use awk to
# re-order the fields, and sort the avr910 column last (so we'll get an
# empty variable in read if it is not present).
set -- `grep -i "^${device} " ${PARTFILE} |\
${AWK} -F ' ' \
'{print $1 " " $2 " " $3 " " $4 " " $5 " " $7 " " $8 " " $9 " " $10 " " $11 " " $12 " " $13 " " $14 " " $15 " " $16 " " $17 " " $18 " " $6; exit}'`
dev=$1
include=$2
pagesz=$3
nrwwpag=$4
totpag=$5
sig1=$6
sig2=$7
sig3=$8
baudlo=$9
shift 9
uartc=$1
uarts=$2
txen=$3
rxen=$4
txc=$5
rxc=$6
udr=$7
spmcr=$8
avr910=$9
# Verify boot size
pagebytes=`expr $pagesz \* 2`
maxboot=`expr $nrwwpag \* $pagebytes`
bootbytes=`expr 2 \* $bootsize` || exit 1
if [ \( $bootbytes -ne $maxboot \) -a \
\( $bootbytes -ne `expr $maxboot / 4` \) -a \
\( $bootbytes -ne `expr $maxboot / 2` \) -a \
\( $bootbytes -ne `expr $maxboot \* 3 / 4` \) ]
then
echo "Invalid boot size ${bootsize}, valid: `expr $maxboot / 8`, `expr $maxboot / 4`, `expr $maxboot \* 3 / 8`, `expr $maxboot / 2` words" >& 2
exit 1
fi
if p=`expr $progport : 'PORT\(.\)'`
then
: # ok
else
echo "Invalid port name ${progport}, must be PORTx" >& 2
exit 1
fi
progpin="PIN$p"
brreg=`expr $cpu_freq / \( 16 \* $baud_rate \) - 1` || exit 1
memsize=`expr $totpag \* $pagebytes`
append=`expr $memsize - $bootbytes`
echo "/* definitions generated by preprocessor, copy into defines.h */
#ifndef PPINC
#define _${devupper} // device select: _ATMEGAxxxx
#define _B${bootsize} // boot size select: _Bxxxx (words), powers of two only
#ifdef __ICCAVR__
#include \"${include}\"
#endif
#if __GNUC__
#include <avr/io.h>
#endif
/* define pin for enter-self-prog-mode */
#define PROGPORT ${progport}
#define PROGPIN ${progpin}
#define PROG_NO ${prog_no}
/* baud rate register value calculation */
#define CPU_FREQ ${cpu_freq}
#define BAUD_RATE ${baud_rate}
#define BRREG_VALUE ${brreg}
/* definitions for UART control */
#define BAUD_RATE_LOW_REG ${baudlo}
#define UART_CONTROL_REG ${uartc}
#define ENABLE_TRANSMITTER_BIT ${txen}
#define ENABLE_RECEIVER_BIT ${rxen}
#define UART_STATUS_REG ${uarts}
#define TRANSMIT_COMPLETE_BIT ${txc}
#define RECEIVE_COMPLETE_BIT ${rxc}
#define UART_DATA_REG ${udr}
/* definitions for SPM control */
#define SPMCR_REG ${spmcr}
#define PAGESIZE ${pagebytes}
#define APP_END ${append}"
if [ $memsize -gt 65536 ]
then
echo "#define LARGE_MEMORY"
else
echo "//#define LARGE_MEMORY"
fi
echo "
/* definitions for device recognition */
#define PARTCODE ${avr910}
#define SIGNATURE_BYTE_1 ${sig1}
#define SIGNATURE_BYTE_2 ${sig2}
#define SIGNATURE_BYTE_3 ${sig3}
/* indicate that preprocessor result is included */
#define PPINC
#endif"
echo "(IAR) Replace all code segment definitions in the linker file with the following line:" >& 2
${AWK} 'BEGIN {printf "-Z(CODE)INTVEC,FAR_F,SWITCH,CODE=%X-%X\n", '$append', '$memsize' - 1; exit}' >& 2
Binary file not shown.
+41
View File
@@ -0,0 +1,41 @@
/*****************************************************************************
*
* Atmel Corporation
*
* File : serial.c
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
* Revision : $Revision: 1.7 $
* Date : $Date: Tuesday, June 07, 200 $
* Updated by : $Author: raapeland $
*
* Support mail : avr@atmel.com
*
* Target platform : All AVRs with bootloader support
*
* AppNote : AVR109 - Self-programming
*
* Description : UART communication routines
****************************************************************************/
#include "defines.h"
void initbootuart(void)
{
BAUD_RATE_LOW_REG = BRREG_VALUE;
UART_CONTROL_REG = (1 << ENABLE_RECEIVER_BIT) |
(1 << ENABLE_TRANSMITTER_BIT); /* enable receive and transmit */
}
void sendchar(unsigned char c)
{
UART_DATA_REG = c; /* prepare transmission */
while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT)))
; /* wait until byte sendt */
UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT); /* delete TXCflag */
}
unsigned char recchar(void)
{
while (!(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT)))
; /* wait for data */
return UART_DATA_REG;
}
+25
View File
@@ -0,0 +1,25 @@
/*****************************************************************************
*
* Atmel Corporation
*
* File : serial.h
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
* Revision : $Revision: 1.7 $
* Date : $Date: Tuesday, June 07, 200 $
* Updated by : $Author: raapeland $
*
* Support mail : avr@atmel.com
*
* Target platform : All AVRs with bootloader support
*
* AppNote : AVR109 - Self-programming
*
* Description : Header file for serial.c
****************************************************************************/
void initbootuart(
void);
void sendchar(
unsigned char);
unsigned char recchar(
void);
+20
View File
@@ -0,0 +1,20 @@
#ifndef STDBOOL_H
#define STDBOOL_H
/* C99 Boolean types for compilers without C99 support */
#ifndef __cplusplus
typedef char _Bool;
#ifndef bool
#define bool _Bool
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define __bool_true_false_are_defined 1
#endif
#endif