📄 avratmel.c
字号:
Send(writeEE, 2, 1);
CheckResponse(writeEE[0]);
}
else if (segment==SEG_FUSE){
Info(3, "Write fuse/lock: byte %d = 0x%02X\n",
(int) addr, (int) byte);
switch (addr) {
case AVR_FUSE_LOW_ADDR:
if (TestFeatures(AVR_FUSE_NEWWR))
WriteFuseLowBits(byte);
else if (TestFeatures(AVR_FUSE_OLDWR))
WriteOldFuseBits(byte);
break;
case AVR_FUSE_HIGH_ADDR:
if (TestFeatures(AVR_FUSE_HIGH))
WriteFuseHighBits(byte);
else
Info (1, "Cannot write high fuse bits on this device");
break;
/* calibration byte (addr == 2) is read only */
case AVR_CAL_ADDR:
Info (1, "Cannot write calibration byte. It is read-only.\n");
break;
case AVR_LOCK_ADDR:
WriteLockBits(byte);
break;
case AVR_FUSE_EXT_ADDR:
if (TestFeatures(AVR_FUSE_EXT))
WriteFuseExtBits(byte);
}
}
}
/*
Write Fuse Bits (old): 7 6 5 4 3 2 1 0
2323,8535: x x x 1 1 1 1 FSTRT
2343: x x x 1 1 1 1 RCEN
2333,4433: x x x BODLV BODEN CKSL2 CKSL1 CKSL0
m103,m603: x x x 1 EESAV 1 SUT1 SUT0
*/
void TAvrAtmel::WriteOldFuseBits (TByte val)
{
TByte buf[5] = {'.', 0xac, (val & 0x1f) | 0xa0, 0x00, 0xd2 };
Info (2, "Write fuse high bits: %02x\n", (int)val);
Send (buf, 5, 2);
CheckResponse (buf[1]);
}
/*
Write Fuse Bits (Low, new): 7 6 5 4 3 2 1 0
m161: 1 BTRST 1 BODLV BODEN CKSL2 CKSL1 CKSL0
m163,m323: BODLV BODEN 1 1 CKSL3 CKSL2 CKSL1 CKSL0
m8,m16,m64,m128: BODLV BODEN SUT1 SUT0 CKSL3 CKSL2 CKSL1 CKSL0
tn12: BODLV BODEN SPIEN RSTDI CKSL3 CKSL2 CKSL1 CKSL0
tn15: BODLV BODEN SPIEN RSTDI 1 1 CKSL1 CKSL0
WARNING (tn12,tn15): writing SPIEN=1 disables further low voltage programming!
*/
void TAvrAtmel::WriteFuseLowBits (TByte val)
{
// use new universal command.
TByte buf[5] = {'.', 0xac, 0xa0, 0x00, val };
Info (2, "Write fuse high bits: %02x\n", (int)val);
Send (buf, 5, 2);
CheckResponse (buf[1]);
}
/*
Write Fuse Bits High: 7 6 5 4 3 2 1 0
m163: 1 1 1 1 1 BTSZ1 BTSZ0 BTRST
m323: OCDEN JTGEN 1 1 EESAV BTSZ1 BTSZ0 BTRST
m16,m64,m128: OCDEN JTGEN x CKOPT EESAV BTSZ1 BTSZ0 BTRST
m8: RSTDI WDTON x CKOPT EESAV BTSZ1 BTSZ0 BTRST
*/
void TAvrAtmel::WriteFuseHighBits (TByte val)
{
// use new universal command.
TByte buf[5] = {'.', 0xac, 0xa8, 0x00, val };
Info (2, "Write fuse high bits: %02x\n", (int)val);
Send (buf, 5, 2);
CheckResponse (buf[1]);
}
/*
Write Extended Fuse Bits: 7 6 5 4 3 2 1 0
m64,m128: x x x x x x M103C WDTON
*/
void TAvrAtmel::WriteFuseExtBits (TByte val)
{
// use new universal command.
TByte buf[5] = {'.', 0xac, 0xa4, 0x00, val };
Info (2, "Write fuse extended bits: %02x\n", (int)val);
Send (buf, 5, 2);
CheckResponse (buf[1]);
}
void TAvrAtmel::FlushWriteBuffer(){
if (page_addr_fetched){
WriteProgramMemoryPage();
}
}
/* Chip erase can take a few seconds when talking to a boot loader,
which does it one page at a time. */
#ifndef CHIP_ERASE_TIMEOUT
#define CHIP_ERASE_TIMEOUT 5
#endif
void TAvrAtmel::ChipErase(){
TByte eraseTarget [1] = { 'e' };
Send (eraseTarget, 1, -1, CHIP_ERASE_TIMEOUT);
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();
}
TByte TAvrAtmel::ReadFuseLowBits ()
{
// use new universal command.
TByte buf[5] = {'.', 0x50, 0x00, 0x00, 0x00 };
Send (buf, 5, 2);
CheckResponse (buf[1]);
Info (2, "Read fuse low bits: %02x\n", (int)buf[0]);
return buf[0];
}
TByte TAvrAtmel::ReadFuseHighBits ()
{
// use new universal command.
TByte buf[5] = {'.', 0x58, 0x08, 0x00, 0x00 };
Send (buf, 5, 2);
CheckResponse (buf[1]);
Info (2, "Read fuse high bits: %02x\n", (int)buf[0]);
return buf[0];
}
TByte TAvrAtmel::ReadCalByte(TByte addr)
{
// use new universal command.
TByte buf[5] = {'.', 0x38, 0x00, addr, 0x00 };
Send (buf, 5, 2);
CheckResponse (buf[1]);
Info (2, "Read calibration byte: %02x\n", (int)buf[0]);
return buf[0];
}
TByte TAvrAtmel::ReadFuseExtBits ()
{
// use new universal command.
TByte buf[5] = {'.', 0x50, 0x08, 0x00, 0x00 };
Send (buf, 5, 2);
CheckResponse (buf[1]);
return buf[0];
Info (2, "Read extended fuse bits: %02x\n", (int)buf[0]);
return buf[0];
}
TByte TAvrAtmel::ReadLockFuseBits ()
{
// use new universal command.
TByte buf[5] = {'.', 0x58, 0x00, 0x00, 0x00 };
Send (buf, 5, 2);
CheckResponse (buf[1]);
Info (2, "Read lock bits: %02x\n", (int)buf[0]);
return buf[0];
}
// ReadLockBits tries to return the lock bits in a uniform order, despite
// the differences in different AVR versions. The goal is to get the lock
// bits into this order:
// x x BLB12 BLB11 BLB02 BLB01 LB2 LB1
// For devices that don't support a boot block, the BLB bits will be 1.
TByte
TAvrAtmel::ReadLockBits()
{
TByte rbits = 0xFF;
if (TestFeatures(AVR_LOCK_BOOT)) {
/* x x BLB12 BLB11 BLB02 BLB01 LB2 LB1 */
rbits = ReadLockFuseBits();
} else if (TestFeatures(AVR_LOCK_RD76)) {
rbits = ReadLockFuseBits();
/* LB1 LB2 x x x x x x -> 1 1 1 1 1 1 LB2 LB1 */
rbits = ((rbits >> 7) & 1) | ((rbits >> 5) & 1) | 0xFC;
} else if (TestFeatures(AVR_LOCK_RD12)) {
rbits = ReadLockFuseBits();
/* x x x x x LB2 LB1 x -> 1 1 1 1 1 1 LB2 LB1 */
rbits = ((rbits >> 1) & 3) | 0xFC;
} else {
// if its signature returns 0,1,2 then say it's locked.
/* Read Signature Bytes */
TByte sig_bytes[3] = {'s', 0, 0};
Send(sig_bytes, 1, 3);
if (sig_bytes[0]==0 && sig_bytes[1]==1 && sig_bytes[2]==2)
rbits = 0xFC;
else
throw Error_Device ("ReadLockBits failed: are you sure this device has lock bits?");
}
return rbits;
}
/* 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 ((strcasecmp (desired_partname, prg_part[j].name)==0) ||
(strcasecmp (desired_partname, prg_part[j].description)==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'};
Tx(sup_codes, 1);
TByte buf_code;
timeval timeout = {1, 0};
if (desired_partname==NULL){
Info(1, " Supported Parts:\n\tNo\tAbbreviation\tDescription\n");
}
do{
Rx(&buf_code, 1, &timeout);
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 + -