MBED AVR ISP programmer. Targeted for ATMEGA1284p but should work for other AVR chips as well. Inspired by AVR_SPI_Programmer_v2 and AVR910.
Revision 0:064004c069be, committed 2012-01-05
- Comitter:
- qiangbo
- Date:
- Thu Jan 05 02:44:12 2012 +0000
- Commit message:
- Initial version
Changed in this revision
diff -r 000000000000 -r 064004c069be AVRISP/AVRISP.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AVRISP/AVRISP.cpp Thu Jan 05 02:44:12 2012 +0000 @@ -0,0 +1,311 @@ +#include "AVRISP.h" + +// constructor +AVRISP::AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset) +{ + spiPort = new SPI(mosi,miso,sclk); + spiPort->frequency(TARGET_CLK>>2); + spiPort->format(8,1); + resetPin = new DigitalOut(reset); +} + +//A function to poll BSY to prevent loading a new instruction prematurely +void AVRISP::StillProgramming() +{ + int check = 1; + while(check == 1) + { + 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 1 +int AVRISP::ReadChipSignatureByte1() +{ + // read byte 1 + spiPort->write(0x30); + spiPort->write(0x00); + spiPort->write(0x00); + int signatureByte1 = spiPort->write(0x00); + StillProgramming(); + + return signatureByte1; +} + +// read chip signature byte 2 +int AVRISP::ReadChipSignatureByte2() +{ + // read byte 1 + spiPort->write(0x30); + spiPort->write(0x00); + spiPort->write(0x01); + int signatureByte2 = spiPort->write(0x00); + StillProgramming(); + + return signatureByte2; +} + +// read chip signature byte 3 +int AVRISP::ReadChipSignatureByte3() +{ + // read byte 1 + spiPort->write(0x30); + spiPort->write(0x00); + spiPort->write(0x02); + int signatureByte3 = spiPort->write(0x00); + StillProgramming(); + + return signatureByte3; +} + +// 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 low +void AVRISP::WriteFuseLow(uint8_t fuseLow) +{ + fuseLow = fuseLow&0xFF; + spiPort->write(0xAC); + spiPort->write(0xA0); + spiPort->write(0x00); + spiPort->write(fuseLow); + StillProgramming(); +} + +// read fuse byte low +int AVRISP::ReadFuseLow() +{ + spiPort->write(0x50); + spiPort->write(0x00); + spiPort->write(0x00); + int readBack = spiPort->write(0x00); + StillProgramming(); + + return readBack; +} + +// write fuse byte high +void AVRISP::WriteFuseHigh(uint8_t fuseHigh) +{ + fuseHigh = fuseHigh&0xFF; + spiPort->write(0xAC); + spiPort->write(0xA8); + spiPort->write(0x00); + spiPort->write(fuseHigh); + StillProgramming(); +} + +// read fuse byte high +int AVRISP::ReadFuseHigh() +{ + spiPort->write(0x58); + spiPort->write(0x08); + spiPort->write(0x00); + int readBack = spiPort->write(0x00); + StillProgramming(); + + return readBack; +} + +// write fuse byte extended +void AVRISP::WriteFuseExtended(uint8_t fuseExtended) +{ + fuseExtended = fuseExtended&0xFF; + spiPort->write(0xAC); + spiPort->write(0xA4); + spiPort->write(0x00); + spiPort->write(fuseExtended); + StillProgramming(); +} + +// read fuse byte extended +int AVRISP::ReadFuseExtended() +{ + spiPort->write(0x50); + spiPort->write(0x08); + spiPort->write(0x00); + int readBack = spiPort->write(0x00); + StillProgramming(); + + return readBack; +} + +// write lock byte +void AVRISP::WriteLockByte(uint8_t lockByte) +{ + lockByte = lockByte&0xFF; + spiPort->write(0xAC); + spiPort->write(0xE0); + spiPort->write(0x00); + spiPort->write(lockByte); + StillProgramming(); +} + +// read lock byte +int AVRISP::ReadLockByte() +{ + spiPort->write(0x58); + spiPort->write(0x00); + spiPort->write(0x00); + int readBack = spiPort->write(0x00); + StillProgramming(); + + return readBack; +} + +// 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); + + // write page if 32 words have now been written + if(addr % MAX_PAGE_SIZE == (MAX_PAGE_SIZE-1)) + { + WriteProgramPage(addr); + } +} + +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)); +} + +void AVRISP::ReadProgramFlash(uint8_t addrMSB, uint8_t addrLSB) +{ + spiPort->write(0x28); + spiPort->write(addrMSB); + spiPort->write(addrLSB); + spiPort->write(0x00); + spiPort->write(0x20); + spiPort->write(addrMSB); + spiPort->write(addrLSB); +} + +// program flash +bool AVRISP::ProgramFlash(char *hexFileName) +{ + int flag = 0; + FILE *hexFile; + hexFile = fopen(hexFileName,"r"); + 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); + + address++; + } + while((temp = fgetc(hexFile)) != ':'); + } + } + else flag = 1; + } + WriteProgramPage(address); + fclose(hexFile); + } + else + { + return false; + } + + return true; +} +
diff -r 000000000000 -r 064004c069be AVRISP/AVRISP.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AVRISP/AVRISP.h Thu Jan 05 02:44:12 2012 +0000 @@ -0,0 +1,66 @@ +//****************************************************************************/ +// Description: +// +// Program AVR chips with the AVR910 ISP (in-system programming) protocol, +// using an mbed. +// +// This is a wrapper for AVR_ISP_Programmer_v2 +// +//****************************************************************************/ + +#ifndef AVRISP_H +#define AVRISP_H + +//****************************************************************************/ +// Includes +//****************************************************************************/ +#include "mbed.h" + +//****************************************************************************/ +// Definations for: ATMEGA1284p +//****************************************************************************/ +#define SIGNATURE_BYTE_1 0x1E +#define SIGNATURE_BYTE_2 0x97 +#define SIGNATURE_BYTE_3 0x05 +#define PAGE_SIZE 128 +#define NUM_PAGE 512 + +//****************************************************************************/ +// Definations for programming +//****************************************************************************/ +#define LSB(I) ((I) & 0xFF) +#define MSB(I) (((I) & 0xF00) >> 8) +#define TARGET_CLK 1000000L +#define MAX_PAGE_SIZE (PAGE_SIZE >> 1) //divide max page size by 2 to get number of words per page + +class AVRISP +{ + public: + AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset); + bool EnableProgrammingMode(); + void LeaveProgrammingMode(); + int ReadChipSignatureByte1(); + int ReadChipSignatureByte2(); + int ReadChipSignatureByte3(); + void StillProgramming(); + void ChipErase(); + void WriteFuseLow(uint8_t fuseLow); + int ReadFuseLow(); + void WriteFuseHigh(uint8_t fuseHigh); + int ReadFuseHigh(); + void WriteFuseExtended(uint8_t fuseExtended); + int ReadFuseExtended(); + void WriteLockByte(uint8_t lockByte); + int ReadLockByte(); + void WriteProgramPage(uint16_t addr); + void LoadProgramPage(uint16_t addr,uint8_t lowData,uint8_t highData); + uint8_t ReadByte(FILE *file); + void ReadProgramFlash(uint8_t addrMSB, uint8_t addrLSB); + bool ProgramFlash(char *hexFileName); + + private: + SPI* spiPort; + DigitalOut *resetPin; +}; + +#endif
diff -r 000000000000 -r 064004c069be main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Jan 05 02:44:12 2012 +0000 @@ -0,0 +1,65 @@ +#include "mbed.h" +#include "AVRISP.h" + +#define FUSE_LOW 0xD0 +#define FUSE_HIGH 0xD9 +#define FUSE_EXTENDED 0xFF +#define LOCK_BYTE 0xFF + +LocalFileSystem local("local"); +AVRISP avrisp(p11,p12,p13,p14); +Serial pc(USBTX, USBRX); + +int main() +{ + bool ifSuccessful; + + pc.printf("Press any button to program the AVR.\n"); + char c = pc.getc(); + + ifSuccessful = avrisp.EnableProgrammingMode(); + if(ifSuccessful) + { + pc.printf("Enter Programming Mode: Successful.\n"); + } + else + { + pc.printf("Enter Programming Mode: Failed.\n"); + } + + int signatureByte1 = avrisp.ReadChipSignatureByte1(); + int signatureByte2 = avrisp.ReadChipSignatureByte2(); + int signatureByte3 = avrisp.ReadChipSignatureByte3(); + pc.printf("Chip signature is %x %x %x\n",signatureByte1,signatureByte2,signatureByte3); + + pc.printf("Erase Chip.\n"); + avrisp.ChipErase(); + + pc.printf("Write Fuse Low Byte.\n"); + avrisp.WriteFuseLow(FUSE_LOW); + pc.printf("Fuse Low Byte Readback = %x.\n",avrisp.ReadFuseLow()); + + pc.printf("Write Fuse High Byte.\n"); + avrisp.WriteFuseLow(FUSE_HIGH); + pc.printf("Fuse High Byte Readback = %x.\n",avrisp.ReadFuseHigh()); + + pc.printf("Write Fuse Extended Byte.\n"); + avrisp.WriteFuseLow(FUSE_EXTENDED); + pc.printf("Fuse Extended Byte Readback = %x.\n",avrisp.ReadFuseExtended()); + + pc.printf("Write Lock Byte.\n"); + avrisp.WriteLockByte(LOCK_BYTE); + pc.printf("Lock Byte Readback = %x.\n",avrisp.ReadLockByte()); + + ifSuccessful = avrisp.ProgramFlash("/local/avr1"); + if(ifSuccessful) + { + pc.printf("Program Flash: Successful.\n"); + } + else + { + pc.printf("Program Flash: Failed.\n"); + } + + avrisp.LeaveProgrammingMode(); +}
diff -r 000000000000 -r 064004c069be mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Jan 05 02:44:12 2012 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/078e4b97a13e