
AVRisp tested on ATMega88A inspired by various implementations around: - AVR_SPI_Programmer_v2 ( BO Qiang ) - mAVRISP (Aaron Berk) - TestAVRISP(Chester Hamilton)
AVRisp implementation for mBED
AVRISP/AVRISP.cpp
- Committer:
- Ellips
- Date:
- 2015-04-28
- Revision:
- 0:29abe3c0b902
File content as of revision 0:29abe3c0b902:
#include "AVRISP.h" // constructor AVRISP::AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset, uint32_t targetClk, uint16_t pageSize, PRGCB pCB ) : spiPort(mosi, miso, sclk ) , resetPin(reset) , mPageSize(pageSize) , progressCB(pCB) { spiPort.frequency(targetClk>>2);//1/4 th of the clock frequency of the unit spiPort.format(8,0); } AVRISP::~AVRISP() { } //A function to poll BSY to prevent loading a new instruction prematurely void AVRISP::StillProgramming() { uint8_t check = 1; while(check & 0x1){//check LSB only spiPort.write(0xF0); spiPort.write(0x00); spiPort.write(0x00); check = spiPort.write(0x00); //read data byte out } } // enable programming mode bool AVRISP::EnableProgrammingMode() { int failed = 0; resetPin = 1; wait(0.02); resetPin = 0; wait(0.02); while(failed < 5) //loop to try to enable programming mode 5 times { spiPort.write(0xAC); spiPort.write(0x53); int echoBack= spiPort.write(0x00); if(echoBack == 0x53) { //if data read on 3rd byte load is 0x53 spiPort.write(0x00); //programming mode was enabled...good job! return true; } else { failed++; resetPin = 1; //pulse reset and try again resetPin = 0; wait(0.5); } } return false; //Bummer... } void AVRISP::LeaveProgrammingMode() { resetPin = 1; wait(0.02); } // read chip signature byte uint8_t AVRISP::ReadChipSignatureByte(SignatureByte Nr) { spiPort.write(0x30); spiPort.write(0x00); spiPort.write(Nr); return spiPort.write(0x00); } // erase chip void AVRISP::ChipErase() { spiPort.write(0xAC); spiPort.write(0x80); spiPort.write(0x00); spiPort.write(0x00); StillProgramming(); resetPin = 1; wait(0.02); resetPin = 0; wait(0.02); EnableProgrammingMode(); } // write fuse byte void AVRISP::WriteFuse(FuseType Typ, uint8_t fuse) { spiPort.write(0xAC); switch ( Typ ){ case eFTLo: spiPort.write(0xA0); break; case eFTHi: spiPort.write(0xA8); break; case eFTEx: spiPort.write(0xA4); break; case eFTLock: spiPort.write(0xE0); break; default: spiPort.write(0x00); break; }; spiPort.write(0x00); spiPort.write(fuse&0xff); StillProgramming(); } // read fuse byte uint8_t AVRISP::ReadFuse(FuseType Typ) { switch (Typ){ case eFTLo: spiPort.write(0x50); spiPort.write(0x00); break; case eFTHi: spiPort.write(0x58); spiPort.write(0x08); break; case eFTEx: spiPort.write(0x50); spiPort.write(0x08); break; case eFTLock: spiPort.write(0x58); spiPort.write(0x00); break; default: spiPort.write(0x00); spiPort.write(0x00); break; } spiPort.write(0x00); return spiPort.write(0x00); } #define LSB(I) ((I) & 0xFF) #define MSB(I) (((I) & 0xF00) >> 8) // write program page void AVRISP::WriteProgramPage(uint16_t addr) { //write program memory page spiPort.write(0x4C); spiPort.write(MSB(addr)); spiPort.write(LSB(addr)); spiPort.write(0x00); StillProgramming(); //make sure the operation worked } //function to load and write program memory //args: addr is the 12 bit address of the memory location // low_data and high_data are the values to write to that location void AVRISP::LoadProgramPage(uint16_t addr,uint8_t lowData,uint8_t highData)//int addr_MSB, { //load program memory low byte (little endian) spiPort.write(0x40); spiPort.write(0x00); spiPort.write(LSB(addr)); spiPort.write(lowData); //load program memory high byte spiPort.write(0x48); spiPort.write(0x00); spiPort.write(LSB(addr)); spiPort.write(highData); } inline uint8_t AVRISP::ReadByte(FILE *file) { char ascii_char[2]; fread(&ascii_char, 1, 2, file); return (((ascii_char[0] < 65) ? (ascii_char[0]-48) : (ascii_char[0]-55)) << 4) | ((ascii_char[1] < 65) ? (ascii_char[1]-48) : (ascii_char[1]-55)); } uint8_t AVRISP::ReadProgramFlash(uint16_t addr, bool highByte) { spiPort.write(highByte ? 0x28: 0x20 ); spiPort.write(MSB(addr)); spiPort.write(LSB(addr)); return spiPort.write(0x00); } #define AT_BOUNDARY(addr,size) ((addr % size) == (size -1)) // program flash //TODO: Implement address gaps in the hex file format bool AVRISP::ProgramFlash(FILE *hexFile) { int flag = 0; if(hexFile != NULL) { uint16_t address = 0; char temp; temp = fgetc(hexFile); while(flag == 0) { if(temp == ':') { uint8_t length = ReadByte(hexFile); if(length == 0) { flag = 1; } else { fseek(hexFile,6,SEEK_CUR); //2 if reading address for(uint8_t i=0;i<length;i+=2) { uint8_t lowData = ReadByte(hexFile); uint8_t highData = ReadByte(hexFile); //load data bytes here LoadProgramPage(address,lowData,highData); if (AT_BOUNDARY(address, mPageSize)) // write page if 32 words have now been written { WriteProgramPage(address); if( progressCB ) (*progressCB)(); //activity callback } address++; } while((temp = fgetc(hexFile)) != ':'); } } else flag = 1; } WriteProgramPage(address);//write the last part } else { return false; } return true; } //TODO: Implement address gaps in the hex file format bool AVRISP::VerifyFlash(FILE* hexFile) { int flag = 0; bool Error = false; if(hexFile != NULL) { uint16_t address = 0; char temp; temp = fgetc(hexFile); while(flag == 0) { if(temp == ':') { uint8_t length = ReadByte(hexFile); if(length == 0) { flag = 1; } else { fseek(hexFile,6,SEEK_CUR); //2 if reading address for(uint8_t i=0;i<length;i+=2) { uint8_t lowData = ReadByte(hexFile); uint8_t highData = ReadByte(hexFile); uint8_t lowDataF = ReadProgramFlash(address, false); uint8_t highDataF = ReadProgramFlash(address, true); if( lowData != lowDataF || highData != highDataF ) { printf( "\n@%04x src %02x,%02x != %02x,%02x\n", address, lowData, highData, lowDataF,highDataF); Error = true; } if (AT_BOUNDARY(address, mPageSize)) { if( progressCB ) (*progressCB)(); //activity callback } address++; } while((temp = fgetc(hexFile)) != ':'); } } else flag = 1; } if(Error) return false; } else { return false; } return true; }