/*************************************************************************** * Copyright (C) 2007 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 "tbl_bootloader.h" #include "tbl_bootloader_data.h" #include "progs/base/prog_config.h" //----------------------------------------------------------------------------- Port::Serial::Speed TinyBootloader::Config::readSpeed() { uint speed = readUIntEntry("port_speed", 19200); for (uint i=0; iopen() ) return false; Config config; if ( !port()->setMode(Port::Serial::IgnoreBreak | Port::Serial::IgnoreParity, Port::Serial::ByteSize8 | Port::Serial::IgnoreControlLines, config.readSpeed(), _timeout) ) return false; return true; } bool TinyBootloader::Hardware::internalConnectHardware() { if ( !openPort() ) return false; // #### possibly do hard (RTS) or soft reset (codes) uchar uc = 0xC1; if ( !port()->sendChar(uc, _timeout) ) return false; if ( !port()->receiveChar((char &)_id, _timeout) ) return false; if ( !waitReady(0) ) return false; return true; } bool TinyBootloader::Hardware::verifyDeviceId() { uchar id = data(device().name()).id; TQValueVector list = _base.group().supportedDevices(); TQStringList devices; for (uint i=0; ireceiveChar(c, _timeout) ) return false; if ( c=='K' ) { if (checkCRC) *checkCRC = true; return true; } if (checkCRC) { *checkCRC = false; if ( c=='N' ) return true; log(Log::LineType::Error, i18n("Received unexpected character ('%1' received; 'K' or 'N' expected).").arg(toPrintable(c, PrintAlphaNum))); return true; } log(Log::LineType::Error, i18n("Received unexpected character ('%1' received; 'K' expected).").arg(toPrintable(c, PrintAlphaNum))); return false; } bool TinyBootloader::Hardware::sendChar(char c, uchar *crc) { if (crc) *crc += c; return port()->sendChar(c, 10*_timeout); } bool TinyBootloader::Hardware::sendCodeAddress(uint address, uchar &crc) { switch (device().architecture().type()) { case Pic::Architecture::P16X: if ( !sendChar(address >> 8, &crc) ) return false; // address high if ( !sendChar(address & 0xFF, &crc) ) return false; // address low break; case Pic::Architecture::P18F: if ( !sendChar(address >> 16, &crc) ) return false; // address upper if ( !sendChar((address >> 8) & 0xFF, &crc) ) return false; // address high if ( !sendChar(address & 0xFF, &crc) ) return false; // address low break; case Pic::Architecture::P30F: if ( !sendChar(address & 0xFF, &crc) ) return false; // address low if ( !sendChar((address >> 8) & 0xFF, &crc) ) return false; // address high if ( !sendChar(address >> 16, &crc) ) return false; // address upper break; default: Q_ASSERT(false); return false; } return true; } bool TinyBootloader::Hardware::endWrite(uchar crc, uint &retries, bool &ok) { if ( !sendChar(-crc & 0xFF, 0) ) return false; if ( !waitReady(&ok) ) return false; if ( !ok ) { if ( retries==0 ) { log(Log::LineType::Error, i18n("Too many failures: bailing out.")); return false; } retries--; log(Log::LineType::Warning, i18n("CRC error from bootloader: retrying...")); } return true; } bool TinyBootloader::Hardware::writeCode(const Device::Array &data, bool erase) { uint nb = data.count() - 100; Device::Array wdata(nb+4); // check that there is nothing on top of bootloader for (uint i=nb; i(hardware()).writeCode(memory.arrayForWriting(type), true); return hardware().write(type, memory.arrayForWriting(type)); }