AVRisp tested on ATMega88A inspired by various implementations around: - AVR_SPI_Programmer_v2 ( BO Qiang ) - mAVRISP (Aaron Berk) - TestAVRISP(Chester Hamilton)

Dependencies:   mbed

AVRisp implementation for mBED

Committer:
Ellips
Date:
Tue Apr 28 11:01:19 2015 +0000
Revision:
1:4b883042df7d
Parent:
0:29abe3c0b902
AVRisp , v0.1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Ellips 0:29abe3c0b902 1 #include "AVRISP.h"
Ellips 0:29abe3c0b902 2
Ellips 0:29abe3c0b902 3 // constructor
Ellips 0:29abe3c0b902 4 AVRISP::AVRISP(PinName mosi, PinName miso, PinName sclk, PinName reset, uint32_t targetClk, uint16_t pageSize, PRGCB pCB )
Ellips 0:29abe3c0b902 5 : spiPort(mosi, miso, sclk )
Ellips 0:29abe3c0b902 6 , resetPin(reset)
Ellips 0:29abe3c0b902 7 , mPageSize(pageSize)
Ellips 0:29abe3c0b902 8 , progressCB(pCB)
Ellips 0:29abe3c0b902 9 {
Ellips 0:29abe3c0b902 10 spiPort.frequency(targetClk>>2);//1/4 th of the clock frequency of the unit
Ellips 0:29abe3c0b902 11 spiPort.format(8,0);
Ellips 0:29abe3c0b902 12 }
Ellips 0:29abe3c0b902 13
Ellips 0:29abe3c0b902 14 AVRISP::~AVRISP()
Ellips 0:29abe3c0b902 15 {
Ellips 0:29abe3c0b902 16 }
Ellips 0:29abe3c0b902 17
Ellips 0:29abe3c0b902 18 //A function to poll BSY to prevent loading a new instruction prematurely
Ellips 0:29abe3c0b902 19 void AVRISP::StillProgramming()
Ellips 0:29abe3c0b902 20 {
Ellips 0:29abe3c0b902 21 uint8_t check = 1;
Ellips 0:29abe3c0b902 22 while(check & 0x1){//check LSB only
Ellips 0:29abe3c0b902 23 spiPort.write(0xF0);
Ellips 0:29abe3c0b902 24 spiPort.write(0x00);
Ellips 0:29abe3c0b902 25 spiPort.write(0x00);
Ellips 0:29abe3c0b902 26 check = spiPort.write(0x00); //read data byte out
Ellips 0:29abe3c0b902 27 }
Ellips 0:29abe3c0b902 28 }
Ellips 0:29abe3c0b902 29
Ellips 0:29abe3c0b902 30 // enable programming mode
Ellips 0:29abe3c0b902 31 bool AVRISP::EnableProgrammingMode()
Ellips 0:29abe3c0b902 32 {
Ellips 0:29abe3c0b902 33 int failed = 0;
Ellips 0:29abe3c0b902 34
Ellips 0:29abe3c0b902 35 resetPin = 1;
Ellips 0:29abe3c0b902 36 wait(0.02);
Ellips 0:29abe3c0b902 37 resetPin = 0;
Ellips 0:29abe3c0b902 38 wait(0.02);
Ellips 0:29abe3c0b902 39
Ellips 0:29abe3c0b902 40 while(failed < 5) //loop to try to enable programming mode 5 times
Ellips 0:29abe3c0b902 41 {
Ellips 0:29abe3c0b902 42 spiPort.write(0xAC);
Ellips 0:29abe3c0b902 43 spiPort.write(0x53);
Ellips 0:29abe3c0b902 44 int echoBack= spiPort.write(0x00);
Ellips 0:29abe3c0b902 45 if(echoBack == 0x53)
Ellips 0:29abe3c0b902 46 { //if data read on 3rd byte load is 0x53
Ellips 0:29abe3c0b902 47 spiPort.write(0x00); //programming mode was enabled...good job!
Ellips 0:29abe3c0b902 48 return true;
Ellips 0:29abe3c0b902 49 }
Ellips 0:29abe3c0b902 50 else
Ellips 0:29abe3c0b902 51 {
Ellips 0:29abe3c0b902 52 failed++;
Ellips 0:29abe3c0b902 53 resetPin = 1; //pulse reset and try again
Ellips 0:29abe3c0b902 54 resetPin = 0;
Ellips 0:29abe3c0b902 55 wait(0.5);
Ellips 0:29abe3c0b902 56 }
Ellips 0:29abe3c0b902 57 }
Ellips 0:29abe3c0b902 58 return false; //Bummer...
Ellips 0:29abe3c0b902 59 }
Ellips 0:29abe3c0b902 60
Ellips 0:29abe3c0b902 61 void AVRISP::LeaveProgrammingMode()
Ellips 0:29abe3c0b902 62 {
Ellips 0:29abe3c0b902 63 resetPin = 1;
Ellips 0:29abe3c0b902 64 wait(0.02);
Ellips 0:29abe3c0b902 65 }
Ellips 0:29abe3c0b902 66
Ellips 0:29abe3c0b902 67 // read chip signature byte
Ellips 0:29abe3c0b902 68 uint8_t AVRISP::ReadChipSignatureByte(SignatureByte Nr)
Ellips 0:29abe3c0b902 69 {
Ellips 0:29abe3c0b902 70 spiPort.write(0x30);
Ellips 0:29abe3c0b902 71 spiPort.write(0x00);
Ellips 0:29abe3c0b902 72 spiPort.write(Nr);
Ellips 0:29abe3c0b902 73 return spiPort.write(0x00);
Ellips 0:29abe3c0b902 74 }
Ellips 0:29abe3c0b902 75
Ellips 0:29abe3c0b902 76 // erase chip
Ellips 0:29abe3c0b902 77 void AVRISP::ChipErase()
Ellips 0:29abe3c0b902 78 {
Ellips 0:29abe3c0b902 79 spiPort.write(0xAC);
Ellips 0:29abe3c0b902 80 spiPort.write(0x80);
Ellips 0:29abe3c0b902 81 spiPort.write(0x00);
Ellips 0:29abe3c0b902 82 spiPort.write(0x00);
Ellips 0:29abe3c0b902 83 StillProgramming();
Ellips 0:29abe3c0b902 84 resetPin = 1;
Ellips 0:29abe3c0b902 85 wait(0.02);
Ellips 0:29abe3c0b902 86 resetPin = 0;
Ellips 0:29abe3c0b902 87 wait(0.02);
Ellips 0:29abe3c0b902 88 EnableProgrammingMode();
Ellips 0:29abe3c0b902 89 }
Ellips 0:29abe3c0b902 90
Ellips 0:29abe3c0b902 91 // write fuse byte
Ellips 0:29abe3c0b902 92 void AVRISP::WriteFuse(FuseType Typ, uint8_t fuse)
Ellips 0:29abe3c0b902 93 {
Ellips 0:29abe3c0b902 94 spiPort.write(0xAC);
Ellips 0:29abe3c0b902 95 switch ( Typ ){
Ellips 0:29abe3c0b902 96 case eFTLo:
Ellips 0:29abe3c0b902 97 spiPort.write(0xA0); break;
Ellips 0:29abe3c0b902 98 case eFTHi:
Ellips 0:29abe3c0b902 99 spiPort.write(0xA8); break;
Ellips 0:29abe3c0b902 100 case eFTEx:
Ellips 0:29abe3c0b902 101 spiPort.write(0xA4); break;
Ellips 0:29abe3c0b902 102 case eFTLock:
Ellips 0:29abe3c0b902 103 spiPort.write(0xE0); break;
Ellips 0:29abe3c0b902 104 default:
Ellips 0:29abe3c0b902 105 spiPort.write(0x00); break;
Ellips 0:29abe3c0b902 106 };
Ellips 0:29abe3c0b902 107 spiPort.write(0x00);
Ellips 0:29abe3c0b902 108 spiPort.write(fuse&0xff);
Ellips 0:29abe3c0b902 109 StillProgramming();
Ellips 0:29abe3c0b902 110 }
Ellips 0:29abe3c0b902 111
Ellips 0:29abe3c0b902 112 // read fuse byte
Ellips 0:29abe3c0b902 113 uint8_t AVRISP::ReadFuse(FuseType Typ)
Ellips 0:29abe3c0b902 114 {
Ellips 0:29abe3c0b902 115 switch (Typ){
Ellips 0:29abe3c0b902 116 case eFTLo:
Ellips 0:29abe3c0b902 117 spiPort.write(0x50);
Ellips 0:29abe3c0b902 118 spiPort.write(0x00);
Ellips 0:29abe3c0b902 119 break;
Ellips 0:29abe3c0b902 120 case eFTHi:
Ellips 0:29abe3c0b902 121 spiPort.write(0x58);
Ellips 0:29abe3c0b902 122 spiPort.write(0x08);
Ellips 0:29abe3c0b902 123 break;
Ellips 0:29abe3c0b902 124 case eFTEx:
Ellips 0:29abe3c0b902 125 spiPort.write(0x50);
Ellips 0:29abe3c0b902 126 spiPort.write(0x08);
Ellips 0:29abe3c0b902 127 break;
Ellips 0:29abe3c0b902 128 case eFTLock:
Ellips 0:29abe3c0b902 129 spiPort.write(0x58);
Ellips 0:29abe3c0b902 130 spiPort.write(0x00);
Ellips 0:29abe3c0b902 131 break;
Ellips 0:29abe3c0b902 132 default:
Ellips 0:29abe3c0b902 133 spiPort.write(0x00);
Ellips 0:29abe3c0b902 134 spiPort.write(0x00);
Ellips 0:29abe3c0b902 135 break;
Ellips 0:29abe3c0b902 136 }
Ellips 0:29abe3c0b902 137 spiPort.write(0x00);
Ellips 0:29abe3c0b902 138 return spiPort.write(0x00);
Ellips 0:29abe3c0b902 139 }
Ellips 0:29abe3c0b902 140 #define LSB(I) ((I) & 0xFF)
Ellips 0:29abe3c0b902 141 #define MSB(I) (((I) & 0xF00) >> 8)
Ellips 0:29abe3c0b902 142 // write program page
Ellips 0:29abe3c0b902 143 void AVRISP::WriteProgramPage(uint16_t addr)
Ellips 0:29abe3c0b902 144 {
Ellips 0:29abe3c0b902 145 //write program memory page
Ellips 0:29abe3c0b902 146 spiPort.write(0x4C);
Ellips 0:29abe3c0b902 147 spiPort.write(MSB(addr));
Ellips 0:29abe3c0b902 148 spiPort.write(LSB(addr));
Ellips 0:29abe3c0b902 149 spiPort.write(0x00);
Ellips 0:29abe3c0b902 150
Ellips 0:29abe3c0b902 151 StillProgramming(); //make sure the operation worked
Ellips 0:29abe3c0b902 152 }
Ellips 0:29abe3c0b902 153
Ellips 0:29abe3c0b902 154
Ellips 0:29abe3c0b902 155 //function to load and write program memory
Ellips 0:29abe3c0b902 156 //args: addr is the 12 bit address of the memory location
Ellips 0:29abe3c0b902 157 // low_data and high_data are the values to write to that location
Ellips 0:29abe3c0b902 158 void AVRISP::LoadProgramPage(uint16_t addr,uint8_t lowData,uint8_t highData)//int addr_MSB,
Ellips 0:29abe3c0b902 159 {
Ellips 0:29abe3c0b902 160 //load program memory low byte (little endian)
Ellips 0:29abe3c0b902 161 spiPort.write(0x40);
Ellips 0:29abe3c0b902 162 spiPort.write(0x00);
Ellips 0:29abe3c0b902 163 spiPort.write(LSB(addr));
Ellips 0:29abe3c0b902 164 spiPort.write(lowData);
Ellips 0:29abe3c0b902 165
Ellips 0:29abe3c0b902 166 //load program memory high byte
Ellips 0:29abe3c0b902 167 spiPort.write(0x48);
Ellips 0:29abe3c0b902 168 spiPort.write(0x00);
Ellips 0:29abe3c0b902 169 spiPort.write(LSB(addr));
Ellips 0:29abe3c0b902 170 spiPort.write(highData);
Ellips 0:29abe3c0b902 171 }
Ellips 0:29abe3c0b902 172
Ellips 0:29abe3c0b902 173 inline uint8_t AVRISP::ReadByte(FILE *file)
Ellips 0:29abe3c0b902 174 {
Ellips 0:29abe3c0b902 175 char ascii_char[2];
Ellips 0:29abe3c0b902 176 fread(&ascii_char, 1, 2, file);
Ellips 0:29abe3c0b902 177 return (((ascii_char[0] < 65) ? (ascii_char[0]-48) : (ascii_char[0]-55)) << 4)
Ellips 0:29abe3c0b902 178 | ((ascii_char[1] < 65) ? (ascii_char[1]-48) : (ascii_char[1]-55));
Ellips 0:29abe3c0b902 179 }
Ellips 0:29abe3c0b902 180
Ellips 0:29abe3c0b902 181 uint8_t AVRISP::ReadProgramFlash(uint16_t addr, bool highByte)
Ellips 0:29abe3c0b902 182 {
Ellips 0:29abe3c0b902 183 spiPort.write(highByte ? 0x28: 0x20 );
Ellips 0:29abe3c0b902 184 spiPort.write(MSB(addr));
Ellips 0:29abe3c0b902 185 spiPort.write(LSB(addr));
Ellips 0:29abe3c0b902 186 return spiPort.write(0x00);
Ellips 0:29abe3c0b902 187 }
Ellips 0:29abe3c0b902 188 #define AT_BOUNDARY(addr,size) ((addr % size) == (size -1))
Ellips 0:29abe3c0b902 189 // program flash
Ellips 0:29abe3c0b902 190
Ellips 0:29abe3c0b902 191 //TODO: Implement address gaps in the hex file format
Ellips 0:29abe3c0b902 192 bool AVRISP::ProgramFlash(FILE *hexFile)
Ellips 0:29abe3c0b902 193 {
Ellips 0:29abe3c0b902 194 int flag = 0;
Ellips 0:29abe3c0b902 195 if(hexFile != NULL)
Ellips 0:29abe3c0b902 196 {
Ellips 0:29abe3c0b902 197 uint16_t address = 0;
Ellips 0:29abe3c0b902 198 char temp;
Ellips 0:29abe3c0b902 199 temp = fgetc(hexFile);
Ellips 0:29abe3c0b902 200 while(flag == 0)
Ellips 0:29abe3c0b902 201 {
Ellips 0:29abe3c0b902 202 if(temp == ':')
Ellips 0:29abe3c0b902 203 {
Ellips 0:29abe3c0b902 204 uint8_t length = ReadByte(hexFile);
Ellips 0:29abe3c0b902 205 if(length == 0)
Ellips 0:29abe3c0b902 206 {
Ellips 0:29abe3c0b902 207 flag = 1;
Ellips 0:29abe3c0b902 208 }
Ellips 0:29abe3c0b902 209 else
Ellips 0:29abe3c0b902 210 {
Ellips 0:29abe3c0b902 211 fseek(hexFile,6,SEEK_CUR); //2 if reading address
Ellips 0:29abe3c0b902 212
Ellips 0:29abe3c0b902 213 for(uint8_t i=0;i<length;i+=2)
Ellips 0:29abe3c0b902 214 {
Ellips 0:29abe3c0b902 215 uint8_t lowData = ReadByte(hexFile);
Ellips 0:29abe3c0b902 216 uint8_t highData = ReadByte(hexFile);
Ellips 0:29abe3c0b902 217
Ellips 0:29abe3c0b902 218 //load data bytes here
Ellips 0:29abe3c0b902 219 LoadProgramPage(address,lowData,highData);
Ellips 0:29abe3c0b902 220
Ellips 0:29abe3c0b902 221 if (AT_BOUNDARY(address, mPageSize)) // write page if 32 words have now been written
Ellips 0:29abe3c0b902 222 {
Ellips 0:29abe3c0b902 223 WriteProgramPage(address);
Ellips 0:29abe3c0b902 224 if( progressCB ) (*progressCB)(); //activity callback
Ellips 0:29abe3c0b902 225 }
Ellips 0:29abe3c0b902 226
Ellips 0:29abe3c0b902 227 address++;
Ellips 0:29abe3c0b902 228 }
Ellips 0:29abe3c0b902 229 while((temp = fgetc(hexFile)) != ':');
Ellips 0:29abe3c0b902 230 }
Ellips 0:29abe3c0b902 231 }
Ellips 0:29abe3c0b902 232 else flag = 1;
Ellips 0:29abe3c0b902 233 }
Ellips 0:29abe3c0b902 234 WriteProgramPage(address);//write the last part
Ellips 0:29abe3c0b902 235 }
Ellips 0:29abe3c0b902 236 else
Ellips 0:29abe3c0b902 237 {
Ellips 0:29abe3c0b902 238 return false;
Ellips 0:29abe3c0b902 239 }
Ellips 0:29abe3c0b902 240 return true;
Ellips 0:29abe3c0b902 241 }
Ellips 0:29abe3c0b902 242
Ellips 0:29abe3c0b902 243 //TODO: Implement address gaps in the hex file format
Ellips 0:29abe3c0b902 244 bool AVRISP::VerifyFlash(FILE* hexFile)
Ellips 0:29abe3c0b902 245 {
Ellips 0:29abe3c0b902 246 int flag = 0;
Ellips 0:29abe3c0b902 247 bool Error = false;
Ellips 0:29abe3c0b902 248 if(hexFile != NULL)
Ellips 0:29abe3c0b902 249 {
Ellips 0:29abe3c0b902 250 uint16_t address = 0;
Ellips 0:29abe3c0b902 251 char temp;
Ellips 0:29abe3c0b902 252 temp = fgetc(hexFile);
Ellips 0:29abe3c0b902 253 while(flag == 0)
Ellips 0:29abe3c0b902 254 {
Ellips 0:29abe3c0b902 255 if(temp == ':')
Ellips 0:29abe3c0b902 256 {
Ellips 0:29abe3c0b902 257 uint8_t length = ReadByte(hexFile);
Ellips 0:29abe3c0b902 258 if(length == 0)
Ellips 0:29abe3c0b902 259 {
Ellips 0:29abe3c0b902 260 flag = 1;
Ellips 0:29abe3c0b902 261 }
Ellips 0:29abe3c0b902 262 else
Ellips 0:29abe3c0b902 263 {
Ellips 0:29abe3c0b902 264 fseek(hexFile,6,SEEK_CUR); //2 if reading address
Ellips 0:29abe3c0b902 265
Ellips 0:29abe3c0b902 266 for(uint8_t i=0;i<length;i+=2)
Ellips 0:29abe3c0b902 267 {
Ellips 0:29abe3c0b902 268 uint8_t lowData = ReadByte(hexFile);
Ellips 0:29abe3c0b902 269 uint8_t highData = ReadByte(hexFile);
Ellips 0:29abe3c0b902 270 uint8_t lowDataF = ReadProgramFlash(address, false);
Ellips 0:29abe3c0b902 271 uint8_t highDataF = ReadProgramFlash(address, true);
Ellips 0:29abe3c0b902 272
Ellips 0:29abe3c0b902 273 if( lowData != lowDataF || highData != highDataF )
Ellips 0:29abe3c0b902 274 {
Ellips 0:29abe3c0b902 275 printf( "\n@%04x src %02x,%02x != %02x,%02x\n", address, lowData, highData, lowDataF,highDataF);
Ellips 0:29abe3c0b902 276 Error = true;
Ellips 0:29abe3c0b902 277 }
Ellips 0:29abe3c0b902 278
Ellips 0:29abe3c0b902 279 if (AT_BOUNDARY(address, mPageSize))
Ellips 0:29abe3c0b902 280 {
Ellips 0:29abe3c0b902 281 if( progressCB ) (*progressCB)(); //activity callback
Ellips 0:29abe3c0b902 282 }
Ellips 0:29abe3c0b902 283 address++;
Ellips 0:29abe3c0b902 284 }
Ellips 0:29abe3c0b902 285 while((temp = fgetc(hexFile)) != ':');
Ellips 0:29abe3c0b902 286 }
Ellips 0:29abe3c0b902 287 }
Ellips 0:29abe3c0b902 288 else flag = 1;
Ellips 0:29abe3c0b902 289 }
Ellips 0:29abe3c0b902 290 if(Error)
Ellips 0:29abe3c0b902 291 return false;
Ellips 0:29abe3c0b902 292 }
Ellips 0:29abe3c0b902 293 else
Ellips 0:29abe3c0b902 294 {
Ellips 0:29abe3c0b902 295 return false;
Ellips 0:29abe3c0b902 296 }
Ellips 0:29abe3c0b902 297
Ellips 0:29abe3c0b902 298 return true;
Ellips 0:29abe3c0b902 299 }