1
/***************************************************************************
2
* Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
4
* This program is free software; you can redistribute it and/or modify *
5
* it under the terms of the GNU General Public License as published by *
6
* the Free Software Foundation; either version 2 of the License, or *
7
* (at your option) any later version. *
8
***************************************************************************/
11
#include "devices/base/device_group.h"
12
#include "progs/base/prog_group.h"
14
//-----------------------------------------------------------------------------
15
Pickit::Array::Array(uint length, uchar fillChar, PrintMode mode)
16
: _fillChar(fillChar), _mode(mode), _data(length)
21
QString Pickit::Array::pretty() const
23
int end = _data.count() - 1;
25
if ( _data[end]!=_fillChar ) break;
27
for (int i=0; i<=end; i++) s += toPrintable(_data[i], _mode);
31
//-----------------------------------------------------------------------------
32
Pickit::USBPort::USBPort(uint deviceId, Log::Base &log)
35
init(Microchip::VENDOR_ID, deviceId, CONFIG_HID);
38
bool Pickit::USBPort::command(uchar c)
45
bool Pickit::USBPort::command(const char *s)
49
Q_ASSERT( strlen(s)<=a.length() );
50
for (uint i=0; i<strlen(s); i++) a._data[i] = s[i];
55
bool Pickit::USBPort::command(const Array &cmd)
57
log(Log::ExtraDebug, QString("send command: \"%1\"").arg(cmd.pretty()));
58
return write(writeEndPoint(), (const char *)cmd._data.data(), cmd.length());
61
bool Pickit::USBPort::receive(Pickit::Array &array)
63
if ( !read(readEndPoint(), (char *)array._data.data(), array.length()) ) return false;
64
log(Log::MaxDebug, QString("received: \"%1\"").arg(array.pretty()));
68
bool Pickit::USBPort::getMode(VersionData &version, ::Programmer::Mode &mode)
70
if ( !command('v') ) return false;
72
if ( !receive(a) ) return false;
74
version = VersionData(a[6], a[7], 0);
75
mode = ::Programmer::BootloadMode;
77
version = VersionData(a[0], a[1], a[2]);
78
mode = ::Programmer::NormalMode;
83
bool Pickit::USBPort::receiveWords(uint nbBytesWord, uint nbRead, QValueVector<uint> &words, uint offset)
85
log(Log::MaxDebug, QString("receive words nbBytesWord=%1 nbRead=%2 offset=%3").arg(nbBytesWord).arg(nbRead).arg(offset));
87
QMemArray<uchar> data(nbRead*a.length());
89
for (uint i=0; i<nbRead; i++) {
90
if ( !receive(a) ) return false;
91
for (uint k=offset; k<a.length(); k++) {
96
words.resize(data.count()/nbBytesWord);
97
for (uint i=0; i<uint(words.count()); i++) {
99
for (uint k=0; k<nbBytesWord; k++) words[i] |= data[nbBytesWord*i + k] << (8*k);
104
//-----------------------------------------------------------------------------
105
Pickit::Hardware::Hardware(::Programmer::Base &base, USBPort *port)
106
: ::Programmer::PicHardware(base, port)
109
bool Pickit::Hardware::internalConnectHardware()
111
return port().open();
114
bool Pickit::Hardware::setTargetPower(uint v)
116
Array cmd = port().array();
119
return port().command(cmd);
122
bool Pickit::Hardware::writeWords(uint max, char c, uint nbBytesWord,
123
uint &i, const Device::Array &data)
125
Q_ASSERT( i<data.count() );
126
Q_ASSERT( nbBytesWord==1 || nbBytesWord==2 );
127
Array cmd = port().array();
128
uint n = (nbBytesWord==1 ? 2 : 3);
129
Q_ASSERT( n*max<=cmd.length() );
130
for (uint k=0; k<max; k++) {
132
cmd[n*k+1] = data[i] & 0xFF;
133
if ( nbBytesWord==2 ) cmd[n*k+2] = (data[i] >> 8) & 0xFF;
135
if ( i>=data.count() ) break;
137
return port().command(cmd);
140
bool Pickit::Hardware::regenerateOsccal(uint &newValue)
142
if ( !setTargetPower(Osc2_5kHz) ) return false;
143
if ( !setTargetPower(PowerOn + Osc2_5kHz) ) return false;
144
Port::usleep(400000); // 400 ms
145
if ( !setTargetPower(PowerOff) ) return false;
146
Pickit::Array cmd = port().array();
153
if ( !port().command(cmd) ) return false;
154
QValueVector<uint> words;
155
if ( !port().receiveWords(1, 1, words) ) return false;
156
newValue = words[7] | 0x3400;
160
//----------------------------------------------------------------------------
161
bool Pickit::DeviceSpecific::setPowerOn()
163
return hardware().port().command(entryMode());
166
bool Pickit::DeviceSpecific::setPowerOff()
168
return hardware().port().command('p');
171
bool Pickit::DeviceSpecific::setTargetPowerOn(bool on)
173
return hardware().setTargetPower(on ? PowerOn : PowerOff);
176
//----------------------------------------------------------------------------
177
bool Pickit::BMDeviceSpecific::doRead(Pic::MemoryRangeType type, Device::Array &data, const ::Programmer::VerifyData *vdata)
179
data.resize(device().nbWords(type));
181
QValueVector<uint> words;
183
case Pic::MemoryConfig:
184
case Pic::MemoryCode:
186
case Pic::MemoryCalBackup:
187
case Pic::MemoryUserId:
188
case Pic::MemoryDeviceId:
189
for (uint i=0; i<data.count();) {
190
if ( !hardware().port().command('R') ) return false;
191
if ( !hardware().port().receiveWords(2, 1, words) ) return false;
192
for (uint k=0; k<uint(words.count()); k++) {
194
if ( vdata && !hardware().verifyWord(i, data[i], type, *vdata) ) return false;
196
if ( i>=data.count() ) break;
200
case Pic::MemoryEeprom:
201
for (uint i=0; i<data.count();) {
202
if ( !hardware().port().command('r') ) return false; // #### not sure this is correct for Pickit1: "rrrrrrrr" used by usb_pickit
203
if ( !hardware().port().receiveWords(1, 1, words) ) return false;
204
for (uint k=0; k<uint(words.count()); k++) {
206
if ( vdata && !hardware().verifyWord(i, data[i], type, *vdata) ) return false;
208
if ( i>=data.count() ) break;
212
case Pic::MemoryDebugVector:
213
case Pic::MemoryHardwareStack:
214
case Pic::MemoryProgramExecutive:
215
case Pic::Nb_MemoryRangeTypes: Q_ASSERT(false); return false;
217
if ( type==Pic::MemoryCode || type==Pic::MemoryEeprom ) addProgress(data.count());
221
bool Pickit::BMDeviceSpecific::incrementPC(uint nb)
223
Pickit::Array cmd = hardware().port().array();
226
cmd[2] = (nb >> 8) & 0xFF;
227
return hardware().port().command(cmd);
230
bool Pickit::BMDeviceSpecific::doEraseRange(Pic::MemoryRangeType type)
232
Q_ASSERT( type==Pic::MemoryCode );
233
return hardware().port().command('E');
236
bool Pickit::BMDeviceSpecific::doWrite(Pic::MemoryRangeType type, const Device::Array &data, bool force)
238
// #### TODO: speed optimize...
241
uint nb = nbWrites(type);
243
case Pic::MemoryConfig:
244
case Pic::MemoryCode:
246
case Pic::MemoryUserId:
247
for (uint i=0; i<data.count(); )
248
hardware().writeWords(nb, writeCode(), 2, i, data);
250
case Pic::MemoryEeprom:
251
for (uint i=0; i<data.count(); )
252
hardware().writeWords(nb, writeData(), 1, i, data);
254
case Pic::MemoryCalBackup:
255
case Pic::MemoryDeviceId:
256
case Pic::MemoryDebugVector:
257
case Pic::MemoryHardwareStack:
258
case Pic::MemoryProgramExecutive:
259
case Pic::Nb_MemoryRangeTypes: Q_ASSERT(false); return false;
261
if ( type==Pic::MemoryCode || type==Pic::MemoryEeprom ) addProgress(data.count());
265
//----------------------------------------------------------------------------
266
bool Pickit::Baseline::gotoMemory(Pic::MemoryRangeType type)
269
case Pic::MemoryConfig:
270
case Pic::MemoryEeprom: return true;
271
case Pic::MemoryCode:
273
case Pic::MemoryUserId:
274
case Pic::MemoryCalBackup: return incrementPC(1+device().range(type).start);
275
case Pic::MemoryDeviceId:
276
case Pic::MemoryDebugVector:
277
case Pic::MemoryHardwareStack:
278
case Pic::MemoryProgramExecutive:
279
case Pic::Nb_MemoryRangeTypes: break;
285
//----------------------------------------------------------------------------
286
bool Pickit::P16F::gotoMemory(Pic::MemoryRangeType type)
288
Pickit::Array cmd = hardware().port().array();
291
case Pic::MemoryCode: return true;
292
case Pic::MemoryEeprom: return true;
293
case Pic::MemoryUserId: return hardware().port().command(cmd);
294
case Pic::MemoryDeviceId:
298
return hardware().port().command(cmd);
299
case Pic::MemoryConfig:
303
return hardware().port().command(cmd);
305
if ( device().range(type).start==device().range(Pic::MemoryCode).end+1 )
306
return incrementPC(device().range(type).start);
310
return hardware().port().command(cmd);
311
case Pic::MemoryCalBackup:
312
case Pic::MemoryDebugVector:
313
case Pic::MemoryHardwareStack:
314
case Pic::MemoryProgramExecutive:
315
case Pic::Nb_MemoryRangeTypes: break;
321
bool Pickit::P16F::doErase(bool)
323
Pickit::Array cmd = hardware().port().array();
325
cmd[1] = writeCode();
330
return hardware().port().command(cmd);
333
bool Pickit::P16F::doEraseRange(Pic::MemoryRangeType type)
335
if ( type==Pic::MemoryEeprom ) return hardware().port().command('e');
336
return BMDeviceSpecific::doEraseRange(type);