/*************************************************************************** * Copyright (C) 2006 Nicolas Hadacek * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "direct_30.h" const uint BULK_ERASE_SEQUENCE[] = { // for all dsPICs 0x000000, 0x000000, 0x040100, 0x000000, // step 1 Direct::Pic30::LoopStart + 2, 0x24008A, 0x883B0A, // step 2 0x200F80, 0x880190, 0x200067, // step 3 0xBB0300, // step 4 0xBB1B86, // step 5 0x200558, 0x200AA9, 0x883B38, 0x883B39, // step 6 0xA8E761, 0x000000, 0x000000, // step 7 Direct::Pic30::Pause + 2000000, 0xA9E761, 0x000000, 0x000000, Direct::Pic30::LoopEnd, 0x2407FA, 0x883B0A, // step 9 0x200558, 0x883B38, 0x200AA9, 0x883B39, // step 10 0xA8E761, 0x000000, 0x000000, // step 11 Direct::Pic30::Pause + 2000000, 0xA9E761, 0x000000, 0x000000, Direct::Pic30::End }; const uint READ_APPLICATION_ID_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 0x200800, 0x880190, 0x205FE0, 0x207841, // step 2 0xBA0890, 0x000000, 0x000000, Direct::Pic30::RegisterOut, 0x000000, // step 3 Direct::Pic30::End }; const uint READ_CONFIG_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 0x200F80, 0x880190, 0xEB0300, 0xEB0380, // step 2 Direct::Pic30::LoopStart + 7, 0xBA0BB6, 0x000000, 0x000000, 0x883C20, 0x000000, // step 3 Direct::Pic30::RegisterOut, 0x000000, // step 4 0x040100, 0x000000, // step 5 Direct::Pic30::LoopEnd, Direct::Pic30::End }; const uint WRITE_CONFIG_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 Direct::Pic30::FillAddressLow + 0x200007, // step 2 0x24008A, 0x883B0A, // step 3 0x200F80, 0x880190, // step 4 Direct::Pic30::FillData + 0x200000, // step 5 //0xEB0300, ??? 0xBB1B96, 0x000000, 0x000000, // step 8 0x200558, 0x883B38, 0x200AA9, 0x883B39, // step 7 0xA8E761, 0x000000, 0x000000, // step 8 Direct::Pic30::Pause + 2000000, 0xA9E761, 0x000000, 0x000000, Direct::Pic30::End }; const uint READ_DATA_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 0x2007F0, 0x880190, Direct::Pic30::FillAddressLow + 0x200006, // step 2 0xEB0380, // step 3 0xBA1BB6, 0x000000, 0x000000, 0xBA1BB6, 0x000000, 0x000000, 0xBA1BB6, 0x000000, 0x000000, 0xBA1BB6, 0x000000, 0x000000, 0x883C20, 0x000000, Direct::Pic30::RegisterOut, 0x000000, // step 4 0x883C21, 0x000000, Direct::Pic30::RegisterOut, 0x000000, 0x883C22, 0x000000, Direct::Pic30::RegisterOut, 0x000000, 0x883C23, 0x000000, Direct::Pic30::RegisterOut, 0x000000, Direct::Pic30::End }; const uint WRITE_DATA_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 0x24005A, 0x883B0A, // step 2 0x2007F0, 0x880190, Direct::Pic30::FillAddressLow + 0x200007, // step 3 Direct::Pic30::LoopStart + 4, Direct::Pic30::FillData + 0x200000, // step 4 Direct::Pic30::FillData + 0x200001, Direct::Pic30::FillData + 0x200002, Direct::Pic30::FillData + 0x200003, 0xEB0300, 0x000000, // step 5 0xBB1BB6, 0x000000, 0x000000, 0xBB1BB6, 0x000000, 0x000000, 0xBB1BB6, 0x000000, 0x000000, 0xBB1BB6, 0x000000, 0x000000, Direct::Pic30::LoopEnd, 0x200558, 0x883B38, 0x200AA9, 0x883B39, // step 7 0xA8E761, 0x000000, 0x000000, // step 8 Direct::Pic30::Pause + 2000000, 0xA9E761, 0x000000, 0x000000, Direct::Pic30::End }; const uint READ_CODE_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 Direct::Pic30::FillAddressHigh + 0x200000, // step 2 0x880190, Direct::Pic30::FillAddressLow + 0x200006, 0xEB0380, // step 3 0xBA1B96, 0x000000, 0x000000, 0xBADBB6, 0x000000, 0x000000, 0xBADBD6, 0x000000, 0x000000, 0xBA1BB6, 0x000000, 0x000000, 0xBA1B96, 0x000000, 0x000000, 0xBADBB6, 0x000000, 0x000000, 0xBADBD6, 0x000000, 0x000000, 0xBA0BB6, 0x000000, 0x000000, 0x883C20, 0x000000, Direct::Pic30::RegisterOut, 0x000000, // step 4 0x883C21, 0x000000, Direct::Pic30::RegisterOut, 0x000000, 0x883C22, 0x000000, Direct::Pic30::RegisterOut, 0x000000, 0x883C23, 0x000000, Direct::Pic30::RegisterOut, 0x000000, 0x883C24, 0x000000, Direct::Pic30::RegisterOut, 0x000000, 0x883C25, 0x000000, Direct::Pic30::RegisterOut, 0x000000, Direct::Pic30::End }; const uint WRITE_CODE_SEQUENCE[] = { 0x000000, 0x000000, 0x040100, 0x000000, // step 1 0x24001A, 0x883B0A, // step 2 Direct::Pic30::FillAddressHigh + 0x200000, // step 3 0x880190, Direct::Pic30::FillAddressLow + 0x200007, Direct::Pic30::LoopStart + 8, Direct::Pic30::FillData + 0x200000, // step 4 Direct::Pic30::FillData + 0x200001, Direct::Pic30::FillData + 0x200002, Direct::Pic30::FillData + 0x200003, Direct::Pic30::FillData + 0x200004, Direct::Pic30::FillData + 0x200005, 0xEB0300, 0x000000, // step 5 0xBB0BB6, 0x000000, 0x000000, 0xBBDBB6, 0x000000, 0x000000, 0xBBEBB6, 0x000000, 0x000000, 0xBB1BB6, 0x000000, 0x000000, 0xBB0BB6, 0x000000, 0x000000, 0xBBDBB6, 0x000000, 0x000000, 0xBBEBB6, 0x000000, 0x000000, 0xBB1BB6, 0x000000, 0x000000, Direct::Pic30::LoopEnd, 0x200558, 0x883B38, 0x200AA9, 0x883B39, // step 7 0xA8E761, 0x000000, 0x000000, 0x000000, 0x000000, // step 8 Direct::Pic30::Pause + 2000000, 0xA9E761, 0x000000, 0x000000, 0x000000, 0x000000, Direct::Pic30::End }; bool Direct::Pic30::sendCommand(Command cmd) { for (uint i=0; i<4; i++) { hardware().setPin(DataOut, ((cmd>>i) & 1 ? High : Low)); hardware().setPin(Clock, High); Port::nsleep(100); hardware().setPin(Clock, Low); Port::nsleep(100); } return true; } bool Direct::Pic30::executeSIX(uint opcode) { if ( !sendCommand(SIX) ) return false; for (uint i=0; i<24; i++) { hardware().setPin(DataOut, ((opcode>>i) & 1 ? High : Low)); hardware().setPin(Clock, High); Port::nsleep(100); hardware().setPin(Clock, Low); // seem to need this longer delay here -- maybe // specific to my programmer hardware? #### from dspicprg Port::nsleep(5000); } return true; } bool Direct::Pic30::executeREGOUT(uint &v) { v = 0; if ( !sendCommand(REGOUT) ) return false; hardware().setPin(DataOut, High); for (uint i=0; i<24; i++) { hardware().setPin(Clock, High); Port::nsleep(100); hardware().setPin(Clock, Low); // as above, need extra delay here, but even // longer in this case -- maybe data line takes // longer to settle when it is being driven by // the PIC than by the programmer? #### from dspicprg Port::nsleep(10000); if ( i>=8 ) { uint r = hardware().readBit(); v |= (r << (i-8)); } } return true; } bool Direct::Pic30::doStdpSequence(const uint *sequence, uint address, const char *outData, char *inData) { uint loopStart = 0, loopCound = 0; for (uint i=0; sequence[i]!=End; i++) { uint opcode = (sequence[i] & OpcodeMask); switch (Operation(sequence[i] & OperationMask)) { case SendSix: if ( !executeSIX(opcode) ) return false; break; case RegisterOut: { uint v; if ( !executeREGOUT(v) ) return false; (*inData) = v & 0xFF; inData++; (*inData) = (v >> 8) & 0xFF; inData++; break; } case Pause: Port::nsleep(opcode); break; case LoopStart: loopCound = opcode; loopStart = i; break; case LoopEnd: loopCound--; if (loopCound) i = loopStart; break; case FillData: { uint v = *outData; v <<= 4; outData++; v |= *outData; outData++; v <<= 4; executeSIX(v | opcode); break; } case FillAddressLow: { uint v = address & 0xFFFF; v <<= 4; executeSIX(v | opcode); break; } case FillAddressHigh: { uint v = (address & 0xFF0000) >> 16; v <<= 4; executeSIX(v | opcode); break; } case End: Q_ASSERT(false); break; } } return true; } bool Direct::Pic30::doErase(bool) { if ( !enterStdpMode() ) return false; if ( !doStdpSequence(BULK_ERASE_SEQUENCE, 0, 0, 0) ) return false; return exitStdpMode(); } bool Direct::Pic30::doRead(Pic::MemoryRangeType type, Device::Array &data, const ::Programmer::VerifyData *data) { // #### TODO return false; } bool Direct::Pic30::doWrite(Pic::MemoryRangeType type, const Device::Array &data, bool force) { // #### TODO return false; }