📄 avratmel.c
字号:
/* AvrAtmel.C Device driver for the Serial Atmel Low Cost Programmer Uros Platise (c) 1999*/#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include "AvrAtmel.h"#define AUTO_SELECT 0/* Low Cost Atmel Programmer AVR Codes Valid for software version: SW_MAJOR=2 SW_MINOR=0 Code 0xff is reserved for invalid code. Update the TAvrAtmel constructor if Atmel comes up with it.*/TAvrAtmel::SPrgPart TAvrAtmel::prg_part [] = { /* 0x10, 0x11 = AT90S1200 rev. A, B (very old) */ {"S1200C", 0x12, "AT90S1200 Revision C", false}, /* old */ {"S1200D", 0x13, "AT90S1200 Revision D", false}, {"S2313A", 0x20, "AT90S2313 Revision A", false}, {"S2323A", 0x48, "AT90S2323 Revision A", false}, {"S4414A", 0x28, "AT90S4414 Revision A", false}, {"S8515A", 0x38, "AT90S8515 Revision A", false}, {"S8252", 0x86, "AT89S8252", false}, {"S01838C",0x40, "ATmega103 Revision C", false}, /* old */ {"S01838D",0x41, "ATmega103 Revision D", false},#if 1 /* more device codes, mostly reverse-engineered from avrprog.exe that comes with AVR Studio (but where is the updated avr910.asm ??? version 2.0 updated 1998-01-06 only handles the above devices). XXX - ATtiny22 is missing from avrprog.exe (should work as a 2343). */ {"S4433", 0x30, "AT90S4433", false}, {"S2333", 0x34, "AT90S2333", false}, /* 0x38 = AT90S8515 */ /* 0x40 = ATmega103 rev. C (old) */ /* 0x41 = ATmega103 */ {"M603", 0x42, "ATmega603", false}, /* 0x48 = AT90S2323 */ {"S2343", 0x4C, "AT90S2343", false}, /* ATtiny22 ??? */ {"TN11", 0x50, "ATtiny11", false}, /* parallel */ {"TN10", 0x51, "ATtiny10", false}, /* parallel */ {"TN12", 0x55, "ATtiny12", false}, {"TN15", 0x56, "ATtiny15", false}, {"TN19", 0x58, "ATtiny19", false}, /* parallel ??? */ {"TN28", 0x5C, "ATtiny28", false}, /* parallel */ {"M161", 0x60, "ATmega161", false}, {"M163", 0x64, "ATmega163", false}, {"M83", 0x65, "ATmega83", false}, {"AVR109", 0x66, "AVR109", false}, /* self programming, AVR109 app note */ {"S8535", 0x68, "AT90S8535", false}, {"S4434", 0x6C, "AT90S4434", false}, {"C8534", 0x70, "AT90C8534", false}, /* parallel */ {"M323", 0x72, "ATmega323", false}, {"89C2051",0x81, "AT89C2051", false}, /* parallel */ {"89C51", 0x82, "AT89C51", false}, /* parallel */ {"89LV51", 0x83, "AT89LV51", false}, /* parallel */ {"89C52", 0x84, "AT89C52", false}, /* parallel */ {"89LV52", 0x85, "AT89LV52", false}, /* parallel */ /* 0x86 = AT89S8252 */ {"89S53", 0x87, "AT89S53", false}, /* 0x88..0xDF reserved for AT89, 0xE0..0xFF reserved */#endif {"auto", AUTO_SELECT, "Auto detect", false}, {"", 0x00, "", false}};/* Private Functions*/void TAvrAtmel::EnterProgrammingMode(){ /* Select Device Type */ TByte set_device[2] = {'T', desired_avrcode}; Send(set_device, 2, 1); CheckResponse(set_device[0]); /* Enter Programming Mode */ TByte enter_prg[1] = {'P'}; Send(enter_prg, 1); CheckResponse(enter_prg[0]); /* Read Signature Bytes */ TByte sig_bytes[3] = {'s', 0, 0}; Send(sig_bytes, 1, 3); part_number = sig_bytes[0]; part_family = sig_bytes[1]; vendor_code = sig_bytes[2];}void TAvrAtmel::LeaveProgrammingMode(){ TByte leave_prg [1] = { 'L' }; Send(leave_prg, 1); }void TAvrAtmel::CheckResponse(TByte x){ if (x!=13){throw Error_Device ("Device is not responding correctly.");}}void TAvrAtmel::EnableAvr(){ bool auto_select = desired_avrcode == AUTO_SELECT; for (unsigned pidx=0; prg_part[pidx].code != AUTO_SELECT; pidx++){ if (!prg_part[pidx].supported && auto_select){continue;} if (auto_select){ desired_avrcode = prg_part[pidx].code; Info(2, "Trying with: %s\n", prg_part[pidx].description); } EnterProgrammingMode(); if (!auto_select || !(vendor_code==0 && part_family==1 && part_number==2)){ break; } LeaveProgrammingMode(); } // OverridePart("atmega163"); // XXXXX local hack for broken signature bytes Identify(); if (auto_select){ /* If avr was recongnized by the Identify(), try to find better match in the support list. */ unsigned better_pidx = 0; TByte better_avrcode = desired_avrcode; for (unsigned pidx=0; prg_part[pidx].code != AUTO_SELECT; pidx++){ if (!prg_part[pidx].supported){continue;} if (strstr(prg_part[pidx].description, GetPartName())){ better_avrcode = prg_part[better_pidx = pidx].code; } } if (better_avrcode != desired_avrcode){ Info(2, "Retrying with better match: %s\n", prg_part[better_pidx].description); desired_avrcode = better_avrcode; LeaveProgrammingMode(); EnterProgrammingMode(); Identify(); } }}void TAvrAtmel::SetAddress(TAddr addr){ apc_address = addr; TByte setAddr [3] = { 'A', (addr>>8)&0xff, addr&0xff}; Send(setAddr, 3, 1); CheckResponse(setAddr [0]);}void TAvrAtmel::WriteProgramMemoryPage(){ SetAddress(page_addr >> 1); TByte prg_page [1] = { 'm' }; Send(prg_page, 1); }/* Device Interface Functions*/TByte TAvrAtmel::ReadByte(TAddr addr){ CheckMemoryRange(addr); if (segment==SEG_FLASH){ TAddr saddr = addr>>1; TByte rdF [2] = { 'R', 0 }; if (buf_addr==addr && cache_lowbyte==true){return buf_lowbyte;} if (apc_address!=saddr || apc_autoinc==false) SetAddress(saddr); apc_address++; Send(rdF, 1, 2); /* cache low byte */ cache_lowbyte = true; buf_addr = (saddr<<1) + 1; buf_lowbyte = rdF[0]; return rdF [1 - (addr&1)]; } else if (segment==SEG_EEPROM){ SetAddress(addr); TByte readEE [1] = { 'd' }; Send(readEE, 1); return readEE[0]; } else return 0;}void TAvrAtmel::WriteByte(TAddr addr, TByte byte, bool flush_buffer){ CheckMemoryRange(addr); /* do not check if byte is already written -- it spoils auto-increment feature which reduces the speed for 50%! */ if (segment==SEG_FLASH){ cache_lowbyte = false; /* clear read cache buffer */ if (!page_size && byte==0xff) return; /* PAGE MODE PROGRAMMING: If page mode is enabled cache page address. When current address is out of the page address flush page buffer and continue programming. */ if (page_size){ Info(4, "Loading data to address: %d (page_addr_fetched=%s)\n", addr, page_addr_fetched?"Yes":"No"); if (page_addr_fetched && page_addr != (addr & ~(page_size - 1))){ WriteProgramMemoryPage(); page_addr_fetched = false; } if (page_addr_fetched==false){ page_addr=addr & ~(page_size - 1); page_addr_fetched=true; } if (flush_buffer){WriteProgramMemoryPage();} } TByte wrF [2] = { (addr&1)?'C':'c', byte }; if (apc_address!=(addr>>1) || apc_autoinc==false) SetAddress (addr>>1); if (wrF[0]=='C') apc_address++; Send(wrF, 2, 1); CheckResponse(wrF[0]); } else if (segment==SEG_EEPROM){ SetAddress(addr); TByte writeEE [2] = { 'D', byte }; Send(writeEE, 2, 1); CheckResponse(writeEE[0]); } }void TAvrAtmel::FlushWriteBuffer(){ if (page_addr_fetched){ WriteProgramMemoryPage(); }}void TAvrAtmel::ChipErase(){ TByte eraseTarget [1] = { 'e' }; Send (eraseTarget, 1); CheckResponse(eraseTarget [0]); Info(1, "Erasing device ...\nReinitializing device\n"); EnableAvr();}void TAvrAtmel::WriteLockBits(TByte bits){ TByte lockTarget [2] = { 'l', 0xF9 | ((bits << 1) & 0x06) }; Send (lockTarget, 2, 1); CheckResponse(lockTarget [0]); Info(1, "Writing lock bits ...\nReinitializing device\n"); EnableAvr();}/* Constructor/Destructor*/TAvrAtmel::TAvrAtmel(): cache_lowbyte(false), apc_address(0x10000), apc_autoinc(false) { /* Select Part by Number or Name */ desired_avrcode=0xff; const char* desired_partname = GetCmdParam("-dpart"); bool got_device=false; if (desired_partname!=NULL) { if (desired_partname[0] >= '0' && desired_partname[0] <= '9'){ desired_avrcode = strtol(&desired_partname[0],(char**)NULL,16); } else{ int j; for (j=0; prg_part[j].name[0] != 0; j++){ if (strcmp (desired_partname, prg_part[j].name)==0){ desired_avrcode = prg_part[j].code; break; } } if (prg_part[j].name[0]==0){throw Error_Device("-dpart: Invalid name.");} } } /* check: software version and supported part codes */ TByte sw_version [2] = {'V', 0}; TByte hw_version [2] = {'v', 0}; Send(sw_version, 1, 2); Send(hw_version, 1, 2); Info(1, "Programmer Information:\n" " Software Version: %c.%c, Hardware Version: %c.%c\n", sw_version [0], sw_version [1], hw_version [0], hw_version [1]); /* Detect Auto-Increment */ if (sw_version[0]>='2'){ apc_autoinc=true; Info(2, "Address Auto Increment Optimization Enabled\n"); } /* Retrieve supported codes */ TByte sup_codes[1] = {'t'}; TByte sup_prg_code[32]; Tx(sup_codes, 1); TByte buf_code; timeval timeout = {1, 0}; int i=0; if (desired_partname==NULL){ Info(1, " Supported Parts:\n\tNo\tAbbreviation\tDescription\n"); } do{ Rx(&buf_code, 1, &timeout); sup_prg_code[i++] = buf_code; if (buf_code==0){break;} if (desired_partname!=NULL){ if (buf_code==desired_avrcode){got_device=true;} if (desired_avrcode!=AUTO_SELECT) continue; } int j; for (j=0; prg_part[j].name[0] != 0; j++){ if (prg_part[j].code == buf_code){ prg_part[j].supported = true; if (desired_avrcode!=AUTO_SELECT){ Info(1, "\t%.2x\t%s\t\t%s\n", buf_code, prg_part[j].name, prg_part[j].description); } break; } } if (prg_part[j].code == 0) { Info(1, " - %.2xh (not on the uisp's list yet)\n", buf_code); } } while (1); Info(1, "\n"); if (got_device==false) { if (desired_partname==NULL){ throw Error_Device("Select a part from the list with the: -dpart\n" "or use the -dpart=auto option for auto-select.\n"); } else if (desired_avrcode!=AUTO_SELECT){ throw Error_Device("Programmer does not supported chosen device."); } } EnableAvr();}TAvrAtmel::~TAvrAtmel(){ /* leave programming mode! Due to this procedure, enableAvr had to be taken out of TAtmelAvr::TAtmelAvr func. */ LeaveProgrammingMode();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -