mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-29 14:52:12 +01:00
OP-35 Preliminary work on the new DFU gadget. Not much to see so far.
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2050 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
6e0332eb10
commit
dde66a3c24
2
ground/src/plugins/uploader/delay.cpp
Normal file
2
ground/src/plugins/uploader/delay.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "delay.h"
|
||||
|
13
ground/src/plugins/uploader/delay.h
Normal file
13
ground/src/plugins/uploader/delay.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef DELAY_H
|
||||
#define DELAY_H
|
||||
#include <QThread>
|
||||
|
||||
class delay : public QThread
|
||||
{
|
||||
public:
|
||||
static void msleep(unsigned long msecs)
|
||||
{
|
||||
QThread::msleep(msecs);
|
||||
}
|
||||
};
|
||||
#endif // DELAY_H
|
725
ground/src/plugins/uploader/op_dfu.cpp
Normal file
725
ground/src/plugins/uploader/op_dfu.cpp
Normal file
@ -0,0 +1,725 @@
|
||||
#include "op_dfu.h"
|
||||
#include <cmath>
|
||||
#include <qwaitcondition.h>
|
||||
#include <QMutex>
|
||||
|
||||
OP_DFU::OP_DFU(bool _debug): debug(_debug)
|
||||
{
|
||||
send_delay=10;
|
||||
use_delay=true;
|
||||
int numDevices=0;
|
||||
cout<<"Please connect device now\n";
|
||||
int count=0;
|
||||
while(numDevices==0)
|
||||
{
|
||||
cout<<".";
|
||||
delay::msleep(500);
|
||||
numDevices = hidHandle.open(1,0x20a0,0x4117,0,0); //0xff9c,0x0001);
|
||||
if(++count==10)
|
||||
{
|
||||
cout<<"\r";
|
||||
cout<<" ";
|
||||
cout<<"\r";
|
||||
count=0;
|
||||
}
|
||||
}
|
||||
if(debug)
|
||||
qDebug() << numDevices << " device(s) opened";
|
||||
}
|
||||
bool OP_DFU::SaveByteArrayToFile(QString const & sfile, const QByteArray &array)
|
||||
{
|
||||
QFile file(sfile);
|
||||
//QFile file("in.txt");
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
if(debug)
|
||||
qDebug()<<"Cant open file";
|
||||
return false;
|
||||
}
|
||||
file.write(array);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OP_DFU::enterDFU(int const &devNumber)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::EnterDFU;//DFU Command
|
||||
buf[2] = 0;//DFU Count
|
||||
buf[3] = 0;//DFU Count
|
||||
buf[4] = 0;//DFU Count
|
||||
buf[5] = 0;//DFU Count
|
||||
buf[6] = devNumber;//DFU Data0
|
||||
buf[7] = 1;//DFU Data1
|
||||
buf[8] = 1;//DFU Data2
|
||||
buf[9] = 1;//DFU Data3
|
||||
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
if(result<1)
|
||||
return false;
|
||||
if(debug)
|
||||
qDebug() << result << " bytes sent";
|
||||
return true;
|
||||
}
|
||||
bool OP_DFU::StartUpload(qint32 const & numberOfBytes, TransferTypes const & type,quint32 crc)
|
||||
{
|
||||
int lastPacketCount;
|
||||
qint32 numberOfPackets=numberOfBytes/4/14;
|
||||
int pad=(numberOfBytes-numberOfPackets*4*14)/4;
|
||||
if(pad==0)
|
||||
{
|
||||
lastPacketCount=14;
|
||||
}
|
||||
else
|
||||
{
|
||||
++numberOfPackets;
|
||||
lastPacketCount=pad;
|
||||
}
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = setStartBit(OP_DFU::Upload);//DFU Command
|
||||
buf[2] = numberOfPackets>>24;//DFU Count
|
||||
buf[3] = numberOfPackets>>16;//DFU Count
|
||||
buf[4] = numberOfPackets>>8;//DFU Count
|
||||
buf[5] = numberOfPackets;//DFU Count
|
||||
buf[6] = (int)type;//DFU Data0
|
||||
buf[7] = lastPacketCount;//DFU Data1
|
||||
buf[8] = crc>>24;
|
||||
buf[9] = crc>>16;
|
||||
buf[10] = crc>>8;
|
||||
buf[11] = crc;
|
||||
if(debug)
|
||||
qDebug()<<"Number of packets:"<<numberOfPackets<<" Size of last packet:"<<lastPacketCount;
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 5000);
|
||||
if(debug)
|
||||
qDebug() << result << " bytes sent";
|
||||
if(result>0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool OP_DFU::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
||||
{
|
||||
int lastPacketCount;
|
||||
qint32 numberOfPackets=numberOfBytes/4/14;
|
||||
int pad=(numberOfBytes-numberOfPackets*4*14)/4;
|
||||
if(pad==0)
|
||||
{
|
||||
lastPacketCount=14;
|
||||
}
|
||||
else
|
||||
{
|
||||
++numberOfPackets;
|
||||
lastPacketCount=pad;
|
||||
}
|
||||
if(debug)
|
||||
qDebug()<<"Start Uploading:"<<numberOfPackets<<"4Bytes";
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Upload;//DFU Command
|
||||
int packetsize;
|
||||
float percentage;
|
||||
int laspercentage;
|
||||
for(qint32 packetcount=0;packetcount<numberOfPackets;++packetcount)
|
||||
{
|
||||
percentage=(float)(packetcount+1)/numberOfPackets*100;
|
||||
if(laspercentage!=(int)percentage)
|
||||
printProgBar((int)percentage,"UPLOADING");
|
||||
laspercentage=(int)percentage;
|
||||
if(packetcount==numberOfPackets)
|
||||
packetsize=lastPacketCount;
|
||||
else
|
||||
packetsize=14;
|
||||
// qDebug()<<packetcount;
|
||||
buf[2] = packetcount>>24;//DFU Count
|
||||
buf[3] = packetcount>>16;//DFU Count
|
||||
buf[4] = packetcount>>8;//DFU Count
|
||||
buf[5] = packetcount;//DFU Count
|
||||
char *pointer=data.data();
|
||||
pointer=pointer+4*14*packetcount;
|
||||
// qDebug()<<"Packet Number="<<packetcount<<"Data0="<<(int)data[0]<<" Data1="<<(int)data[1]<<" Data0="<<(int)data[2]<<" Data0="<<(int)data[3]<<" buf6="<<(int)buf[6]<<" buf7="<<(int)buf[7]<<" buf8="<<(int)buf[8]<<" buf9="<<(int)buf[9];
|
||||
CopyWords(pointer,buf+6,packetsize*4);
|
||||
// for (int y=0;y<packetsize*4;++y)
|
||||
// {
|
||||
|
||||
// qDebug()<<y<<":"<<(int)data[packetcount*14*4+y]<<"---"<<(int)buf[6+y];
|
||||
|
||||
|
||||
// }
|
||||
// qDebug()<<" Data0="<<(int)data[0]<<" Data0="<<(int)data[1]<<" Data0="<<(int)data[2]<<" Data0="<<(int)data[3]<<" buf6="<<(int)buf[6]<<" buf7="<<(int)buf[7]<<" buf8="<<(int)buf[8]<<" buf9="<<(int)buf[9];
|
||||
//delay::msleep(send_delay);
|
||||
if(int ret=StatusRequest()!=OP_DFU::uploading) return false;
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 5000);
|
||||
// qDebug()<<"sent:"<<result;
|
||||
if(result<1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// qDebug() << "UPLOAD:"<<"Data="<<(int)buf[6]<<(int)buf[7]<<(int)buf[8]<<(int)buf[9]<<";"<<result << " bytes sent";
|
||||
|
||||
}
|
||||
cout<<"\n";
|
||||
// while(true){}
|
||||
return true;
|
||||
}
|
||||
OP_DFU::Status OP_DFU::UploadDescription(QString & description)
|
||||
{
|
||||
cout<<"Starting uploading description\n";
|
||||
if(description.length()%4!=0)
|
||||
{
|
||||
int pad=description.length()/4;
|
||||
pad=(pad+1)*4;
|
||||
pad=pad-description.length();
|
||||
QString padding;
|
||||
padding.fill(' ',pad);
|
||||
description.append(padding);
|
||||
}
|
||||
if(!StartUpload(description.length(),OP_DFU::Descript,0))
|
||||
return OP_DFU::abort;
|
||||
QByteArray array=description.toAscii();
|
||||
if(!UploadData(description.length(),array))
|
||||
{
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
if(!EndOperation())
|
||||
{
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
int ret=StatusRequest();
|
||||
|
||||
if(debug)
|
||||
qDebug()<<"Upload description Status="<<ret;
|
||||
return (OP_DFU::Status)ret;
|
||||
}
|
||||
QString OP_DFU::DownloadDescription(int const & numberOfChars)
|
||||
{
|
||||
// enterDFU(devNumber);
|
||||
QByteArray arr=StartDownload(numberOfChars,Descript);
|
||||
QString str(arr);
|
||||
return str;
|
||||
|
||||
}
|
||||
void OP_DFU::test()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
int result;
|
||||
buf[0]=0x02;
|
||||
buf[1]=11;
|
||||
buf[2]=11;
|
||||
buf[63]=333;
|
||||
while(true)
|
||||
{
|
||||
buf[0]=0x02;
|
||||
++buf[1];
|
||||
++buf[2];
|
||||
++buf[63];
|
||||
hidHandle.send(0,buf,BUF_LEN,5000);
|
||||
result = hidHandle.receive(0,buf,BUF_LEN,5000);
|
||||
|
||||
qDebug()<<"Result="<<result;
|
||||
qDebug()<<(int)buf[0]<<":"<<(int)buf[1]<<":"<<(int)buf[2]<<":"<<(int)buf[63];
|
||||
}}
|
||||
|
||||
QByteArray OP_DFU::StartDownload(qint32 const & numberOfBytes, TransferTypes const & type)
|
||||
{
|
||||
int lastPacketCount;
|
||||
qint32 numberOfPackets=numberOfBytes/4/14;
|
||||
int pad=(numberOfBytes-numberOfPackets*4*14)/4;
|
||||
if(pad==0)
|
||||
{
|
||||
lastPacketCount=14;
|
||||
}
|
||||
else
|
||||
{
|
||||
++numberOfPackets;
|
||||
lastPacketCount=pad;
|
||||
}
|
||||
QByteArray ret;
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Download_Req;//DFU Command
|
||||
buf[2] = numberOfPackets>>24;//DFU Count
|
||||
buf[3] = numberOfPackets>>16;//DFU Count
|
||||
buf[4] = numberOfPackets>>8;//DFU Count
|
||||
buf[5] = numberOfPackets;//DFU Count
|
||||
buf[6] = (int)type;//DFU Data0
|
||||
buf[7] = lastPacketCount;//DFU Data1
|
||||
buf[8] = 1;//DFU Data2
|
||||
buf[9] = 1;//DFU Data3
|
||||
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
if(debug)
|
||||
qDebug() << "StartDownload:"<<numberOfPackets<<"packets"<<" Last Packet Size="<<lastPacketCount<<" "<<result << " bytes sent";
|
||||
float percentage;
|
||||
int laspercentage;
|
||||
for(qint32 x=0;x<numberOfPackets;++x)
|
||||
{
|
||||
percentage=(float)(x+1)/numberOfPackets*100;
|
||||
if(laspercentage!=(int)percentage)
|
||||
printProgBar((int)percentage,"DOWNLOADING");
|
||||
laspercentage=(int)percentage;
|
||||
|
||||
|
||||
// qDebug()<<"Status="<<StatusToString(StatusRequest());
|
||||
result = hidHandle.receive(0,buf,BUF_LEN,5000);
|
||||
if(debug)
|
||||
qDebug() << result << " bytes received"<<" Count="<<x<<"-"<<(int)buf[2]<<";"<<(int)buf[3]<<";"<<(int)buf[4]<<";"<<(int)buf[5]<<" Data="<<(int)buf[6]<<";"<<(int)buf[7]<<";"<<(int)buf[8]<<";"<<(int)buf[9];
|
||||
int size;
|
||||
if(x==numberOfPackets-1)
|
||||
size=lastPacketCount*4;
|
||||
else
|
||||
size=14*4;
|
||||
ret.append(buf+6,size);
|
||||
}
|
||||
cout<<"\n";
|
||||
StatusRequest();
|
||||
return ret;
|
||||
}
|
||||
void OP_DFU::ResetDevice(void)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Reset;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
}
|
||||
void OP_DFU::AbortOperation(void)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Abort_Operation;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
}
|
||||
void OP_DFU::JumpToApp()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::JumpFW;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
}
|
||||
OP_DFU::Status OP_DFU::StatusRequest()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Status_Request;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 10000);
|
||||
if(debug)
|
||||
qDebug() << result << " bytes sent";
|
||||
result = hidHandle.receive(0,buf,BUF_LEN,10000);
|
||||
if(debug)
|
||||
qDebug() << result << " bytes received";
|
||||
if(buf[1]==OP_DFU::Status_Rep)
|
||||
{
|
||||
return (OP_DFU::Status)buf[6];
|
||||
}
|
||||
else
|
||||
return OP_DFU::abort;
|
||||
|
||||
|
||||
}
|
||||
bool OP_DFU::findDevices()
|
||||
{
|
||||
devices.clear();
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Req_Capabilities;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 5000);
|
||||
if(result<1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result = hidHandle.receive(0,buf,BUF_LEN,5000);
|
||||
if(result<1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
numberOfDevices=buf[7];
|
||||
RWFlags=buf[8];
|
||||
RWFlags=RWFlags<<8 | buf[9];
|
||||
|
||||
|
||||
if(buf[1]==OP_DFU::Rep_Capabilities)
|
||||
{
|
||||
for(int x=0;x<numberOfDevices;++x)
|
||||
{
|
||||
device dev;
|
||||
dev.Readable=(bool)(RWFlags>>(x*2) & 1);
|
||||
dev.Writable=(bool)(RWFlags>>(x*2+1) & 1);
|
||||
devices.append(dev);
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Req_Capabilities;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = x+1;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 5000);
|
||||
result = hidHandle.receive(0,buf,BUF_LEN,5000);
|
||||
devices[x].ID=buf[9];
|
||||
devices[x].BL_Version=buf[7];
|
||||
devices[x].SizeOfDesc=buf[8];
|
||||
|
||||
quint32 aux;
|
||||
aux=(quint8)buf[10];
|
||||
aux=aux<<8 |(quint8)buf[11];
|
||||
aux=aux<<8 |(quint8)buf[12];
|
||||
aux=aux<<8 |(quint8)buf[13];
|
||||
|
||||
devices[x].FW_CRC=aux;
|
||||
|
||||
|
||||
aux=(quint8)buf[2];
|
||||
aux=aux<<8 |(quint8)buf[3];
|
||||
aux=aux<<8 |(quint8)buf[4];
|
||||
aux=aux<<8 |(quint8)buf[5];
|
||||
devices[x].SizeOfCode=aux;
|
||||
}
|
||||
if(debug)
|
||||
{
|
||||
qDebug()<<"Found "<<numberOfDevices;
|
||||
for(int x=0;x<numberOfDevices;++x)
|
||||
{
|
||||
qDebug()<<"Device #"<<x+1;
|
||||
qDebug()<<"Device ID="<<devices[x].ID;
|
||||
qDebug()<<"Device Readable="<<devices[x].Readable;
|
||||
qDebug()<<"Device Writable="<<devices[x].Writable;
|
||||
qDebug()<<"Device SizeOfCode="<<devices[x].SizeOfCode;
|
||||
qDebug()<<"Device SizeOfDesc="<<devices[x].SizeOfDesc;
|
||||
qDebug()<<"BL Version="<<devices[x].BL_Version;
|
||||
qDebug()<<"FW CRC="<<devices[x].FW_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool OP_DFU::EndOperation()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
buf[0] =0x02;//reportID
|
||||
buf[1] = OP_DFU::Op_END;//DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
buf[5] = 0;
|
||||
buf[6] = 0;
|
||||
buf[7] = 0;
|
||||
buf[8] = 0;
|
||||
buf[9] = 0;
|
||||
|
||||
int result = hidHandle.send(0,buf, BUF_LEN, 5000);
|
||||
// hidHandle.receive(0,buf,BUF_LEN,5000);
|
||||
if(debug)
|
||||
qDebug() << result << " bytes sent";
|
||||
if(result>0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
OP_DFU::Status OP_DFU::UploadFirmware(const QString &sfile, const bool &verify,int device)
|
||||
{
|
||||
OP_DFU::Status ret;
|
||||
cout<<"Starting Firmware Uploading...\n";
|
||||
QFile file(sfile);
|
||||
//QFile file("in.txt");
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if(debug)
|
||||
qDebug()<<"Cant open file";
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
QByteArray arr=file.readAll();
|
||||
|
||||
if(debug)
|
||||
qDebug()<<"Bytes Loaded="<<arr.length();
|
||||
if(arr.length()%4!=0)
|
||||
{
|
||||
int pad=arr.length()/4;
|
||||
++pad;
|
||||
pad=pad*4;
|
||||
pad=pad-arr.length();
|
||||
arr.append(QByteArray(pad,255));
|
||||
}
|
||||
if(devices[device].SizeOfCode<arr.length())
|
||||
{
|
||||
cout<<"ERROR file to big for device\n";
|
||||
return OP_DFU::abort;;
|
||||
}
|
||||
quint32 crc=CRCFromQBArray(arr,devices[device].SizeOfCode);
|
||||
cout<<"NEW FIRMWARE CRC="<<crc<<"\n";
|
||||
if(!StartUpload(arr.length(),FW,crc))
|
||||
{
|
||||
if(debug)
|
||||
{
|
||||
qDebug()<<"StartUpload failed";
|
||||
OP_DFU::Status ret=StatusRequest();
|
||||
qDebug()<<"StartUpload returned:"<< StatusToString(ret);
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
cout<<"Erasing memory\n";
|
||||
if(StatusRequest()==OP_DFU::abort) return OP_DFU::abort;
|
||||
for(int x=0;x<3;++x)
|
||||
{
|
||||
OP_DFU::Status ret=StatusRequest();
|
||||
if(debug)
|
||||
qDebug()<<"Erase returned:"<<StatusToString(ret);
|
||||
if (ret==OP_DFU::uploading)
|
||||
break;
|
||||
else
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
if(!UploadData(arr.length(),arr))
|
||||
{
|
||||
if(debug)
|
||||
{
|
||||
qDebug()<<"Upload failed (upload data)";
|
||||
OP_DFU::Status ret=StatusRequest();
|
||||
qDebug()<<"StartUpload returned:"<<StatusToString(ret);
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
if(!EndOperation())
|
||||
{
|
||||
if(debug)
|
||||
{
|
||||
qDebug()<<"Upload failed (end operation)";
|
||||
OP_DFU::Status ret=StatusRequest();
|
||||
qDebug()<<"StartUpload returned:"<<StatusToString(ret);
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
ret=StatusRequest();
|
||||
if(ret==OP_DFU::Last_operation_Success)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if(verify)
|
||||
{
|
||||
cout<<"Starting code verification\n";
|
||||
if(arr==StartDownload(arr.length(),OP_DFU::FW))
|
||||
cout<<"Verify:PASSED\n";
|
||||
else
|
||||
{
|
||||
cout<<"Verify:FAILED\n";
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if(debug)
|
||||
qDebug()<<"Status="<<ret;
|
||||
cout<<"Firmware Uploading succeeded\n";
|
||||
return ret;
|
||||
}
|
||||
OP_DFU::Status OP_DFU::CompareFirmware(const QString &sfile, const CompareType &type,int device)
|
||||
{
|
||||
cout<<"Starting Firmware Compare...\n";
|
||||
QFile file(sfile);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if(debug)
|
||||
qDebug()<<"Cant open file";
|
||||
return OP_DFU::abort;
|
||||
}
|
||||
QByteArray arr=file.readAll();
|
||||
|
||||
if(debug)
|
||||
qDebug()<<"Bytes Loaded="<<arr.length();
|
||||
if(arr.length()%4!=0)
|
||||
{
|
||||
int pad=arr.length()/4;
|
||||
++pad;
|
||||
pad=pad*4;
|
||||
pad=pad-arr.length();
|
||||
arr.append(QByteArray(pad,255));
|
||||
}
|
||||
if(type==OP_DFU::crccompare)
|
||||
{
|
||||
quint32 crc=CRCFromQBArray(arr,devices[device].SizeOfCode);
|
||||
if(crc==devices[device].FW_CRC)
|
||||
{
|
||||
cout<<"Compare Successfull CRC MATCH!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"Compare failed CRC DONT MATCH!\n";
|
||||
}
|
||||
return StatusRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(arr==StartDownload(arr.length(),OP_DFU::FW))
|
||||
{
|
||||
cout<<"Compare Successfull ALL Bytes MATCH!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout<<"Compare failed Bytes DONT MATCH!\n";
|
||||
}
|
||||
return StatusRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void OP_DFU::CopyWords(char *source, char *destination, int count)
|
||||
{
|
||||
for (int x=0;x<count;x=x+4)
|
||||
{
|
||||
*(destination+x)=source[x+3];
|
||||
*(destination+x+1)=source[x+2];
|
||||
*(destination+x+2)=source[x+1];
|
||||
*(destination+x+3)=source[x+0];
|
||||
}
|
||||
}
|
||||
QString OP_DFU::StatusToString(OP_DFU::Status const & status)
|
||||
{
|
||||
switch(status)
|
||||
{
|
||||
case DFUidle:
|
||||
return "DFUidle";
|
||||
case uploading:
|
||||
return "";
|
||||
case wrong_packet_received:
|
||||
return "wrong_packet_received";
|
||||
case too_many_packets:
|
||||
return "too_many_packets";
|
||||
case too_few_packets:
|
||||
return "too_few_packets";
|
||||
case Last_operation_Success:
|
||||
return "Last_operation_Success";
|
||||
case downloading:
|
||||
return "downloading";
|
||||
case idle:
|
||||
return "idle";
|
||||
case Last_operation_failed:
|
||||
return "Last_operation_failed";
|
||||
case outsideDevCapabilities:
|
||||
return "outsideDevCapabilities";
|
||||
case CRC_Fail:
|
||||
return "CRC check FAILED";
|
||||
case failed_jump:
|
||||
return "Jmp to user FW failed";
|
||||
case abort:
|
||||
return "abort";
|
||||
case uploadingStarting:
|
||||
return "Uploading Starting";
|
||||
default:
|
||||
return "unknown";
|
||||
|
||||
}
|
||||
}
|
||||
void OP_DFU::printProgBar( int const & percent,QString const& label){
|
||||
std::string bar;
|
||||
|
||||
for(int i = 0; i < 50; i++){
|
||||
if( i < (percent/2)){
|
||||
bar.replace(i,1,"=");
|
||||
}else if( i == (percent/2)){
|
||||
bar.replace(i,1,">");
|
||||
}else{
|
||||
bar.replace(i,1," ");
|
||||
}
|
||||
}
|
||||
|
||||
std::cout<< "\r"<<label.toLatin1().data()<< "[" << bar << "] ";
|
||||
std::cout.width( 3 );
|
||||
std::cout<< percent << "% " << std::flush;
|
||||
}
|
||||
quint32 OP_DFU::CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer)
|
||||
{
|
||||
//Size = Size >> 2; // /4 Size passed in as a byte count, assumed to be a multiple of 4
|
||||
|
||||
while(Size--)
|
||||
{
|
||||
static const quint32 CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
|
||||
0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,
|
||||
0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD };
|
||||
|
||||
Crc = Crc ^ *((quint32 *)Buffer); // Apply all 32-bits
|
||||
|
||||
Buffer += 1;
|
||||
|
||||
// Process 32-bits, 4 at a time, or 8 rounds
|
||||
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // 0x04C11DB7 Polynomial used in STM32
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
|
||||
Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
|
||||
}
|
||||
|
||||
return(Crc);
|
||||
}
|
||||
quint32 OP_DFU::CRCFromQBArray(QByteArray array, quint32 Size)
|
||||
{
|
||||
int pad=Size-array.length();
|
||||
array.append(QByteArray(pad,255));
|
||||
quint32 t[Size/4];
|
||||
for(int x=0;x<array.length()/4;x++)
|
||||
{
|
||||
quint32 aux=0;
|
||||
aux=(char)array[x*4+3]&0xFF;
|
||||
aux=aux<<8;
|
||||
aux+=(char)array[x*4+2]&0xFF;
|
||||
aux=aux<<8;
|
||||
aux+=(char)array[x*4+1]&0xFF;
|
||||
aux=aux<<8;
|
||||
aux+=(char)array[x*4+0]&0xFF;
|
||||
t[x]=aux;
|
||||
}
|
||||
return CRC32WideFast(0xFFFFFFFF,Size/4,(quint32*)t);
|
||||
}
|
139
ground/src/plugins/uploader/op_dfu.h
Normal file
139
ground/src/plugins/uploader/op_dfu.h
Normal file
@ -0,0 +1,139 @@
|
||||
#ifndef OP_DFU_H
|
||||
#define OP_DFU_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <rawhid/pjrc_rawhid.h>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QList>
|
||||
#include <iostream>
|
||||
#include "delay.h"
|
||||
using namespace std;
|
||||
#define BUF_LEN 64
|
||||
|
||||
//Command Line Options
|
||||
#define DOWNLOAD "-dn" //done
|
||||
#define DEVICE "-d" //done
|
||||
//#define DOWNDESCRIPTION "-dd" //done
|
||||
#define PROGRAMFW "-p" //done
|
||||
#define PROGRAMDESC "-w" //done
|
||||
#define VERIFY "-v" //done
|
||||
#define COMPARECRC "-cc"
|
||||
#define COMPAREALL "-ca"
|
||||
#define STATUSREQUEST "-s" //done
|
||||
#define LISTDEVICES "-ls" //done
|
||||
#define RESET "-r"
|
||||
#define JUMP "-j"
|
||||
|
||||
class OP_DFU
|
||||
{
|
||||
public:
|
||||
enum TransferTypes
|
||||
{
|
||||
FW,
|
||||
Descript
|
||||
};
|
||||
enum CompareType
|
||||
{
|
||||
crccompare,
|
||||
bytetobytecompare
|
||||
};
|
||||
|
||||
enum Status
|
||||
{
|
||||
DFUidle,//0
|
||||
uploading,//1
|
||||
wrong_packet_received,//2
|
||||
too_many_packets,//3
|
||||
too_few_packets,//4
|
||||
Last_operation_Success,//5
|
||||
downloading,//6
|
||||
idle,//7
|
||||
Last_operation_failed,//8
|
||||
uploadingStarting,//9
|
||||
outsideDevCapabilities,//10
|
||||
CRC_Fail,//11
|
||||
failed_jump,//12
|
||||
abort//13
|
||||
|
||||
};
|
||||
enum Actions
|
||||
{
|
||||
actionProgram,
|
||||
actionProgramAndVerify,
|
||||
actionDownload,
|
||||
actionCompareAll,
|
||||
actionCompareCrc,
|
||||
actionListDevs,
|
||||
actionStatusReq,
|
||||
actionReset,
|
||||
actionJump
|
||||
};
|
||||
|
||||
enum Commands
|
||||
{
|
||||
Reserved,
|
||||
Req_Capabilities,
|
||||
Rep_Capabilities,
|
||||
EnterDFU,
|
||||
JumpFW,
|
||||
Reset,
|
||||
Abort_Operation,
|
||||
Upload,
|
||||
Op_END,
|
||||
Download_Req,
|
||||
Download,
|
||||
Status_Request,
|
||||
Status_Rep,
|
||||
|
||||
};
|
||||
struct device
|
||||
{
|
||||
int ID;
|
||||
quint32 FW_CRC;
|
||||
int BL_Version;
|
||||
int SizeOfDesc;
|
||||
quint32 SizeOfCode;
|
||||
bool Readable;
|
||||
bool Writable;
|
||||
};
|
||||
|
||||
void JumpToApp();
|
||||
void ResetDevice(void);
|
||||
bool enterDFU(int const &devNumber);
|
||||
bool StartUpload(qint32 const &numberOfBytes, TransferTypes const & type,quint32 crc);
|
||||
bool UploadData(qint32 const & numberOfPackets,QByteArray & data);
|
||||
Status UploadDescription(QString & description);
|
||||
Status UploadFirmware(const QString &sfile, const bool &verify,int device);
|
||||
Status StatusRequest();
|
||||
bool EndOperation();
|
||||
void printProgBar( int const & percent,QString const& label);
|
||||
QString DownloadDescription(int const & numberOfChars);
|
||||
QByteArray StartDownload(qint32 const & numberOfBytes, TransferTypes const & type);
|
||||
bool SaveByteArrayToFile(QString const & file,QByteArray const &array);
|
||||
void CopyWords(char * source, char* destination, int count);
|
||||
// QByteArray DownloadData(int devNumber,int numberOfPackets);
|
||||
OP_DFU(bool debug);
|
||||
bool findDevices();
|
||||
QList<device> devices;
|
||||
int numberOfDevices;
|
||||
QString StatusToString(OP_DFU::Status const & status);
|
||||
OP_DFU::Status CompareFirmware(const QString &sfile, const CompareType &type,int device);
|
||||
quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer);
|
||||
quint32 CRCFromQBArray(QByteArray array, quint32 Size);
|
||||
void test();
|
||||
int send_delay;
|
||||
bool use_delay;
|
||||
void AbortOperation(void);
|
||||
private:
|
||||
bool debug;
|
||||
int RWFlags;
|
||||
|
||||
pjrc_rawhid hidHandle;
|
||||
int setStartBit(int command){return command|0x20;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // OP_DFU_H
|
@ -1,19 +1,26 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = Uploader
|
||||
include(../../openpilotgcsplugin.pri)
|
||||
include(../../plugins/coreplugin/coreplugin.pri)
|
||||
include(../../libs/qextserialport/qextserialport.pri)
|
||||
include(../../libs/qymodem/qymodem.pri)
|
||||
HEADERS += uploadergadget.h \
|
||||
uploadergadgetconfiguration.h \
|
||||
uploadergadgetfactory.h \
|
||||
uploadergadgetoptionspage.h \
|
||||
uploadergadgetwidget.h \
|
||||
uploaderplugin.h
|
||||
SOURCES += uploadergadget.cpp \
|
||||
uploadergadgetconfiguration.cpp \
|
||||
uploadergadgetfactory.cpp \
|
||||
uploadergadgetoptionspage.cpp \
|
||||
uploadergadgetwidget.cpp \
|
||||
uploaderplugin.cpp
|
||||
OTHER_FILES += Uploader.pluginspec
|
||||
TEMPLATE = lib
|
||||
TARGET = Uploader
|
||||
include(../../openpilotgcsplugin.pri)
|
||||
include(../../plugins/coreplugin/coreplugin.pri)
|
||||
include(../../libs/qextserialport/qextserialport.pri)
|
||||
include(../../libs/qymodem/qymodem.pri)
|
||||
HEADERS += uploadergadget.h \
|
||||
uploadergadgetconfiguration.h \
|
||||
uploadergadgetfactory.h \
|
||||
uploadergadgetoptionspage.h \
|
||||
uploadergadgetwidget.h \
|
||||
uploaderplugin.h \
|
||||
op_dfu.h \
|
||||
delay.h
|
||||
SOURCES += uploadergadget.cpp \
|
||||
uploadergadgetconfiguration.cpp \
|
||||
uploadergadgetfactory.cpp \
|
||||
uploadergadgetoptionspage.cpp \
|
||||
uploadergadgetwidget.cpp \
|
||||
uploaderplugin.cpp \
|
||||
op_dfu.cpp \
|
||||
delay.cpp
|
||||
OTHER_FILES += Uploader.pluginspec
|
||||
|
||||
FORMS += \
|
||||
uploader.ui
|
||||
|
112
ground/src/plugins/uploader/uploader.ui
Normal file
112
ground/src/plugins/uploader/uploader.ui
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UploaderWidget</class>
|
||||
<widget class="QWidget" name="UploaderWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>580</width>
|
||||
<height>350</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,3,1">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="haltButton">
|
||||
<property name="toolTip">
|
||||
<string>Tells the mainboard to go down
|
||||
to bootloader mode.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Halt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="bootButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Boots the system.
|
||||
Only enabled if the system is halted.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Boot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetButton">
|
||||
<property name="toolTip">
|
||||
<string>Reset the system.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="boardStatus">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="systemElements">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Mainboard</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Please connect your board through USB for firmware upload.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -28,52 +28,10 @@
|
||||
|
||||
UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
m_config = new Ui_UploaderWidget();
|
||||
m_config->setupUi(this);
|
||||
|
||||
//main layout
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
//choose file layout and widget
|
||||
QHBoxLayout *FileLayout = new QHBoxLayout;
|
||||
QWidget *FileWidget = new QWidget;
|
||||
FileWidget->setLayout(FileLayout);
|
||||
openFileNameLE=new QLineEdit();
|
||||
QPushButton* loadfile = new QPushButton("Load File");
|
||||
loadfile->setMaximumWidth(80);
|
||||
FileLayout->addWidget(openFileNameLE);
|
||||
FileLayout->addWidget(loadfile);
|
||||
|
||||
//send file layout and widget
|
||||
QHBoxLayout *SendLayout = new QHBoxLayout;
|
||||
QWidget *SendWidget = new QWidget;
|
||||
SendWidget->setLayout(SendLayout);
|
||||
progressBar=new QProgressBar();
|
||||
progressBar->setMaximum(100);
|
||||
QPushButton* sendBt = new QPushButton("Send");
|
||||
sendBt->setMaximumWidth(80);
|
||||
SendLayout->addWidget(progressBar);
|
||||
SendLayout->addWidget(sendBt);
|
||||
|
||||
//status layout and widget
|
||||
QHBoxLayout *StatusLayout = new QHBoxLayout;
|
||||
QWidget *StatusWidget = new QWidget;
|
||||
StatusWidget->setLayout(StatusLayout);
|
||||
status=new QLabel();
|
||||
StatusLayout->addWidget(status);
|
||||
|
||||
//add partial widgets to main widget
|
||||
layout->addWidget(FileWidget);
|
||||
layout->addWidget(SendWidget);
|
||||
layout->addWidget(StatusWidget);
|
||||
setLayout(layout);
|
||||
|
||||
//connect signals to slots
|
||||
|
||||
//fires when the user presses file button
|
||||
connect(loadfile, SIGNAL(clicked(bool)),
|
||||
this,SLOT(setOpenFileName()));
|
||||
//fires when the user presses send button
|
||||
connect(sendBt, SIGNAL(clicked(bool)),
|
||||
this,SLOT(send()));
|
||||
}
|
||||
//user pressed send, send file using a new thread with qymodem library
|
||||
void UploaderGadgetWidget::send()
|
||||
|
@ -28,22 +28,20 @@
|
||||
#ifndef UPLOADERGADGETWIDGET_H
|
||||
#define UPLOADERGADGETWIDGET_H
|
||||
|
||||
//#include "qmapcontrol/qmapcontrol.h"
|
||||
#include "ui_uploader.h"
|
||||
#include <QtGui/QWidget>
|
||||
#include <qextserialport/src/qextserialport.h>
|
||||
#include <qymodem/src/qymodemsend.h>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QThread>
|
||||
# include <QProgressBar>
|
||||
#include <QProgressBar>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
//using namespace qmapcontrol;
|
||||
|
||||
class Ui_UploaderWidget;
|
||||
|
||||
class UploaderGadgetWidget : public QWidget
|
||||
{
|
||||
@ -57,6 +55,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
Ui_UploaderWidget *m_config;
|
||||
|
||||
QLineEdit* openFileNameLE;
|
||||
QextSerialPort *Port;
|
||||
|
Loading…
x
Reference in New Issue
Block a user