Index: src/Stk500.C =================================================================== RCS file: /cvsroot/uisp/uisp/src/Stk500.C,v retrieving revision 1.1 diff -u -r1.1 Stk500.C --- src/Stk500.C 25 May 2002 17:59:46 -0000 1.1 +++ src/Stk500.C 30 May 2002 05:42:06 -0000 @@ -158,27 +158,127 @@ /* Read byte from active segment at address addr. */ -TByte TStk500::ReadByte(TAddr addr){ +TByte TStk500::ReadByte(TAddr addr) +{ + TByte val = 0xff; + + if (segment == SEG_FUSE) + { + switch (addr) + { + case 0: + if (TestFeatures(AVR_FUSE_RD)) + val = ReadFuseLowBits(); + else if (TestFeatures(AVR_LOCK_RD76)) + val = ReadLockFuseBits(); + else + Info (1, "Cannot read low fuse bits on this device. Returning 0xff\n"); + break; + + case 1: + if (TestFeatures(AVR_FUSE_HIGH)) + val = ReadFuseHighBits(); + else + Info (1, "Cannot read high fuse bits on this device. Returning 0xff\n"); + break; + + case 2: + if (TestFeatures(AVR_CAL_RD)) + val = ReadCalFuseBits(0); + else + Info (1, "Cannot read calibration byte on this device. Returning 0xff\n"); + break; + + case 3: + /* FIXME: TRoth/2002-05-29: Should there be a feature test here? This + will be a duplicate operation if AVR_LOCK_RD76 is set. */ + val = ReadLockFuseBits(); + break; + + case 4: + if (TestFeatures(AVR_FUSE_EXT)) + val = ReadFuseExtBits(); + else + Info (1, "Cannot read extended fuse bits on this device. Returning 0xff\n"); + break; + } + } + else + { + /* FIXME: TRoth/2002-05-29: This is still broken. If flash or eeprom + changes after the calling ReadMem(), you won't ever see the change. */ - if (read_buffer == NULL) - ReadMem(); + if (read_buffer[segment] == NULL) + ReadMem(); - return read_buffer[addr]; + val = read_buffer[segment][addr]; + } + return val; } /* Write byte to active segment */ -void TStk500::WriteByte(TAddr addr, TByte byte, bool flush_buffer=true){ - - if (write_buffer == NULL) { - write_buffer = new TByte[GetSegmentSize()]; - memset(write_buffer, 0xff, GetSegmentSize()); +void TStk500::WriteByte(TAddr addr, TByte byte, bool flush_buffer) +{ + if (segment == SEG_FUSE) + { + switch (addr) + { + case 0: + if (TestFeatures(AVR_FUSE_RD)) + WriteFuseLowBits(byte); + else if (TestFeatures(AVR_LOCK_RD76)) + WriteLockFuseBits(byte); + else + Info (1, "Cannot write low fuse bits on this device.\n"); + break; + + case 1: + if (TestFeatures(AVR_FUSE_HIGH)) + WriteFuseHighBits(byte); + else + Info (1, "Cannot write high fuse bits on this device.\n"); + break; + + case 2: + /* TRoth/2002-05-29: Can any device write the cal byte? */ + +// if (TestFeatures(AVR_CAL_RD)) +// WriteCalFuseBits(0); +// else +// Info (1, "Cannot write calibration byte on this device.\n"); + break; + + case 3: + /* FIXME: TRoth/2002-05-29: Should there be a feature test here? This + will be a duplicate operation if AVR_LOCK_RD76 is set. */ + WriteLockFuseBits(byte); + break; + + case 4: + if (TestFeatures(AVR_FUSE_EXT)) + WriteFuseExtBits(byte); + else + Info (1, "Cannot read extended fuse bits on this device.\n"); + break; + } } + else + { + if (write_buffer[segment] == NULL) { + write_buffer[segment] = new TByte[GetSegmentSize()]; + memset(write_buffer[segment], 0xff, GetSegmentSize()); + } + + if (addr > maxaddr) + maxaddr = addr; - if (addr > maxaddr) - maxaddr = addr; + write_buffer[segment][addr] = byte; - write_buffer[addr] = byte; + if (flush_buffer) { + FlushWriteBuffer(); + } + } } @@ -211,7 +311,7 @@ buf[1] = 0x01; buf[2] = 0x00; buf[3] = seg; - memcpy(buf+sizeof(WriteMemory), write_buffer+addr, 0x100); + memcpy(buf+sizeof(WriteMemory), write_buffer[segment]+addr, 0x100); memcpy(buf+sizeof(WriteMemory)+0x100, CmdStopByte, sizeof(CmdStopByte)); Send(buf, sizeof(WriteMemory)+0x100+sizeof(CmdStopByte), @@ -238,9 +338,116 @@ } -/* Brrr.. evil :( */ -void TStk500::WriteLockBits(TByte bits){ - throw Error_Device ("TStk500::WriteLockBits not implemented."); +TByte TStk500::ReadLockFuseBits() +{ + TByte bits; + TByte cmd[] = { 0x58, 0x00, 0x00, 0x00 }; + + EnterProgrammingMode(); + bits = UniversalCmd(cmd); + LeaveProgrammingMode(); + + return bits; +} + + +TByte TStk500::ReadCalFuseBits(int addr) +{ + TByte bits; + TByte cmd[] = { 0xc8, 0x00, addr, 0x00 }; + + EnterProgrammingMode(); + bits = UniversalCmd(cmd); + LeaveProgrammingMode(); + + return bits; +} + + +TByte TStk500::ReadFuseLowBits() +{ + TByte bits; + TByte cmd[] = { 0x50, 0x00, 0x00, 0x00 }; + + EnterProgrammingMode(); + bits = UniversalCmd(cmd); + LeaveProgrammingMode(); + + return bits; +} + + +TByte TStk500::ReadFuseHighBits() +{ + TByte bits; + TByte cmd[] = { 0x58, 0x08, 0x00, 0x00 }; + + EnterProgrammingMode(); + bits = UniversalCmd(cmd); + LeaveProgrammingMode(); + + return bits; +} + + +TByte TStk500::ReadFuseExtBits() +{ + TByte bits; + TByte cmd[] = { 0x50, 0x08, 0x00, 0x00 }; + + EnterProgrammingMode(); + bits = UniversalCmd(cmd); + LeaveProgrammingMode(); + + return bits; +} + + +void TStk500::WriteLockFuseBits(TByte bits) +{ + TByte cmd[] = { 0xac, 0xff, 0xff, bits & 0xc0 }; + + EnterProgrammingMode(); + UniversalCmd(cmd); + LeaveProgrammingMode(); +} + + +void TStk500::WriteFuseLowBits(TByte bits) +{ + TByte cmd[] = { 0xac, 0xa0, 0xff, bits }; + + EnterProgrammingMode(); + UniversalCmd(cmd); + LeaveProgrammingMode(); +} + + +void TStk500::WriteFuseHighBits(TByte bits) +{ + TByte cmd[] = { 0xac, 0xa8, 0xff, bits }; + + EnterProgrammingMode(); + UniversalCmd(cmd); + LeaveProgrammingMode(); +} + + +void TStk500::WriteFuseExtBits(TByte bits) +{ + TByte cmd[] = { 0xac, 0xa4, 0xff, bits }; + + EnterProgrammingMode(); + UniversalCmd(cmd); + LeaveProgrammingMode(); +} + + +void TStk500::WriteLockBits(TByte bits) +{ + /* FIXME: TRoth/2002-05-29: This is not this simple. */ + //WriteLockFuseBits(bits); + Info (0, "TStk500::WriteLockBits is not implemented yet.\n"); } @@ -294,6 +501,28 @@ } +/* TRoth/2002-05-28: A Universal Command seems to be just the 4 bytes of an + SPI command. I'm basing this on my interpretation of the doc/README.stk500 + and Table 129 of the mega128 datasheet (page 300). */ + +TByte TStk500::UniversalCmd(TByte cmd[]) +{ + TByte buf[6] = { 0x56, 0x00, 0x00, 0x00, 0x00, 0x20 }; + + memcpy(buf+1, cmd, 4); + + /* Expected response is { 0x14, , 0x10 } */ + Send(buf, sizeof(buf), 3); + + if ((buf[0] != 0x14) || (buf[2] != 0x10)) + { + throw Error_Device ("Device is not responding correctly."); + } + + return buf[1]; +} + + void TStk500::ReadSignature() { TByte buf[100]; @@ -311,16 +540,18 @@ TAddr addr; TByte seg; - read_buffer = new TByte[GetSegmentSize()]; - if (segment == SEG_FLASH) { wordsize = 2; seg = Flash; - } else { + } else if (segment == SEG_EEPROM) { wordsize = 1; seg = EEPROM; + } else { + throw Error_Device ("TStk500::ReadMem() called for invalid segment."); } + read_buffer[segment] = new TByte[GetSegmentSize()]; + EnterProgrammingMode(); addr = 0; @@ -336,7 +567,7 @@ buf[3] = seg; Send(buf, sizeof(ReadMemory), 2+0x100); - memcpy(read_buffer+addr, buf+1, 0x100); + memcpy(read_buffer[segment]+addr, buf+1, 0x100); } LeaveProgrammingMode(); @@ -370,14 +601,21 @@ LeaveProgrammingMode(); Identify(); - write_buffer = NULL; - read_buffer = NULL; + write_buffer[SEG_FLASH] = NULL; + write_buffer[SEG_EEPROM] = NULL; + + read_buffer[SEG_FLASH] = NULL; + read_buffer[SEG_EEPROM] = NULL; + maxaddr = 0; } TStk500::~TStk500() { - delete write_buffer; - delete read_buffer; + delete write_buffer[SEG_FLASH]; + delete write_buffer[SEG_EEPROM]; + + delete read_buffer[SEG_FLASH]; + delete read_buffer[SEG_EEPROM]; } Index: src/Stk500.h =================================================================== RCS file: /cvsroot/uisp/uisp/src/Stk500.h,v retrieving revision 1.1 diff -u -r1.1 Stk500.h --- src/Stk500.h 25 May 2002 17:59:46 -0000 1.1 +++ src/Stk500.h 30 May 2002 05:42:08 -0000 @@ -40,8 +40,8 @@ }; int desired_part; - TByte* write_buffer; - TByte* read_buffer; + TByte* write_buffer[2]; /* buffer for SEG_FLASH and SEG_EEPROM */ + TByte* read_buffer[2]; /* buffer for SEG_FLASH and SEG_EEPROM */ TAddr maxaddr; static const TByte pSTK500[]; @@ -77,6 +77,19 @@ void LeaveProgrammingMode(); void ReadSignature(); void ReadMem(); + + TByte UniversalCmd(TByte cmd[]); + + TByte ReadLockFuseBits(); + TByte ReadCalFuseBits(int addr); + TByte ReadFuseLowBits(); + TByte ReadFuseHighBits(); + TByte ReadFuseExtBits(); + + void WriteLockFuseBits(TByte bits); + void WriteFuseLowBits(TByte bits); + void WriteFuseHighBits(TByte bits); + void WriteFuseExtBits(TByte bits); public: /* Read byte from active segment at address addr. */