mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-19 04:52:12 +01:00
Merged in filnet/librepilot/LP-458_uploadtool_fixes (pull request #385)
LP-458 uploadtool fixes Approved-by: Philippe Renon <philippe_renon@yahoo.fr> Approved-by: Lalanne Laurent <f5soh@free.fr> Approved-by: Alessio Morale <alessiomorale@gmail.com>
This commit is contained in:
commit
27d3fb0751
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file common.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -23,10 +24,11 @@
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/#ifndef COMMON_H
|
||||
*/
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
enum decodeState_ {
|
||||
enum DecodeState {
|
||||
decode_len1_e = 0,
|
||||
decode_seqNo_e,
|
||||
decode_data_e,
|
||||
@ -34,10 +36,10 @@ enum decodeState_ {
|
||||
decode_crc2_e,
|
||||
decode_idle_e
|
||||
};
|
||||
|
||||
enum ReceiveState {
|
||||
state_escaped_e = 0,
|
||||
state_unescaped_e
|
||||
};
|
||||
|
||||
|
||||
#endif // COMMON_H
|
||||
|
@ -1,20 +1,51 @@
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include "../../../libs/qextserialport/src/qextserialport.h"
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file main.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
* @{
|
||||
* @brief The USB and Serial protocol uploader plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "qssp.h"
|
||||
#include "port.h"
|
||||
#include "qsspt.h"
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
#include "../../../libs/qextserialport/src/qextserialport.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
|
||||
#define MAX_PACKET_DATA_LEN 255
|
||||
#define MAX_PACKET_BUF_SIZE (1 + 1 + 255 + 2)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE];
|
||||
uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE];
|
||||
|
||||
port *info;
|
||||
PortSettings settings;
|
||||
|
||||
settings.BaudRate = BAUD57600;
|
||||
settings.DataBits = DATA_8;
|
||||
settings.FlowControl = FLOW_OFF;
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file port.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -25,15 +26,15 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "port.h"
|
||||
#include "delay.h"
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QDebug>
|
||||
port::port(QString name, bool debug) : debug(debug), mstatus(port::closed)
|
||||
|
||||
port::port(QString name, bool debug) : mstatus(port::closed), debug(debug)
|
||||
{
|
||||
timer.start();
|
||||
sport = new QSerialPort();
|
||||
sport->setPortName(name);
|
||||
sport = new QSerialPort(name, this);
|
||||
if (sport->open(QIODevice::ReadWrite)) {
|
||||
sport->setReadBufferSize(0);
|
||||
if (sport->setBaudRate(QSerialPort::Baud57600)
|
||||
&& sport->setDataBits(QSerialPort::Data8)
|
||||
&& sport->setParity(QSerialPort::NoParity)
|
||||
@ -41,7 +42,6 @@ port::port(QString name, bool debug) : debug(debug), mstatus(port::closed)
|
||||
&& sport->setFlowControl(QSerialPort::NoFlowControl)) {
|
||||
mstatus = port::open;
|
||||
}
|
||||
// sport->setDtr();
|
||||
} else {
|
||||
qDebug() << sport->error();
|
||||
mstatus = port::error;
|
||||
@ -62,6 +62,7 @@ int16_t port::pfSerialRead(void)
|
||||
{
|
||||
char c[1];
|
||||
|
||||
// TODO why the wait ? (gcs uploader dfu does not have it)
|
||||
sport->waitForBytesWritten(1);
|
||||
if (sport->bytesAvailable() || sport->waitForReadyRead(0)) {
|
||||
sport->read(c, 1);
|
||||
@ -72,7 +73,9 @@ int16_t port::pfSerialRead(void)
|
||||
}
|
||||
rxDebugBuff.append(c[0]);
|
||||
}
|
||||
} else { return -1; }
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return (uint8_t)c[0];
|
||||
}
|
||||
|
||||
@ -89,6 +92,7 @@ void port::pfSerialWrite(uint8_t c)
|
||||
}
|
||||
txDebugBuff.append(cc[0]);
|
||||
}
|
||||
// TODO why the wait ? (gcs uploader dfu does not have it)
|
||||
sport->waitForBytesWritten(1);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file port.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,19 +27,30 @@
|
||||
*/
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
#include <stdint.h>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class port {
|
||||
#include <QObject>
|
||||
#include <QTime>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class QSerialPort;
|
||||
|
||||
class port : public QObject {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
enum portstatus { open, closed, error };
|
||||
|
||||
port(QString name, bool debug);
|
||||
virtual ~port();
|
||||
portstatus status();
|
||||
|
||||
virtual int16_t pfSerialRead(void); // function to read a character from the serial input stream
|
||||
virtual void pfSerialWrite(uint8_t); // function to write a byte to be sent out the serial port
|
||||
virtual uint32_t pfGetTime(void);
|
||||
|
||||
uint8_t retryCount; // how many times have we tried to transmit the 'send' packet
|
||||
uint8_t maxRetryCount; // max. times to try to transmit the 'send' packet
|
||||
uint16_t max_retry; // Maximum number of retrys for a single transmit.
|
||||
@ -54,25 +66,25 @@ public:
|
||||
uint8_t *rxBuf; // receive buffer. Used to store data as a packet is received.
|
||||
uint16_t sendSynch; // flag to indicate that we should send a synchronize packet to the host
|
||||
// this is required when switching from the application to the bootloader
|
||||
// and vice-versa. This fixes the firwmare download timeout.
|
||||
// when this flag is set to true, the next time we send a packet we will first // send a synchronize packet.
|
||||
ReceiveState InputState;
|
||||
decodeState_ DecodeState;
|
||||
// and vice-versa. This fixes the firmware download timeout.
|
||||
// when this flag is set to true, the next time we send a packet we will first
|
||||
// send a synchronize packet.
|
||||
ReceiveState inputState;
|
||||
DecodeState decodeState;
|
||||
uint16_t SendState;
|
||||
uint16_t crc;
|
||||
uint32_t RxError;
|
||||
uint32_t TxError;
|
||||
uint16_t flags;
|
||||
port(QString name, bool debug);
|
||||
virtual ~port();
|
||||
portstatus status();
|
||||
|
||||
private:
|
||||
bool debug;
|
||||
QByteArray rxDebugBuff;
|
||||
QByteArray txDebugBuff;
|
||||
portstatus mstatus;
|
||||
QTime timer;
|
||||
QSerialPort *sport;
|
||||
|
||||
bool debug;
|
||||
QByteArray rxDebugBuff;
|
||||
QByteArray txDebugBuff;
|
||||
};
|
||||
|
||||
#endif // PORT_H
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qssp.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,12 +27,12 @@
|
||||
*/
|
||||
#include "qssp.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/** PRIVATE DEFINITIONS **/
|
||||
#define SYNC 225 // Sync character used in Serial Protocol
|
||||
#define ESC 224 // ESC character used in Serial Protocol
|
||||
@ -143,8 +144,8 @@ void qssp::ssp_Init(const PortConfig_t *const info)
|
||||
thisport->rxSeqNo = 255;
|
||||
thisport->txSeqNo = 255;
|
||||
thisport->SendState = SSP_IDLE;
|
||||
thisport->InputState = (ReceiveState)0;
|
||||
thisport->DecodeState = (decodeState_)0;
|
||||
thisport->inputState = (ReceiveState)0;
|
||||
thisport->decodeState = (DecodeState)0;
|
||||
thisport->TxError = 0;
|
||||
thisport->RxError = 0;
|
||||
thisport->txSeqNo = 0;
|
||||
@ -174,7 +175,7 @@ int16_t qssp::ssp_SendProcess()
|
||||
sf_SetSendTimeout();
|
||||
value = SSP_TX_WAITING;
|
||||
} else {
|
||||
// Give up, # of trys has exceded the limit
|
||||
// Give up, # of tries has exceeded the limit
|
||||
value = SSP_TX_TIMEOUT;
|
||||
CLEARBIT(thisport->flags, ACK_RECEIVED);
|
||||
thisport->SendState = SSP_IDLE;
|
||||
@ -258,6 +259,7 @@ uint16_t qssp::ssp_SendDataBlock(uint8_t *data, uint16_t length)
|
||||
uint16_t retval = FALSE;
|
||||
|
||||
packet_status = ssp_SendData(data, length); // send the data
|
||||
// TODO the loop is non blocking and will spin as fast as the CPU allows
|
||||
while (packet_status == SSP_TX_WAITING) { // check the status
|
||||
(void)ssp_ReceiveProcess(); // process any bytes received.
|
||||
packet_status = ssp_SendProcess(); // check the send status
|
||||
@ -343,7 +345,7 @@ int16_t qssp::ssp_SendData(const uint8_t *data, const uint16_t length)
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Attempts to synchronize the sequence numbers with the other end of the connectin.
|
||||
* \brief Attempts to synchronize the sequence numbers with the other end of the connection.
|
||||
* \param thisport = which port to use
|
||||
* \return true = success
|
||||
* \return false = failed to receive an ACK to our synch request
|
||||
@ -374,7 +376,7 @@ uint16_t qssp::ssp_Synchronise()
|
||||
packet_status = ssp_SendData(NULL, 0);
|
||||
#endif
|
||||
while (packet_status == SSP_TX_WAITING) { // we loop until we time out.
|
||||
(void)ssp_ReceiveProcess(); // do the receive process
|
||||
ssp_ReceiveProcess(); // do the receive process
|
||||
packet_status = ssp_SendProcess(); // do the send process
|
||||
}
|
||||
thisport->sendSynch = FALSE;
|
||||
@ -391,7 +393,6 @@ uint16_t qssp::ssp_Synchronise()
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -417,7 +418,6 @@ void qssp::sf_SendPacket()
|
||||
thisport->retryCount++;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief converts data to transport layer protocol packet format.
|
||||
* \param txbuf = buffer to use when forming the packet
|
||||
@ -603,20 +603,20 @@ int16_t qssp::sf_ReceiveState(uint8_t c)
|
||||
{
|
||||
int16_t retval = SSP_RX_RECEIVING;
|
||||
|
||||
switch (thisport->InputState) {
|
||||
switch (thisport->inputState) {
|
||||
case state_unescaped_e:
|
||||
if (c == SYNC) {
|
||||
thisport->DecodeState = decode_len1_e;
|
||||
thisport->decodeState = decode_len1_e;
|
||||
} else if (c == ESC) {
|
||||
thisport->InputState = state_escaped_e;
|
||||
thisport->inputState = state_escaped_e;
|
||||
} else {
|
||||
retval = sf_DecodeState(c);
|
||||
}
|
||||
break; // end of unescaped state.
|
||||
case state_escaped_e:
|
||||
thisport->InputState = state_unescaped_e;
|
||||
thisport->inputState = state_unescaped_e;
|
||||
if (c == SYNC) {
|
||||
thisport->DecodeState = decode_len1_e;
|
||||
thisport->decodeState = decode_len1_e;
|
||||
} else if (c == ESC_SYNC) {
|
||||
retval = sf_DecodeState(SYNC);
|
||||
} else {
|
||||
@ -653,20 +653,26 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
{
|
||||
int16_t retval;
|
||||
|
||||
switch (thisport->DecodeState) {
|
||||
switch (thisport->decodeState) {
|
||||
case decode_idle_e:
|
||||
// 'c' is ignored in this state as the only way to leave the idle state is
|
||||
// recognition of the SYNC byte in the sf_ReceiveState function.
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
case decode_len1_e:
|
||||
if (c == 0) {
|
||||
thisport->decodeState = decode_idle_e;
|
||||
thisport->RxError++;
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
}
|
||||
thisport->rxBuf[LENGTH] = c;
|
||||
thisport->rxBufLen = c;
|
||||
if (thisport->rxBufLen <= thisport->rxBufSize) {
|
||||
thisport->DecodeState = decode_seqNo_e;
|
||||
thisport->decodeState = decode_seqNo_e;
|
||||
retval = SSP_RX_RECEIVING;
|
||||
} else {
|
||||
thisport->DecodeState = decode_idle_e;
|
||||
thisport->decodeState = decode_idle_e;
|
||||
retval = SSP_RX_IDLE;
|
||||
}
|
||||
break;
|
||||
@ -678,9 +684,9 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
if (thisport->rxBufLen > 0) {
|
||||
thisport->DecodeState = decode_data_e;
|
||||
thisport->decodeState = decode_data_e;
|
||||
} else {
|
||||
thisport->DecodeState = decode_crc1_e;
|
||||
thisport->decodeState = decode_crc1_e;
|
||||
}
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
@ -688,17 +694,17 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
thisport->rxBuf[(thisport->rxBufPos)++] = c;
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
if (thisport->rxBufPos == (thisport->rxBufLen + 2)) {
|
||||
thisport->DecodeState = decode_crc1_e;
|
||||
thisport->decodeState = decode_crc1_e;
|
||||
}
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_crc1_e:
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
thisport->DecodeState = decode_crc2_e;
|
||||
thisport->decodeState = decode_crc2_e;
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_crc2_e:
|
||||
thisport->DecodeState = decode_idle_e;
|
||||
thisport->decodeState = decode_idle_e;
|
||||
// verify the CRC value for the packet
|
||||
if (sf_crc16(thisport->crc, c) == 0) {
|
||||
// TODO shouldn't the return value of sf_ReceivePacket() be checked?
|
||||
@ -710,7 +716,7 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
thisport->DecodeState = decode_idle_e; // unknown state so reset to idle state and wait for the next start of a packet.
|
||||
thisport->decodeState = decode_idle_e; // unknown state so reset to idle state and wait for the next start of a packet.
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
}
|
||||
@ -794,6 +800,7 @@ int16_t qssp::sf_ReceivePacket()
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
qssp::qssp(port *info, bool debug) : debug(debug)
|
||||
{
|
||||
thisport = info;
|
||||
@ -808,13 +815,14 @@ qssp::qssp(port *info, bool debug) : debug(debug)
|
||||
thisport->rxSeqNo = 255;
|
||||
thisport->txSeqNo = 255;
|
||||
thisport->SendState = SSP_IDLE;
|
||||
thisport->InputState = (ReceiveState)0;
|
||||
thisport->DecodeState = (decodeState_)0;
|
||||
thisport->inputState = (ReceiveState)0;
|
||||
thisport->decodeState = (DecodeState)0;
|
||||
thisport->TxError = 0;
|
||||
thisport->RxError = 0;
|
||||
thisport->txSeqNo = 0;
|
||||
thisport->rxSeqNo = 0;
|
||||
}
|
||||
|
||||
void qssp::pfCallBack(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qssp.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,9 +27,12 @@
|
||||
*/
|
||||
#ifndef QSSP_H
|
||||
#define QSSP_H
|
||||
#include <stdint.h>
|
||||
#include "port.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "port.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** LOCAL DEFINITIONS **/
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
@ -39,6 +43,7 @@
|
||||
#endif
|
||||
|
||||
#define SPP_USES_CRC
|
||||
|
||||
#define SSP_TX_IDLE 0 // not expecting a ACK packet (no current transmissions in progress)
|
||||
#define SSP_TX_WAITING 1 // waiting for a valid ACK to arrive
|
||||
#define SSP_TX_TIMEOUT 2 // failed to receive a valid ACK in the timeout period, after retrying.
|
||||
@ -56,7 +61,6 @@
|
||||
#define SSP_RX_ACK 6
|
||||
#define SSP_RX_SYNCH 7
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t *pbuff;
|
||||
uint16_t length;
|
||||
@ -74,42 +78,41 @@ typedef struct {
|
||||
// function returns time in number of seconds that has elapsed from a given reference point
|
||||
} PortConfig_t;
|
||||
|
||||
|
||||
/** Public Data **/
|
||||
|
||||
|
||||
/** EXTERNAL FUNCTIONS **/
|
||||
|
||||
class qssp {
|
||||
private:
|
||||
port *thisport;
|
||||
decodeState_ DecodeState_t;
|
||||
/** PRIVATE FUNCTIONS **/
|
||||
bool debug;
|
||||
|
||||
// static void sf_SendSynchPacket( Port_t *thisport );
|
||||
uint16_t sf_crc16(uint16_t crc, uint8_t data);
|
||||
uint16_t sf_crc16(uint16_t crc, uint8_t data);
|
||||
void sf_write_byte(uint8_t c);
|
||||
void sf_SetSendTimeout();
|
||||
uint16_t sf_CheckTimeout();
|
||||
uint16_t sf_CheckTimeout();
|
||||
int16_t sf_DecodeState(uint8_t c);
|
||||
int16_t sf_ReceiveState(uint8_t c);
|
||||
|
||||
void sf_SendPacket();
|
||||
void sf_SendAckPacket(uint8_t seqNumber);
|
||||
void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo);
|
||||
void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo);
|
||||
int16_t sf_ReceivePacket();
|
||||
uint16_t ssp_SendDataBlock(uint8_t *data, uint16_t length);
|
||||
bool debug;
|
||||
uint16_t ssp_SendDataBlock(uint8_t *data, uint16_t length);
|
||||
|
||||
public:
|
||||
/** PUBLIC FUNCTIONS **/
|
||||
virtual void pfCallBack(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
|
||||
qssp(port *info, bool debug);
|
||||
|
||||
int16_t ssp_ReceiveProcess();
|
||||
int16_t ssp_SendProcess();
|
||||
uint16_t ssp_SendString(char *str);
|
||||
int16_t ssp_SendData(const uint8_t *data, const uint16_t length);
|
||||
void ssp_Init(const PortConfig_t *const info);
|
||||
int16_t ssp_ReceiveByte();
|
||||
int16_t ssp_ReceiveByte();
|
||||
uint16_t ssp_Synchronise();
|
||||
qssp(port *info, bool debug);
|
||||
|
||||
virtual void pfCallBack(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
|
||||
};
|
||||
|
||||
#endif // QSSP_H
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qsspt.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,17 +27,27 @@
|
||||
*/
|
||||
#include "qsspt.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
qsspt::qsspt(port *info, bool debug) : qssp(info, debug), endthread(false), datapending(false), debug(debug)
|
||||
{}
|
||||
|
||||
qsspt::~qsspt()
|
||||
{
|
||||
endthread = true;
|
||||
// TODO bad...
|
||||
wait(1000);
|
||||
}
|
||||
|
||||
void qsspt::run()
|
||||
{
|
||||
// TODO the loop is non blocking and will spin as fast as the CPU allows
|
||||
while (!endthread) {
|
||||
receivestatus = this->ssp_ReceiveProcess();
|
||||
sendstatus = this->ssp_SendProcess();
|
||||
receivestatus = ssp_ReceiveProcess();
|
||||
sendstatus = ssp_SendProcess();
|
||||
sendbufmutex.lock();
|
||||
if (datapending && receivestatus == SSP_TX_IDLE) {
|
||||
this->ssp_SendData(mbuf, msize);
|
||||
ssp_SendData(mbuf, msize);
|
||||
datapending = false;
|
||||
}
|
||||
sendbufmutex.unlock();
|
||||
@ -45,13 +56,11 @@ void qsspt::run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool qsspt::sendData(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
if (debug) {
|
||||
QByteArray data;
|
||||
for (int i = 0; i < size; i++) {
|
||||
data.append((uint8_t)buf[i]);
|
||||
}
|
||||
QByteArray data((const char *)buf, size);
|
||||
qDebug() << "SSP TX " << data.toHex();
|
||||
}
|
||||
if (datapending) {
|
||||
@ -62,6 +71,8 @@ bool qsspt::sendData(uint8_t *buf, uint16_t size)
|
||||
mbuf = buf;
|
||||
msize = size;
|
||||
sendbufmutex.unlock();
|
||||
// TODO why do we wait 10 seconds ? why do we then ignore the timeout ?
|
||||
// There is a ssp_SendDataBlock method...
|
||||
msendwait.lock();
|
||||
sendwait.wait(&msendwait, 10000);
|
||||
msendwait.unlock();
|
||||
@ -71,21 +82,19 @@ bool qsspt::sendData(uint8_t *buf, uint16_t size)
|
||||
void qsspt::pfCallBack(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
if (debug) {
|
||||
qDebug() << "receive callback" << buf[0] << buf[1] << buf[2] << buf[3] << buf[4] << "array size=" << queue.count();
|
||||
}
|
||||
QByteArray array;
|
||||
for (int x = 0; x < size; x++) {
|
||||
array.append(buf[x]);
|
||||
qDebug() << "receive callback" << buf[0] << buf[1] << buf[2] << buf[3] << buf[4] << "queue size=" << queue.count();
|
||||
}
|
||||
QByteArray data((const char *)buf, size);
|
||||
mutex.lock();
|
||||
queue.enqueue(array);
|
||||
// queue.enqueue((const char *)&buf);
|
||||
queue.enqueue(data);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
int qsspt::packets_Available()
|
||||
{
|
||||
return queue.count();
|
||||
}
|
||||
|
||||
int qsspt::read_Packet(void *data)
|
||||
{
|
||||
mutex.lock();
|
||||
@ -101,8 +110,3 @@ int qsspt::read_Packet(void *data)
|
||||
mutex.unlock();
|
||||
return arr.length();
|
||||
}
|
||||
qsspt::~qsspt()
|
||||
{
|
||||
endthread = true;
|
||||
wait(1000);
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qsspt.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -28,20 +29,24 @@
|
||||
#define QSSPT_H
|
||||
|
||||
#include "qssp.h"
|
||||
|
||||
#include <QThread>
|
||||
#include <QQueue>
|
||||
#include <QWaitCondition>
|
||||
#include <QMutex>
|
||||
|
||||
class qsspt : public qssp, public QThread {
|
||||
public:
|
||||
qsspt(port *info, bool debug);
|
||||
~qsspt();
|
||||
|
||||
void run();
|
||||
|
||||
int packets_Available();
|
||||
int read_Packet(void *);
|
||||
~qsspt();
|
||||
bool sendData(uint8_t *buf, uint16_t size);
|
||||
|
||||
private:
|
||||
virtual void pfCallBack(uint8_t *, uint16_t);
|
||||
uint8_t *mbuf;
|
||||
uint16_t msize;
|
||||
QQueue<QByteArray> queue;
|
||||
@ -54,6 +59,8 @@ private:
|
||||
QWaitCondition sendwait;
|
||||
QMutex msendwait;
|
||||
bool debug;
|
||||
|
||||
virtual void pfCallBack(uint8_t *, uint16_t);
|
||||
};
|
||||
|
||||
#endif // QSSPT_H
|
||||
|
@ -4,39 +4,47 @@
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core
|
||||
|
||||
QT -= gui
|
||||
DEFINES += QEXTSERIALPORT_LIBRARY
|
||||
TARGET = ssp_test
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = ssp_test
|
||||
|
||||
SOURCES += main.cpp \
|
||||
QT += core
|
||||
QT -= gui
|
||||
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
DEFINES += QEXTSERIALPORT_LIBRARY
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
qssp.cpp \
|
||||
port.cpp \
|
||||
qsspt.cpp
|
||||
HEADERS += ../../../libs/qextserialport/src/qextserialport.h \
|
||||
../../../libs/qextserialport/src/qextserialenumerator.h \
|
||||
../../../libs/qextserialport/src/qextserialport_global.h \
|
||||
|
||||
HEADERS += \
|
||||
../../../libs/qextserialport/src/qextserialport.h \
|
||||
../../../libs/qextserialport/src/qextserialenumerator.h \
|
||||
../../../libs/qextserialport/src/qextserialport_global.h \
|
||||
qssp.h \
|
||||
port.h \
|
||||
common.h \
|
||||
qsspt.h
|
||||
SOURCES += ../../../libs/qextserialport/src/qextserialport.cpp
|
||||
|
||||
unix:SOURCES += ../../../libs/qextserialport/src/posix_qextserialport.cpp
|
||||
unix:!macx:SOURCES += ../../../libs/qextserialport/src/qextserialenumerator_unix.cpp
|
||||
SOURCES += ../../../libs/qextserialport/src/qextserialport.cpp
|
||||
|
||||
unix:SOURCES += ../../../libs/qextserialport/src/posix_qextserialport.cpp
|
||||
unix:!macx:SOURCES += ../../../libs/qextserialport/src/qextserialenumerator_unix.cpp
|
||||
macx {
|
||||
SOURCES += ../../../libs/qextserialport/src/qextserialenumerator_osx.cpp
|
||||
LIBS += -framework IOKit -framework CoreFoundation
|
||||
SOURCES += ../../../libs/qextserialport/src/qextserialenumerator_osx.cpp
|
||||
LIBS += -framework IOKit -framework CoreFoundation
|
||||
}
|
||||
|
||||
win32 {
|
||||
SOURCES += ../../../libs/qextserialport/src/win_qextserialport.cpp \
|
||||
../../../libs/qextserialport/src/qextserialenumerator_win.cpp
|
||||
DEFINES += WINVER=0x0501 # needed for mingw to pull in appropriate dbt business...probably a better way to do this
|
||||
LIBS += -lsetupapi
|
||||
SOURCES += \
|
||||
../../../libs/qextserialport/src/win_qextserialport.cpp \
|
||||
../../../libs/qextserialport/src/qextserialenumerator_win.cpp
|
||||
|
||||
# needed for mingw to pull in appropriate dbt business...probably a better way to do this
|
||||
DEFINES += WINVER=0x0501
|
||||
LIBS += -lsetupapi
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "delay.h"
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#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
|
@ -1,8 +1,9 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file op_dfu.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @file dfu.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Uploader Plugin
|
||||
@ -24,22 +25,34 @@
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "dfu.h"
|
||||
|
||||
#include "op_dfu.h"
|
||||
#include "SSP/port.h"
|
||||
#include "SSP/qsspt.h"
|
||||
|
||||
// #include <ophid/inc/ophid_hidapi.h>
|
||||
// #include <ophid/inc/ophid_usbmon.h>
|
||||
// #include <ophid/inc/ophid_usbsignal.h>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <qwaitcondition.h>
|
||||
#include <QMetaType>
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
using namespace OP_DFU;
|
||||
using namespace std;
|
||||
using namespace DFU;
|
||||
|
||||
DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
debug(_debug), use_serial(_use_serial), mready(true)
|
||||
{
|
||||
info = NULL;
|
||||
numberOfDevices = 0;
|
||||
serialhandle = NULL;
|
||||
port *info = NULL;
|
||||
|
||||
qRegisterMetaType<OP_DFU::Status>("Status");
|
||||
qRegisterMetaType<DFU::Status>("Status");
|
||||
|
||||
if (use_serial) {
|
||||
info = new port(portname, false);
|
||||
@ -54,42 +67,51 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
mready = false;
|
||||
return;
|
||||
}
|
||||
serialhandle = new qsspt(info, false);
|
||||
serialhandle = new qsspt(info, false /*debug*/);
|
||||
|
||||
int count = 0;
|
||||
while ((serialhandle->ssp_Synchronise() == false) && (count < 10)) {
|
||||
while (!serialhandle->ssp_Synchronise() && (count < 10)) {
|
||||
if (debug) {
|
||||
qDebug() << "SYNC failed, resending";
|
||||
qDebug() << "SYNC failed, resending...";
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (count == 10) {
|
||||
mready = false;
|
||||
qDebug() << "SYNC failed";
|
||||
return;
|
||||
}
|
||||
qDebug() << "SYNC Succeded";
|
||||
|
||||
// transfer ownership of port to serialhandle thread
|
||||
info->moveToThread(serialhandle);
|
||||
connect(serialhandle, SIGNAL(finished()), info, SLOT(deleteLater()));
|
||||
|
||||
// start the serialhandle thread
|
||||
serialhandle->start();
|
||||
/* } else {
|
||||
mready = false;
|
||||
} else {
|
||||
/*
|
||||
hidHandle = new opHID_hidapi();
|
||||
|
||||
mready = false;
|
||||
QEventLoop m_eventloop;
|
||||
QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
|
||||
m_eventloop.exec();
|
||||
QList<USBPortInfo> devices;
|
||||
devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
|
||||
if (devices.length() == 1) {
|
||||
if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
mready = true;
|
||||
QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
|
||||
m_eventloop.exec();
|
||||
} else {
|
||||
hidHandle.close(0);
|
||||
hidHandle->close(0);
|
||||
}
|
||||
} else {
|
||||
// Wait for the board to appear on the USB bus:
|
||||
USBSignalFilter filter(0x20a0, -1, -1, USBMonitor::Bootloader);
|
||||
connect(&filter, SIGNAL(deviceDiscovered()), &m_eventloop, SLOT(quit()));
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
qDebug() << "OP_DFU trying to detect bootloader:" << x;
|
||||
qDebug() << "DFU trying to detect bootloader:" << x;
|
||||
|
||||
if (x == 0) {
|
||||
QTimer::singleShot(10000, &m_eventloop, SLOT(quit()));
|
||||
@ -101,80 +123,38 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
qDebug() << "Devices length: " << devices.length();
|
||||
if (devices.length() == 1) {
|
||||
qDebug() << "Opening device";
|
||||
if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
|
||||
m_eventloop.exec();
|
||||
qDebug() << "OP_DFU detected after delay";
|
||||
qDebug() << "DFU detected after delay";
|
||||
mready = true;
|
||||
qDebug() << "Detected";
|
||||
break;
|
||||
} else {
|
||||
hidHandle.close(0);
|
||||
hidHandle->close(0);
|
||||
}
|
||||
} else {
|
||||
qDebug() << devices.length() << " device(s) detected, don't know what to do!";
|
||||
mready = false;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
DFUObject::~DFUObject()
|
||||
{
|
||||
if (use_serial) {
|
||||
if (mready) {
|
||||
delete serialhandle;
|
||||
delete info;
|
||||
delete serialhandle;
|
||||
} else {
|
||||
/*
|
||||
if (hidHandle) {
|
||||
hidHandle->close(0);
|
||||
delete hidHandle;
|
||||
}
|
||||
} /*else {
|
||||
hidHandle.close(0);
|
||||
}*/
|
||||
}
|
||||
|
||||
void DFUObject::sendReset(void)
|
||||
{
|
||||
qDebug() << "Requesting user mode reset";
|
||||
uint8_t aa[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0x62, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 63
|
||||
uint8_t ba[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0xB9, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t ca[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0x10, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t bb[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x8D, 0x19, 0x00, 0x00, 0x13 };
|
||||
uint8_t ab[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x1B, 0x19, 0x00, 0x00, 0x76 };
|
||||
uint8_t cb[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x78, 0x1C, 0x00, 0x00, 0x25 };
|
||||
// 125
|
||||
/*if (!use_serial) {
|
||||
hidHandle.send(0, aa, 64, 5000);
|
||||
hidHandle.send(0, ab, 64, 5000);
|
||||
delay::msleep(600);
|
||||
hidHandle.send(0, ba, 64, 5000);
|
||||
hidHandle.send(0, bb, 64, 5000);
|
||||
delay::msleep(600);
|
||||
hidHandle.send(0, ca, 64, 5000);
|
||||
hidHandle.send(0, cb, 64, 5000);
|
||||
delay::msleep(100);
|
||||
hidHandle.close(1);
|
||||
} else {*/
|
||||
char a[255];
|
||||
char b[255];
|
||||
char c[255];
|
||||
memcpy(a, aa + 2, 62);
|
||||
memcpy(a + 62, ab + 2, 60);
|
||||
memcpy(b, ba + 2, 62);
|
||||
memcpy(b + 62, bb + 2, 60);
|
||||
memcpy(c, ca + 2, 62);
|
||||
memcpy(c + 62, cb + 2, 60);
|
||||
for (int x = 0; x < 123; ++x) {
|
||||
info->pfSerialWrite(a[x]);
|
||||
*/
|
||||
}
|
||||
delay::msleep(600);
|
||||
for (int x = 0; x < 123; ++x) {
|
||||
info->pfSerialWrite(b[x]);
|
||||
}
|
||||
delay::msleep(600);
|
||||
for (int x = 0; x < 123; ++x) {
|
||||
info->pfSerialWrite(c[x]);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
bool DFUObject::SaveByteArrayToFile(QString const & sfile, const QByteArray &array)
|
||||
@ -183,7 +163,7 @@ bool DFUObject::SaveByteArrayToFile(QString const & sfile, const QByteArray &arr
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
if (debug) {
|
||||
qDebug() << "Can't open file";
|
||||
qDebug() << "Can't open file" << sfile;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -200,7 +180,7 @@ bool DFUObject::enterDFU(int const &devNumber)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::EnterDFU; // DFU Command
|
||||
buf[1] = DFU::EnterDFU; // DFU Command
|
||||
buf[2] = 0; // DFU Count
|
||||
buf[3] = 0; // DFU Count
|
||||
buf[4] = 0; // DFU Count
|
||||
@ -211,7 +191,6 @@ bool DFUObject::enterDFU(int const &devNumber)
|
||||
buf[9] = 1; // DFU Data3
|
||||
|
||||
int result = sendData(buf, BUF_LEN);
|
||||
|
||||
if (result < 1) {
|
||||
return false;
|
||||
}
|
||||
@ -240,7 +219,7 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
|
||||
}
|
||||
char buf[BUF_LEN];
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = setStartBit(OP_DFU::Upload); // DFU Command
|
||||
buf[1] = setStartBit(DFU::Upload); // DFU Command
|
||||
buf[2] = numberOfPackets >> 24; // DFU Count
|
||||
buf[3] = numberOfPackets >> 16; // DFU Count
|
||||
buf[4] = numberOfPackets >> 8; // DFU Count
|
||||
@ -256,7 +235,7 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
|
||||
}
|
||||
|
||||
int result = sendData(buf, BUF_LEN);
|
||||
delay::msleep(1000);
|
||||
QThread::msleep(1000);
|
||||
|
||||
if (debug) {
|
||||
qDebug() << result << " bytes sent";
|
||||
@ -267,7 +246,6 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Does the actual data upload to the board. Needs to be called once the
|
||||
board is ready to accept data following a StartUpload command, and it is erased.
|
||||
@ -289,7 +267,7 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
||||
}
|
||||
char buf[BUF_LEN];
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Upload; // DFU Command
|
||||
buf[1] = DFU::Upload; // DFU Command
|
||||
int packetsize;
|
||||
float percentage;
|
||||
int laspercentage = 0;
|
||||
@ -319,9 +297,9 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
||||
// 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);
|
||||
// QThread::msleep(send_delay);
|
||||
|
||||
if (StatusRequest() != OP_DFU::uploading) {
|
||||
if (StatusRequest() != DFU::uploading) {
|
||||
return false;
|
||||
}
|
||||
int result = sendData(buf, BUF_LEN);
|
||||
@ -341,11 +319,13 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
||||
/**
|
||||
Sends the firmware description to the device
|
||||
*/
|
||||
OP_DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||
DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||
{
|
||||
cout << "Starting uploading description\n";
|
||||
QByteArray array;
|
||||
|
||||
emit operationProgress("Uploading description");
|
||||
|
||||
QByteArray array;
|
||||
if (desc.type() == QVariant::String) {
|
||||
QString description = desc.toString();
|
||||
if (description.length() % 4 != 0) {
|
||||
@ -361,17 +341,16 @@ OP_DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||
array = desc.toByteArray();
|
||||
}
|
||||
|
||||
if (!StartUpload(array.length(), OP_DFU::Descript, 0)) {
|
||||
return OP_DFU::abort;
|
||||
if (!StartUpload(array.length(), DFU::Descript, 0)) {
|
||||
return DFU::abort;
|
||||
}
|
||||
if (!UploadData(array.length(), array)) {
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
if (!EndOperation()) {
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
OP_DFU::Status ret = StatusRequest();
|
||||
|
||||
DFU::Status ret = StatusRequest();
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Upload description Status=" << StatusToString(ret);
|
||||
@ -388,7 +367,7 @@ QString DFUObject::DownloadDescription(int const & numberOfChars)
|
||||
{
|
||||
QByteArray arr;
|
||||
|
||||
StartDownloadT(&arr, numberOfChars, OP_DFU::Descript);
|
||||
StartDownloadT(&arr, numberOfChars, DFU::Descript);
|
||||
|
||||
int index = arr.indexOf(255);
|
||||
return QString((index == -1) ? arr : arr.left(index));
|
||||
@ -398,7 +377,7 @@ QByteArray DFUObject::DownloadDescriptionAsBA(int const & numberOfChars)
|
||||
{
|
||||
QByteArray arr;
|
||||
|
||||
StartDownloadT(&arr, numberOfChars, OP_DFU::Descript);
|
||||
StartDownloadT(&arr, numberOfChars, DFU::Descript);
|
||||
|
||||
return arr;
|
||||
}
|
||||
@ -413,28 +392,27 @@ bool DFUObject::DownloadFirmware(QByteArray *firmwareArray, int device)
|
||||
if (isRunning()) {
|
||||
return false;
|
||||
}
|
||||
requestedOperation = OP_DFU::Download;
|
||||
requestedOperation = DFU::Download;
|
||||
requestSize = devices[device].SizeOfCode;
|
||||
requestTransferType = OP_DFU::FW;
|
||||
requestTransferType = DFU::FW;
|
||||
requestStorage = firmwareArray;
|
||||
start();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Runs the upload or download operations.
|
||||
*/
|
||||
void DFUObject::run()
|
||||
{
|
||||
switch (requestedOperation) {
|
||||
case OP_DFU::Download:
|
||||
case DFU::Download:
|
||||
StartDownloadT(requestStorage, requestSize, requestTransferType);
|
||||
emit(downloadFinished());
|
||||
break;
|
||||
case OP_DFU::Upload:
|
||||
case DFU::Upload:
|
||||
{
|
||||
OP_DFU::Status ret = UploadFirmwareT(requestFilename, requestVerify, requestDevice);
|
||||
DFU::Status ret = UploadFirmwareT(requestFilename, requestVerify, requestDevice);
|
||||
emit(uploadFinished(ret));
|
||||
break;
|
||||
}
|
||||
@ -465,7 +443,7 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Download_Req; // DFU Command
|
||||
buf[1] = DFU::Download_Req; // DFU Command
|
||||
buf[2] = numberOfPackets >> 24; // DFU Count
|
||||
buf[3] = numberOfPackets >> 16; // DFU Count
|
||||
buf[4] = numberOfPackets >> 8; // DFU Count
|
||||
@ -507,7 +485,6 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets the device
|
||||
*/
|
||||
@ -516,7 +493,7 @@ int DFUObject::ResetDevice(void)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Reset; // DFU Command
|
||||
buf[1] = DFU::Reset; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -527,7 +504,7 @@ int DFUObject::ResetDevice(void)
|
||||
buf[9] = 0;
|
||||
|
||||
return sendData(buf, BUF_LEN);
|
||||
// return hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
// return hidHandle->send(0,buf, BUF_LEN, 500);
|
||||
}
|
||||
|
||||
int DFUObject::AbortOperation(void)
|
||||
@ -535,7 +512,7 @@ int DFUObject::AbortOperation(void)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Abort_Operation; // DFU Command
|
||||
buf[1] = DFU::Abort_Operation; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -547,6 +524,7 @@ int DFUObject::AbortOperation(void)
|
||||
|
||||
return sendData(buf, BUF_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the firmware (leaves bootloader and boots the main software)
|
||||
*/
|
||||
@ -555,7 +533,7 @@ int DFUObject::JumpToApp(bool safeboot, bool erase)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::JumpFW; // DFU Command
|
||||
buf[1] = DFU::JumpFW; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -606,12 +584,12 @@ int DFUObject::JumpToApp(bool safeboot, bool erase)
|
||||
return sendData(buf, BUF_LEN);
|
||||
}
|
||||
|
||||
OP_DFU::Status DFUObject::StatusRequest()
|
||||
DFU::Status DFUObject::StatusRequest()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Status_Request; // DFU Command
|
||||
buf[1] = DFU::Status_Request; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -629,10 +607,10 @@ OP_DFU::Status DFUObject::StatusRequest()
|
||||
if (debug) {
|
||||
qDebug() << "StatusRequest: " << result << " bytes received";
|
||||
}
|
||||
if (buf[1] == OP_DFU::Status_Rep) {
|
||||
return (OP_DFU::Status)buf[6];
|
||||
if (buf[1] == DFU::Status_Rep) {
|
||||
return (DFU::Status)buf[6];
|
||||
} else {
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
}
|
||||
|
||||
@ -644,7 +622,7 @@ bool DFUObject::findDevices()
|
||||
devices.clear();
|
||||
char buf[BUF_LEN];
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Req_Capabilities; // DFU Command
|
||||
buf[1] = DFU::Req_Capabilities; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -658,6 +636,7 @@ bool DFUObject::findDevices()
|
||||
if (result < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = receiveData(buf, BUF_LEN);
|
||||
if (result < 1) {
|
||||
return false;
|
||||
@ -667,14 +646,14 @@ bool DFUObject::findDevices()
|
||||
RWFlags = buf[8];
|
||||
RWFlags = RWFlags << 8 | buf[9];
|
||||
|
||||
if (buf[1] == OP_DFU::Rep_Capabilities) {
|
||||
if (buf[1] == 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[1] = DFU::Req_Capabilities; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -722,13 +701,12 @@ bool DFUObject::findDevices()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DFUObject::EndOperation()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Op_END; // DFU Command
|
||||
buf[1] = DFU::END; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -748,8 +726,6 @@ bool DFUObject::EndOperation()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
/**
|
||||
Starts a firmware upload (asynchronous)
|
||||
*/
|
||||
@ -758,7 +734,7 @@ bool DFUObject::UploadFirmware(const QString &sfile, const bool &verify, int dev
|
||||
if (isRunning()) {
|
||||
return false;
|
||||
}
|
||||
requestedOperation = OP_DFU::Upload;
|
||||
requestedOperation = DFU::Upload;
|
||||
requestFilename = sfile;
|
||||
requestDevice = device;
|
||||
requestVerify = verify;
|
||||
@ -766,9 +742,9 @@ bool DFUObject::UploadFirmware(const QString &sfile, const bool &verify, int dev
|
||||
return true;
|
||||
}
|
||||
|
||||
OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &verify, int device)
|
||||
DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &verify, int device)
|
||||
{
|
||||
OP_DFU::Status ret;
|
||||
DFU::Status ret;
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Starting Firmware Uploading...";
|
||||
@ -778,9 +754,9 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
if (debug) {
|
||||
qDebug() << "Cant open file";
|
||||
qDebug() << "Failed to open file" << sfile;
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
|
||||
QByteArray arr = file.readAll();
|
||||
@ -799,7 +775,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
if (debug) {
|
||||
qDebug() << "ERROR file to big for device";
|
||||
}
|
||||
return OP_DFU::abort;;
|
||||
return DFU::abort;;
|
||||
}
|
||||
|
||||
quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode);
|
||||
@ -807,7 +783,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
qDebug() << "NEW FIRMWARE CRC=" << crc;
|
||||
}
|
||||
|
||||
if (!StartUpload(arr.length(), OP_DFU::FW, crc)) {
|
||||
if (!StartUpload(arr.length(), DFU::FW, crc)) {
|
||||
ret = StatusRequest();
|
||||
if (debug) {
|
||||
qDebug() << "StartUpload failed";
|
||||
@ -816,13 +792,13 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
return ret;
|
||||
}
|
||||
|
||||
emit operationProgress(QString("Erasing, please wait..."));
|
||||
emit operationProgress("Erasing, please wait...");
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Erasing memory";
|
||||
}
|
||||
if (StatusRequest() == OP_DFU::abort) {
|
||||
return OP_DFU::abort;
|
||||
if (StatusRequest() == DFU::abort) {
|
||||
return DFU::abort;
|
||||
}
|
||||
|
||||
// TODO: why is there a loop there? The "if" statement
|
||||
@ -832,14 +808,14 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
if (debug) {
|
||||
qDebug() << "Erase returned: " << StatusToString(ret);
|
||||
}
|
||||
if (ret == OP_DFU::uploading) {
|
||||
if (ret == DFU::uploading) {
|
||||
break;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
emit operationProgress(QString("Uploading firmware"));
|
||||
emit operationProgress("Uploading firmware");
|
||||
if (!UploadData(arr.length(), arr)) {
|
||||
ret = StatusRequest();
|
||||
if (debug) {
|
||||
@ -857,18 +833,18 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
return ret;
|
||||
}
|
||||
ret = StatusRequest();
|
||||
if (ret != OP_DFU::Last_operation_Success) {
|
||||
if (ret != DFU::Last_operation_Success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
emit operationProgress(QString("Verifying firmware"));
|
||||
emit operationProgress("Verifying firmware");
|
||||
cout << "Starting code verification\n";
|
||||
QByteArray arr2;
|
||||
StartDownloadT(&arr2, arr.length(), OP_DFU::FW);
|
||||
StartDownloadT(&arr2, arr.length(), DFU::FW);
|
||||
if (arr != arr2) {
|
||||
cout << "Verify:FAILED\n";
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
}
|
||||
|
||||
@ -879,8 +855,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareType &type, int device)
|
||||
DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareType &type, int device)
|
||||
{
|
||||
cout << "Starting Firmware Compare...\n";
|
||||
QFile file(sfile);
|
||||
@ -888,7 +863,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
|
||||
if (debug) {
|
||||
qDebug() << "Cant open file";
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
QByteArray arr = file.readAll();
|
||||
|
||||
@ -902,7 +877,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
|
||||
pad = pad - arr.length();
|
||||
arr.append(QByteArray(pad, 255));
|
||||
}
|
||||
if (type == OP_DFU::crccompare) {
|
||||
if (type == DFU::crccompare) {
|
||||
quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode);
|
||||
if (crc == devices[device].FW_CRC) {
|
||||
cout << "Compare Successfull CRC MATCH!\n";
|
||||
@ -912,7 +887,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
|
||||
return StatusRequest();
|
||||
} else {
|
||||
QByteArray arr2;
|
||||
StartDownloadT(&arr2, arr.length(), OP_DFU::FW);
|
||||
StartDownloadT(&arr2, arr.length(), DFU::FW);
|
||||
if (arr == arr2) {
|
||||
cout << "Compare Successfull ALL Bytes MATCH!\n";
|
||||
} else {
|
||||
@ -931,7 +906,8 @@ void DFUObject::CopyWords(char *source, char *destination, int count)
|
||||
*(destination + x + 3) = source[x + 0];
|
||||
}
|
||||
}
|
||||
QString DFUObject::StatusToString(OP_DFU::Status const & status)
|
||||
|
||||
QString DFUObject::StatusToString(DFU::Status const & status)
|
||||
{
|
||||
switch (status) {
|
||||
case DFUidle:
|
||||
@ -988,11 +964,10 @@ QString DFUObject::StatusToString(OP_DFU::Status const & status)
|
||||
*/
|
||||
void DFUObject::printProgBar(int const & percent, QString const & label)
|
||||
{
|
||||
std::string bar;
|
||||
|
||||
emit(progressUpdated(percent));
|
||||
|
||||
if (debug) {
|
||||
std::string bar;
|
||||
for (int i = 0; i < 50; i++) {
|
||||
if (i < (percent / 2)) {
|
||||
bar.replace(i, 1, "=");
|
||||
@ -1017,7 +992,8 @@ quint32 DFUObject::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
|
||||
// Nibble lookup table for 0x04C11DB7 polynomial
|
||||
static const quint32 CrcTable[16] = {
|
||||
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
|
||||
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
|
||||
};
|
||||
@ -1064,16 +1040,17 @@ quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size)
|
||||
return DFUObject::CRC32WideFast(0xFFFFFFFF, Size / 4, (quint32 *)t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send data to the bootloader, either through the serial port
|
||||
of through the HID handle, depending on the mode we're using
|
||||
*/
|
||||
int DFUObject::sendData(void *data, int size)
|
||||
{
|
||||
/*if (!use_serial) {
|
||||
return hidHandle.send(0, data, size, 5000);
|
||||
}*/
|
||||
/*
|
||||
if (!use_serial) {
|
||||
return hidHandle->send(0, data, size, 5000);
|
||||
}
|
||||
*/
|
||||
|
||||
// Serial Mode:
|
||||
if (serialhandle->sendData((uint8_t *)data + 1, size - 1)) {
|
||||
@ -1088,16 +1065,17 @@ int DFUObject::sendData(void *data, int size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Receive data from the bootloader, either through the serial port
|
||||
of through the HID handle, depending on the mode we're using
|
||||
*/
|
||||
int DFUObject::receiveData(void *data, int size)
|
||||
{
|
||||
/*if (!use_serial) {
|
||||
return hidHandle.receive(0, data, size, 10000);
|
||||
}*/
|
||||
/*
|
||||
if (!use_serial) {
|
||||
return hidHandle->receive(0, data, size, 10000);
|
||||
}
|
||||
*/
|
||||
|
||||
// Serial Mode:
|
||||
int x;
|
||||
@ -1106,7 +1084,7 @@ int DFUObject::receiveData(void *data, int size)
|
||||
time.start();
|
||||
while (true) {
|
||||
if ((x = serialhandle->read_Packet(((char *)data) + 1) != -1) || time.elapsed() > 10000) {
|
||||
msleep(10);
|
||||
QThread::msleep(10);
|
||||
if (time.elapsed() > 10000) {
|
||||
qDebug() << "____timeout";
|
||||
}
|
||||
@ -1129,9 +1107,9 @@ int DFUObject::receiveData(void *data, int size)
|
||||
/**
|
||||
Gets the type of board connected
|
||||
*/
|
||||
OP_DFU::eBoardType DFUObject::GetBoardType(int boardNum)
|
||||
DFU::eBoardType DFUObject::GetBoardType(int boardNum)
|
||||
{
|
||||
OP_DFU::eBoardType brdType = eBoardUnkwn;
|
||||
DFU::eBoardType brdType = eBoardUnkwn;
|
||||
|
||||
// First of all, check what Board type we are talking to
|
||||
int board = devices[boardNum].ID;
|
@ -1,36 +1,51 @@
|
||||
#ifndef OP_DFU_H
|
||||
#define OP_DFU_H
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file dfu.h
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Uploader Plugin
|
||||
* @{
|
||||
* @brief The uploader plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef DFU_H
|
||||
#define DFU_H
|
||||
|
||||
#include <QByteArray>
|
||||
// #include <ophid/inc/ophid_hidapi.h>
|
||||
// #include <ophid/inc/ophid_usbmon.h>
|
||||
// #include <ophid/inc/ophid_usbsignal.h>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QMetaType>
|
||||
#include <QCryptographicHash>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <iostream>
|
||||
#include "delay.h"
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include "SSP/qssp.h"
|
||||
#include "SSP/port.h"
|
||||
#include "SSP/qsspt.h"
|
||||
|
||||
using namespace std;
|
||||
#define BUF_LEN 64
|
||||
|
||||
#define MAX_PACKET_DATA_LEN 255
|
||||
#define MAX_PACKET_BUF_SIZE (1 + 1 + MAX_PACKET_DATA_LEN + 2)
|
||||
|
||||
namespace OP_DFU {
|
||||
#define BUF_LEN 64
|
||||
|
||||
// serial
|
||||
class qsspt;
|
||||
|
||||
// usb
|
||||
class opHID_hidapi;
|
||||
|
||||
namespace DFU {
|
||||
enum TransferTypes {
|
||||
FW,
|
||||
Descript
|
||||
@ -40,21 +55,6 @@ enum CompareType {
|
||||
crccompare,
|
||||
bytetobytecompare
|
||||
};
|
||||
// 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"
|
||||
#define USE_SERIAL "-t"
|
||||
#define NO_COUNTDOWN "-i"
|
||||
|
||||
Q_ENUMS(Status)
|
||||
enum Status {
|
||||
@ -96,7 +96,7 @@ enum Commands {
|
||||
Reset, // 5
|
||||
Abort_Operation, // 6
|
||||
Upload, // 7
|
||||
Op_END, // 8
|
||||
END, // 8
|
||||
Download_Req, // 9
|
||||
Download, // 10
|
||||
Status_Request, // 11
|
||||
@ -114,22 +114,21 @@ enum eBoardType {
|
||||
};
|
||||
|
||||
struct device {
|
||||
int ID;
|
||||
quint16 ID;
|
||||
quint32 FW_CRC;
|
||||
int BL_Version;
|
||||
quint8 BL_Version;
|
||||
int SizeOfDesc;
|
||||
quint32 SizeOfCode;
|
||||
bool Readable;
|
||||
bool Writable;
|
||||
};
|
||||
|
||||
|
||||
class DFUObject : public QThread {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
static quint32 CRCFromQBArray(QByteArray array, quint32 Size);
|
||||
// DFUObject(bool debug);
|
||||
|
||||
DFUObject(bool debug, bool use_serial, QString port);
|
||||
|
||||
virtual ~DFUObject();
|
||||
@ -139,8 +138,7 @@ public:
|
||||
bool findDevices();
|
||||
int JumpToApp(bool safeboot, bool erase);
|
||||
int ResetDevice(void);
|
||||
void sendReset(void);
|
||||
OP_DFU::Status StatusRequest();
|
||||
DFU::Status StatusRequest();
|
||||
bool EndOperation();
|
||||
int AbortOperation(void);
|
||||
bool ready()
|
||||
@ -149,7 +147,7 @@ public:
|
||||
}
|
||||
|
||||
// Upload (send to device) commands
|
||||
OP_DFU::Status UploadDescription(QVariant description);
|
||||
DFU::Status UploadDescription(QVariant description);
|
||||
bool UploadFirmware(const QString &sfile, const bool &verify, int device);
|
||||
|
||||
// Download (get from device) commands:
|
||||
@ -162,11 +160,10 @@ public:
|
||||
bool DownloadFirmware(QByteArray *byteArray, int device);
|
||||
|
||||
// Comparison functions (is this needed?)
|
||||
OP_DFU::Status CompareFirmware(const QString &sfile, const CompareType &type, int device);
|
||||
DFU::Status CompareFirmware(const QString &sfile, const CompareType &type, int device);
|
||||
|
||||
bool SaveByteArrayToFile(QString const & file, QByteArray const &array);
|
||||
|
||||
|
||||
// Variables:
|
||||
QList<device> devices;
|
||||
int numberOfDevices;
|
||||
@ -174,15 +171,14 @@ public:
|
||||
bool use_delay;
|
||||
|
||||
// Helper functions:
|
||||
QString StatusToString(OP_DFU::Status const & status);
|
||||
QString StatusToString(DFU::Status const & status);
|
||||
static quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer);
|
||||
OP_DFU::eBoardType GetBoardType(int boardNum);
|
||||
|
||||
DFU::eBoardType GetBoardType(int boardNum);
|
||||
|
||||
signals:
|
||||
void progressUpdated(int);
|
||||
void downloadFinished();
|
||||
void uploadFinished(OP_DFU::Status);
|
||||
void uploadFinished(DFU::Status);
|
||||
void operationProgress(QString status);
|
||||
|
||||
private:
|
||||
@ -191,16 +187,18 @@ private:
|
||||
bool use_serial;
|
||||
bool mready;
|
||||
int RWFlags;
|
||||
|
||||
// Serial
|
||||
qsspt *serialhandle;
|
||||
|
||||
// USB
|
||||
// opHID_hidapi *hidHandle;
|
||||
|
||||
int sendData(void *, int);
|
||||
int receiveData(void *data, int size);
|
||||
uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE];
|
||||
uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE];
|
||||
port *info;
|
||||
|
||||
|
||||
// USB Bootloader:
|
||||
// opHID_hidapi hidHandle;
|
||||
int setStartBit(int command)
|
||||
{
|
||||
return command | 0x20;
|
||||
@ -214,11 +212,11 @@ private:
|
||||
// Thread management:
|
||||
// Same as startDownload except that we store in an external array:
|
||||
bool StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, TransferTypes const & type);
|
||||
OP_DFU::Status UploadFirmwareT(const QString &sfile, const bool &verify, int device);
|
||||
DFU::Status UploadFirmwareT(const QString &sfile, const bool &verify, int device);
|
||||
QMutex mutex;
|
||||
OP_DFU::Commands requestedOperation;
|
||||
DFU::Commands requestedOperation;
|
||||
qint32 requestSize;
|
||||
OP_DFU::TransferTypes requestTransferType;
|
||||
DFU::TransferTypes requestTransferType;
|
||||
QByteArray *requestStorage;
|
||||
QString requestFilename;
|
||||
bool requestVerify;
|
||||
@ -229,7 +227,7 @@ protected:
|
||||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(OP_DFU::Status)
|
||||
Q_DECLARE_METATYPE(DFU::Status)
|
||||
|
||||
|
||||
#endif // OP_DFU_H
|
||||
#endif // DFU_H
|
@ -1,12 +1,66 @@
|
||||
#include <QtCore/QCoreApplication>
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file main.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader tool
|
||||
* @{
|
||||
* @brief The USB and Serial protocol uploader tool
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "dfu.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
#include <QThread>
|
||||
#include "op_dfu.h"
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void showProgress(QString status);
|
||||
void progressUpdated(int percent);
|
||||
void usage(QTextStream *standardOutput);
|
||||
|
||||
QString label;
|
||||
|
||||
// Command Line Options
|
||||
#define DOWNLOAD "-dn"
|
||||
#define DEVICE "-d"
|
||||
#define DOWNDESCRIPTION "-dd"
|
||||
#define PROGRAMFW "-p"
|
||||
#define PROGRAMDESC "-w"
|
||||
#define VERIFY "-v"
|
||||
#define COMPARECRC "-cc"
|
||||
#define COMPAREALL "-ca"
|
||||
#define STATUSREQUEST "-s"
|
||||
#define LISTDEVICES "-ls"
|
||||
#define RESET "-r"
|
||||
#define JUMP "-j"
|
||||
#define USE_SERIAL "-t"
|
||||
#define NO_COUNTDOWN "-i"
|
||||
#define HELP "-h"
|
||||
#define DEBUG "-debug"
|
||||
#define USERMODERESET "-ur"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
@ -16,23 +70,20 @@ int main(int argc, char *argv[])
|
||||
bool verify;
|
||||
bool debug = false;
|
||||
// bool umodereset = false;
|
||||
OP_DFU::Actions action = OP_DFU::actionNone;
|
||||
DFU::Actions action = DFU::actionNone;
|
||||
QString file;
|
||||
QString serialport;
|
||||
QString description;
|
||||
int device = -1;
|
||||
QStringList args = QCoreApplication::arguments();
|
||||
|
||||
if (args.contains("-debug")) {
|
||||
if (args.contains(DEBUG)) {
|
||||
debug = true;
|
||||
}
|
||||
if (args.contains("-ur")) {
|
||||
if (args.contains(USERMODERESET)) {
|
||||
// umodereset = true;
|
||||
}
|
||||
standardOutput << "OpenPilot serial firmware uploader tool." << endl;
|
||||
if (args.indexOf(PROGRAMFW) + 1 < args.length()) {
|
||||
file = args[args.indexOf(PROGRAMFW) + 1];
|
||||
}
|
||||
standardOutput << "Serial firmware uploader tool." << endl;
|
||||
if (args.contains(DEVICE)) {
|
||||
if (args.indexOf(DEVICE) + 1 < args.length()) {
|
||||
device = (args[args.indexOf(DEVICE) + 1]).toInt();
|
||||
@ -41,7 +92,7 @@ int main(int argc, char *argv[])
|
||||
device = 0;
|
||||
}
|
||||
|
||||
if (argumentCount == 0 || args.contains("-?") || !args.contains(USE_SERIAL)) {
|
||||
if (argumentCount == 0 || args.contains(HELP) || !args.contains(USE_SERIAL)) {
|
||||
usage(&standardOutput);
|
||||
return -1;
|
||||
} else if (args.contains(PROGRAMFW)) {
|
||||
@ -55,30 +106,45 @@ int main(int argc, char *argv[])
|
||||
description = (args[args.indexOf(PROGRAMDESC) + 1]);
|
||||
}
|
||||
}
|
||||
action = OP_DFU::actionProgram;
|
||||
} else if (args.contains(COMPARECRC) || args.contains(COMPAREALL)) {
|
||||
// int index;
|
||||
if (args.contains(COMPARECRC)) {
|
||||
// index = args.indexOf(COMPARECRC);
|
||||
action = OP_DFU::actionCompareCrc;
|
||||
if (args.indexOf(PROGRAMFW) + 1 < args.length()) {
|
||||
file = args[args.indexOf(PROGRAMFW) + 1];
|
||||
} else {
|
||||
// index = args.indexOf(COMPAREALL);
|
||||
action = OP_DFU::actionCompareAll;
|
||||
// error
|
||||
}
|
||||
action = DFU::actionProgram;
|
||||
} else if (args.contains(COMPARECRC) || args.contains(COMPAREALL)) {
|
||||
if (args.contains(COMPARECRC)) {
|
||||
if (args.indexOf(COMPARECRC) + 1 < args.length()) {
|
||||
file = args[args.indexOf(COMPARECRC) + 1];
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
action = DFU::actionCompareCrc;
|
||||
} else {
|
||||
if (args.indexOf(COMPAREALL) + 1 < args.length()) {
|
||||
file = args[args.indexOf(COMPAREALL) + 1];
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
action = DFU::actionCompareAll;
|
||||
}
|
||||
} else if (args.contains(DOWNLOAD)) {
|
||||
// int index;
|
||||
// index = args.indexOf(DOWNLOAD);
|
||||
action = OP_DFU::actionDownload;
|
||||
if (args.indexOf(DOWNLOAD) + 1 < args.length()) {
|
||||
file = args[args.indexOf(DOWNLOAD) + 1];
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
action = DFU::actionDownload;
|
||||
} else if (args.contains(STATUSREQUEST)) {
|
||||
action = OP_DFU::actionStatusReq;
|
||||
action = DFU::actionStatusReq;
|
||||
} else if (args.contains(RESET)) {
|
||||
action = OP_DFU::actionReset;
|
||||
action = DFU::actionReset;
|
||||
} else if (args.contains(JUMP)) {
|
||||
action = OP_DFU::actionJump;
|
||||
action = DFU::actionJump;
|
||||
} else if (args.contains(LISTDEVICES)) {
|
||||
action = OP_DFU::actionListDevs;
|
||||
action = DFU::actionListDevs;
|
||||
}
|
||||
if ((file.isEmpty() || device == -1) && action != OP_DFU::actionReset && action != OP_DFU::actionStatusReq && action != OP_DFU::actionListDevs && action != OP_DFU::actionJump) {
|
||||
if ((file.isEmpty() || device == -1) && action != DFU::actionReset && action != DFU::actionStatusReq && action != DFU::actionListDevs && action != DFU::actionJump) {
|
||||
usage(&standardOutput);
|
||||
return -1;
|
||||
}
|
||||
@ -89,20 +155,19 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
qDebug() << "Action=" << (int)action << endl;
|
||||
qDebug() << "File=" << file << endl;
|
||||
qDebug() << "Device=" << device << endl;
|
||||
qDebug() << "Action=" << action << endl;
|
||||
qDebug() << "Desctription" << description << endl;
|
||||
qDebug() << "Use Serial port" << use_serial << endl;
|
||||
qDebug() << "Action=" << (int)action;
|
||||
qDebug() << "File=" << file;
|
||||
qDebug() << "Device=" << device;
|
||||
qDebug() << "Action=" << action;
|
||||
qDebug() << "Description" << description;
|
||||
qDebug() << "Use Serial port" << use_serial;
|
||||
if (use_serial) {
|
||||
qDebug() << "Port Name" << serialport << endl;
|
||||
qDebug() << "Port Name" << serialport;
|
||||
}
|
||||
}
|
||||
if (use_serial) {
|
||||
if (args.contains(NO_COUNTDOWN)) {} else {
|
||||
standardOutput << "Connect the board" << endl;
|
||||
label = "";
|
||||
showProgress("Connect the board");
|
||||
for (int i = 0; i < 6; i++) {
|
||||
progressUpdated(i * 100 / 5);
|
||||
QThread::msleep(500);
|
||||
@ -111,11 +176,13 @@ int main(int argc, char *argv[])
|
||||
standardOutput << endl << "Connect the board NOW" << endl;
|
||||
QThread::msleep(1000);
|
||||
}
|
||||
///////////////////////////////////ACTIONS START///////////////////////////////////////////////////
|
||||
OP_DFU::DFUObject dfu(debug, use_serial, serialport);
|
||||
|
||||
QObject::connect(&dfu, &OP_DFU::DFUObject::operationProgress, showProgress);
|
||||
QObject::connect(&dfu, &OP_DFU::DFUObject::progressUpdated, progressUpdated);
|
||||
///////////////////////////////////ACTIONS START///////////////////////////////////////////////////
|
||||
|
||||
DFU::DFUObject dfu(debug, use_serial, serialport);
|
||||
|
||||
QObject::connect(&dfu, &DFU::DFUObject::operationProgress, showProgress);
|
||||
QObject::connect(&dfu, &DFU::DFUObject::progressUpdated, progressUpdated);
|
||||
|
||||
if (!dfu.ready()) {
|
||||
return -1;
|
||||
@ -126,26 +193,26 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
if (debug) {
|
||||
OP_DFU::Status ret = dfu.StatusRequest();
|
||||
DFU::Status ret = dfu.StatusRequest();
|
||||
qDebug() << dfu.StatusToString(ret);
|
||||
}
|
||||
if (!(action == OP_DFU::actionStatusReq || action == OP_DFU::actionReset || action == OP_DFU::actionJump)) {
|
||||
if (!(action == DFU::actionStatusReq || action == DFU::actionReset || action == DFU::actionJump)) {
|
||||
dfu.findDevices();
|
||||
if (action == OP_DFU::actionListDevs) {
|
||||
standardOutput << "Found " << dfu.numberOfDevices << "\n" << endl;
|
||||
if (action == DFU::actionListDevs) {
|
||||
standardOutput << "Found " << dfu.numberOfDevices << "\n";
|
||||
for (int x = 0; x < dfu.numberOfDevices; ++x) {
|
||||
standardOutput << "Device #" << x << "\n" << endl;
|
||||
standardOutput << "Device ID=" << dfu.devices[x].ID << "\n" << endl;
|
||||
standardOutput << "Device Readable=" << dfu.devices[x].Readable << "\n" << endl;
|
||||
standardOutput << "Device Writable=" << dfu.devices[x].Writable << "\n" << endl;
|
||||
standardOutput << "Device SizeOfCode=" << dfu.devices[x].SizeOfCode << "\n" << endl;
|
||||
standardOutput << "BL Version=" << dfu.devices[x].BL_Version << "\n" << endl;
|
||||
standardOutput << "Device SizeOfDesc=" << dfu.devices[x].SizeOfDesc << "\n" << endl;
|
||||
standardOutput << "Device #" << x << "\n";
|
||||
standardOutput << "Device ID=" << dfu.devices[x].ID << "\n";
|
||||
standardOutput << "Device Readable=" << dfu.devices[x].Readable << "\n";
|
||||
standardOutput << "Device Writable=" << dfu.devices[x].Writable << "\n";
|
||||
standardOutput << "Device SizeOfCode=" << dfu.devices[x].SizeOfCode << "\n";
|
||||
standardOutput << "BL Version=" << dfu.devices[x].BL_Version << "\n";
|
||||
standardOutput << "Device SizeOfDesc=" << dfu.devices[x].SizeOfDesc << "\n";
|
||||
standardOutput << "FW CRC=" << dfu.devices[x].FW_CRC << "\n";
|
||||
|
||||
int size = ((OP_DFU::device)dfu.devices[x]).SizeOfDesc;
|
||||
int size = ((DFU::device)dfu.devices[x]).SizeOfDesc;
|
||||
dfu.enterDFU(x);
|
||||
standardOutput << "Description:" << dfu.DownloadDescription(size).toLatin1().data() << "\n" << endl;
|
||||
standardOutput << "Description:" << dfu.DownloadDescription(size).toLatin1().data() << "\n";
|
||||
standardOutput << "\n";
|
||||
}
|
||||
return 0;
|
||||
@ -161,12 +228,15 @@ int main(int argc, char *argv[])
|
||||
standardOutput << "Error:Could not enter DFU mode\n" << endl;
|
||||
return -1;
|
||||
}
|
||||
if (action == OP_DFU::actionProgram) {
|
||||
if (((OP_DFU::device)dfu.devices[device]).Writable == false) {
|
||||
if (action == DFU::actionProgram) {
|
||||
if (((DFU::device)dfu.devices[device]).Writable == false) {
|
||||
standardOutput << "ERROR device not Writable\n" << endl;
|
||||
return false;
|
||||
}
|
||||
standardOutput << "Uploading..." << endl;
|
||||
|
||||
// this call is asynchronous so the only false status it will report
|
||||
// is when it is already running...
|
||||
bool retstatus = dfu.UploadFirmware(file.toLatin1(), verify, device);
|
||||
|
||||
if (!retstatus) {
|
||||
@ -176,23 +246,23 @@ int main(int argc, char *argv[])
|
||||
while (!dfu.isFinished()) {
|
||||
QThread::msleep(500);
|
||||
}
|
||||
// TODO check if upload went well...
|
||||
if (file.endsWith("opfw")) {
|
||||
QByteArray firmware;
|
||||
QFile fwfile(file);
|
||||
if (!fwfile.open(QIODevice::ReadOnly)) {
|
||||
standardOutput << "Cannot open file " << file << endl;
|
||||
return -1;
|
||||
}
|
||||
firmware = fwfile.readAll();
|
||||
QByteArray desc = firmware.right(100);
|
||||
OP_DFU::Status status = dfu.UploadDescription(desc);
|
||||
if (status != OP_DFU::Last_operation_Success) {
|
||||
QByteArray firmware = fwfile.readAll();
|
||||
QByteArray desc = firmware.right(100);
|
||||
DFU::Status status = dfu.UploadDescription(desc);
|
||||
if (status != DFU::Last_operation_Success) {
|
||||
standardOutput << "Upload failed with code:" << retstatus << endl;
|
||||
return -1;
|
||||
}
|
||||
} else if (!description.isEmpty()) {
|
||||
OP_DFU::Status status = dfu.UploadDescription(description);
|
||||
if (status != OP_DFU::Last_operation_Success) {
|
||||
DFU::Status status = dfu.UploadDescription(description);
|
||||
if (status != DFU::Last_operation_Success) {
|
||||
standardOutput << "Upload failed with code:" << status << endl;
|
||||
return -1;
|
||||
}
|
||||
@ -200,32 +270,35 @@ int main(int argc, char *argv[])
|
||||
while (!dfu.isFinished()) {
|
||||
QThread::msleep(500);
|
||||
}
|
||||
standardOutput << "Uploading Succeded!\n" << endl;
|
||||
} else if (action == OP_DFU::actionDownload) {
|
||||
if (((OP_DFU::device)dfu.devices[device]).Readable == false) {
|
||||
standardOutput << "Uploading Succeeded!\n" << endl;
|
||||
} else if (action == DFU::actionDownload) {
|
||||
if (((DFU::device)dfu.devices[device]).Readable == false) {
|
||||
standardOutput << "ERROR device not readable\n" << endl;
|
||||
return false;
|
||||
}
|
||||
QByteArray fw;
|
||||
dfu.DownloadFirmware(&fw, 0);
|
||||
while (!dfu.isFinished()) {
|
||||
QThread::msleep(500);
|
||||
}
|
||||
bool ret = dfu.SaveByteArrayToFile(file.toLatin1(), fw);
|
||||
return ret;
|
||||
} else if (action == OP_DFU::actionCompareCrc) {
|
||||
dfu.CompareFirmware(file.toLatin1(), OP_DFU::crccompare, device);
|
||||
} else if (action == DFU::actionCompareCrc) {
|
||||
dfu.CompareFirmware(file.toLatin1(), DFU::crccompare, device);
|
||||
return 1;
|
||||
} else if (action == OP_DFU::actionCompareAll) {
|
||||
if (((OP_DFU::device)dfu.devices[device]).Readable == false) {
|
||||
} else if (action == DFU::actionCompareAll) {
|
||||
if (((DFU::device)dfu.devices[device]).Readable == false) {
|
||||
standardOutput << "ERROR device not readable\n" << endl;
|
||||
return false;
|
||||
}
|
||||
dfu.CompareFirmware(file.toLatin1(), OP_DFU::bytetobytecompare, device);
|
||||
dfu.CompareFirmware(file.toLatin1(), DFU::bytetobytecompare, device);
|
||||
return 1;
|
||||
}
|
||||
} else if (action == OP_DFU::actionStatusReq) {
|
||||
} else if (action == DFU::actionStatusReq) {
|
||||
standardOutput << "Current device status=" << dfu.StatusToString(dfu.StatusRequest()).toLatin1().data() << "\n" << endl;
|
||||
} else if (action == OP_DFU::actionReset) {
|
||||
} else if (action == DFU::actionReset) {
|
||||
dfu.ResetDevice();
|
||||
} else if (action == OP_DFU::actionJump) {
|
||||
} else if (action == DFU::actionJump) {
|
||||
dfu.JumpToApp(false, false);
|
||||
}
|
||||
return 0;
|
||||
@ -254,49 +327,41 @@ void progressUpdated(int percent)
|
||||
bar.replace(i, 1, " ");
|
||||
}
|
||||
}
|
||||
std::cout << "\r" << label.toLatin1().data() << "[" << bar << "] ";
|
||||
std::cout << "\r" << label.toLatin1().data() << " [" << bar << "] ";
|
||||
std::cout.width(3);
|
||||
std::cout << percent << "% " << std::flush;
|
||||
}
|
||||
|
||||
void usage(QTextStream *standardOutput)
|
||||
{
|
||||
*standardOutput << "_________________________________________________________________________\n";
|
||||
*standardOutput << "| Commands |\n";
|
||||
*standardOutput << "| |\n";
|
||||
*standardOutput << "| -ls : lists available devices |\n";
|
||||
*standardOutput << "| -p <file> : program hw (requires:-d - optionals:-v,-w) |\n";
|
||||
*standardOutput << "| -v : verify (requires:-d) |\n";
|
||||
*standardOutput << "| -dn <file> : download firmware to file |\n";
|
||||
// *standardOutput << "| -dd <file> : download discription (requires:-d) |\n";
|
||||
*standardOutput << "| -d <Device Number> : target device number (default 0, first device) |\n";
|
||||
// *standardOutput << "| -w <description> : (requires: -p) |\n";
|
||||
*standardOutput << "| -ca <file> : compares byte by byte current firmware with file|\n";
|
||||
*standardOutput << "| -cc <file> : compares CRC of current firmware with file |\n";
|
||||
*standardOutput << "| -s : requests status of device |\n";
|
||||
*standardOutput << "| -r : resets the device |\n";
|
||||
*standardOutput << "| -j : exits bootloader and jumps to user FW |\n";
|
||||
*standardOutput << "| -debug : prints debug information |\n";
|
||||
*standardOutput << "| -t <port> : uses serial port |\n";
|
||||
*standardOutput << "| -i : immediate, doesn't show the connection countdown|\n";
|
||||
// *standardOutput << "| -ur <port> : user mode reset* |\n";
|
||||
*standardOutput << "| |\n";
|
||||
*standardOutput << "| examples: |\n";
|
||||
*standardOutput << "| |\n";
|
||||
*standardOutput << "| program and verify the fist device device connected to COM1 |\n";
|
||||
*standardOutput << "| OPUploadTool -p c:/gpsp.opfw -v -t COM1 |\n";
|
||||
*standardOutput << "| |\n";
|
||||
*standardOutput << "| program and verify the fist device device connected to COM1 |\n";
|
||||
*standardOutput << "| OPUploadTool -p c:/gpsp.opfw -v -t COM1 |\n";
|
||||
*standardOutput << "| |\n";
|
||||
*standardOutput << "| Perform a quick compare of FW in file with FW in device #1 |\n";
|
||||
*standardOutput << "| OPUploadTool -ch /home/user1/gpsp.opfw -t ttyUSB0 |\n";
|
||||
*standardOutput << "| |\n";
|
||||
// *standardOutput << "| *requires valid user space firmwares already running |\n";
|
||||
*standardOutput << "|________________________________________________________________________|\n";
|
||||
*standardOutput << endl;
|
||||
*standardOutput << "Options:\n";
|
||||
*standardOutput << "-ls : lists available devices\n";
|
||||
*standardOutput << "-p <file> : program hw (requires:-d - optionals:-v,-w)\n";
|
||||
*standardOutput << "-v : verify (requires:-d)\n";
|
||||
*standardOutput << "-dn <file> : download firmware to file\n";
|
||||
// *standardOutput << "-dd <file> : download discription (requires:-d)\n";
|
||||
*standardOutput << "-d <Device Number> : target device number (default 0, first device)\n";
|
||||
// *standardOutput << "-w <description> : (requires: -p)\n";
|
||||
*standardOutput << "-ca <file> : compares byte by byte current firmware with file\n";
|
||||
*standardOutput << "-cc <file> : compares CRC of current firmware with file\n";
|
||||
*standardOutput << "-s : requests status of device\n";
|
||||
*standardOutput << "-r : resets the device\n";
|
||||
*standardOutput << "-j : exits bootloader and jumps to user FW\n";
|
||||
*standardOutput << "-debug : prints debug information\n";
|
||||
*standardOutput << "-t <port> : uses serial port\n";
|
||||
*standardOutput << "-i : immediate, doesn't show the connection countdown\n";
|
||||
*standardOutput << "-h : print usage\n";
|
||||
// *standardOutput << "-ur <port> : user mode reset*\n";
|
||||
// *standardOutput << " *requires valid user space firmwares already running\n";
|
||||
*standardOutput << "\n";
|
||||
*standardOutput << "Program and verify the first device connected to COM1\n";
|
||||
*standardOutput << " UploadTool -p c:/gpsp.opfw -v -t COM1\n";
|
||||
*standardOutput << "\n";
|
||||
*standardOutput << "Perform a quick compare of FW in file with FW on device #1\n";
|
||||
*standardOutput << " UploadTool -ca /home/user1/gpsp.opfw -t ttyUSB0\n";
|
||||
}
|
||||
|
||||
void howToUsage(QTextStream *standardOutput)
|
||||
{
|
||||
*standardOutput << "run the tool with -? for more informations" << endl;
|
||||
*standardOutput << "run the tool with -h for more informations" << endl;
|
||||
}
|
||||
|
@ -4,72 +4,27 @@
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core
|
||||
TEMPLATE = app
|
||||
TARGET = UploadTool
|
||||
|
||||
QT -= gui
|
||||
QT += serialport
|
||||
QT += core serialport
|
||||
QT -= gui
|
||||
|
||||
TARGET = OPUploadTool
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
# don't build both debug and release
|
||||
CONFIG -= debug_and_release
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += main.cpp \
|
||||
op_dfu.cpp \
|
||||
delay.cpp \
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
dfu.cpp \
|
||||
./SSP/qssp.cpp \
|
||||
./SSP/port.cpp \
|
||||
./SSP/qsspt.cpp \
|
||||
|
||||
HEADERS += op_dfu.h \
|
||||
delay.h \
|
||||
HEADERS += \
|
||||
dfu.h \
|
||||
./SSP/qssp.h \
|
||||
./SSP/port.h \
|
||||
./SSP/common.h \
|
||||
./SSP/qsspt.h
|
||||
|
||||
# win32 {
|
||||
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_win.cpp
|
||||
#
|
||||
# LIBS += -lhid \
|
||||
# -lsetupapi
|
||||
#}
|
||||
|
||||
#macx {
|
||||
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_mac.cpp
|
||||
# SDK = /Developer/SDKs/MacOSX10.5.sdk
|
||||
# ARCH = -mmacosx-version-min=10.5 \
|
||||
# -arch \
|
||||
# ppc \
|
||||
# -arch \
|
||||
# i386
|
||||
# LIBS += $(ARCH) \
|
||||
# -Wl,-syslibroot,$(SDK) \
|
||||
# -framework \
|
||||
# IOKit \
|
||||
# -framework \
|
||||
# CoreFoundation
|
||||
#}
|
||||
#linux-g++ {
|
||||
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_unix.cpp
|
||||
# LIBS += -lusb
|
||||
#}
|
||||
#linux-g++-64 {
|
||||
# SOURCES += ../../plugins/rawhid/pjrc_rawhid_unix.cpp
|
||||
# LIBS += -lusb
|
||||
#}
|
||||
|
||||
#unix:SOURCES += ../../libs/qextserialport/src/posix_qextserialport.cpp
|
||||
#unix:!macx:SOURCES += ../../libs/qextserialport/src/qextserialenumerator_unix.cpp
|
||||
#macx {
|
||||
# SOURCES += ../../libs/qextserialport/src/qextserialenumerator_osx.cpp
|
||||
# LIBS += -framework IOKit -framework CoreFoundation
|
||||
#}
|
||||
|
||||
#win32 {
|
||||
# SOURCES += ../../libs/qextserialport/src/win_qextserialport.cpp \
|
||||
#../../libs/qextserialport/src/qextserialenumerator_win.cpp
|
||||
# DEFINES += WINVER=0x0501 # needed for mingw to pull in appropriate dbt business...probably a better way to do this
|
||||
# LIBS += -lsetupapi
|
||||
#}
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file common.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -23,10 +24,11 @@
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/#ifndef COMMON_H
|
||||
*/
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
enum decodeState_ {
|
||||
enum DecodeState {
|
||||
decode_len1_e = 0,
|
||||
decode_seqNo_e,
|
||||
decode_data_e,
|
||||
@ -34,10 +36,10 @@ enum decodeState_ {
|
||||
decode_crc2_e,
|
||||
decode_idle_e
|
||||
};
|
||||
|
||||
enum ReceiveState {
|
||||
state_escaped_e = 0,
|
||||
state_unescaped_e
|
||||
};
|
||||
|
||||
|
||||
#endif // COMMON_H
|
||||
|
97
ground/gcs/src/plugins/uploader/SSP/main.cpp
Normal file
97
ground/gcs/src/plugins/uploader/SSP/main.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file main.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
* @{
|
||||
* @brief The USB and Serial protocol uploader plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "qssp.h"
|
||||
#include "port.h"
|
||||
#include "qsspt.h"
|
||||
|
||||
#include "../../../libs/qextserialport/src/qextserialport.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
|
||||
#define MAX_PACKET_DATA_LEN 255
|
||||
#define MAX_PACKET_BUF_SIZE (1 + 1 + 255 + 2)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE];
|
||||
uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE];
|
||||
|
||||
port *info;
|
||||
PortSettings settings;
|
||||
|
||||
settings.BaudRate = BAUD57600;
|
||||
settings.DataBits = DATA_8;
|
||||
settings.FlowControl = FLOW_OFF;
|
||||
settings.Parity = PAR_NONE;
|
||||
settings.StopBits = STOP_1;
|
||||
settings.Timeout_Millisec = 5000;
|
||||
|
||||
info = new port(settings, "COM3");
|
||||
info->rxBuf = sspRxBuf;
|
||||
info->rxBufSize = MAX_PACKET_DATA_LEN;
|
||||
info->txBuf = sspTxBuf;
|
||||
info->txBufSize = 255;
|
||||
info->max_retry = 3;
|
||||
info->timeoutLen = 5000;
|
||||
// qssp b(info);
|
||||
qsspt bb(info);
|
||||
uint8_t buf[1000];
|
||||
QCoreApplication a(argc, argv);
|
||||
while (!bb.ssp_Synchronise()) {
|
||||
qDebug() << "trying sync";
|
||||
}
|
||||
bb.start();
|
||||
qDebug() << "sync complete";
|
||||
buf[0] = 0;
|
||||
buf[1] = 1;
|
||||
buf[2] = 2;
|
||||
while (true) {
|
||||
if (bb.sendData(buf, 63)) {
|
||||
qDebug() << "send OK";
|
||||
}
|
||||
// else
|
||||
// qDebug()<<"send NOK";
|
||||
////bb.ssp_SendData(buf,63);
|
||||
}
|
||||
while (true) {
|
||||
if (bb.packets_Available() > 0) {
|
||||
bb.read_Packet(buf);
|
||||
qDebug() << "receive=" << (int)buf[0] << (int)buf[1] << (int)buf[2];
|
||||
++buf[0];
|
||||
++buf[1];
|
||||
++buf[2];
|
||||
// bb.ssp_SendData(buf,63);
|
||||
bb.sendData(buf, 63);
|
||||
}
|
||||
// bb.ssp_ReceiveProcess();
|
||||
// bb.ssp_SendProcess();
|
||||
}
|
||||
return a.exec();
|
||||
}
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file port.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -25,21 +26,24 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "port.h"
|
||||
#include "delay.h"
|
||||
port::port(QString name) : mstatus(port::closed)
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QDebug>
|
||||
|
||||
port::port(QString name, bool debug) : mstatus(port::closed), debug(debug)
|
||||
{
|
||||
timer.start();
|
||||
sport = new QSerialPort(name);
|
||||
if (sport->open(QIODevice::ReadWrite | QIODevice::Unbuffered)) {
|
||||
if (sport->setBaudRate(57600)
|
||||
sport = new QSerialPort(name, this);
|
||||
if (sport->open(QIODevice::ReadWrite)) {
|
||||
if (sport->setBaudRate(QSerialPort::Baud57600)
|
||||
&& sport->setDataBits(QSerialPort::Data8)
|
||||
&& sport->setParity(QSerialPort::NoParity)
|
||||
&& sport->setStopBits(QSerialPort::OneStop)
|
||||
&& sport->setFlowControl(QSerialPort::NoFlowControl)) {
|
||||
mstatus = port::open;
|
||||
}
|
||||
// sport->setDtr();
|
||||
} else {
|
||||
qDebug() << sport->error();
|
||||
mstatus = port::error;
|
||||
}
|
||||
}
|
||||
@ -53,13 +57,25 @@ port::portstatus port::status()
|
||||
{
|
||||
return mstatus;
|
||||
}
|
||||
|
||||
int16_t port::pfSerialRead(void)
|
||||
{
|
||||
char c[1];
|
||||
|
||||
if (sport->bytesAvailable()) {
|
||||
// TODO why the wait ? (gcs uploader dfu does not have it)
|
||||
sport->waitForBytesWritten(1);
|
||||
if (sport->bytesAvailable() || sport->waitForReadyRead(0)) {
|
||||
sport->read(c, 1);
|
||||
} else { return -1; }
|
||||
if (debug) {
|
||||
if (((uint8_t)c[0]) == 0xe1 || rxDebugBuff.count() > 50) {
|
||||
qDebug() << "PORT R " << rxDebugBuff.toHex();
|
||||
rxDebugBuff.clear();
|
||||
}
|
||||
rxDebugBuff.append(c[0]);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return (uint8_t)c[0];
|
||||
}
|
||||
|
||||
@ -69,6 +85,15 @@ void port::pfSerialWrite(uint8_t c)
|
||||
|
||||
cc[0] = c;
|
||||
sport->write(cc, 1);
|
||||
if (debug) {
|
||||
if (((uint8_t)cc[0]) == 0xe1 || rxDebugBuff.count() > 50) {
|
||||
qDebug() << "PORT T " << txDebugBuff.toHex();
|
||||
txDebugBuff.clear();
|
||||
}
|
||||
txDebugBuff.append(cc[0]);
|
||||
}
|
||||
// TODO why the wait ? (gcs uploader dfu does not have it)
|
||||
sport->waitForBytesWritten(1);
|
||||
}
|
||||
|
||||
uint32_t port::pfGetTime(void)
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file port.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,19 +27,30 @@
|
||||
*/
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
#include <stdint.h>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class port {
|
||||
#include <QObject>
|
||||
#include <QTime>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class QSerialPort;
|
||||
|
||||
class port : public QObject {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
enum portstatus { open, closed, error };
|
||||
|
||||
port(QString name, bool debug);
|
||||
virtual ~port();
|
||||
portstatus status();
|
||||
|
||||
virtual int16_t pfSerialRead(void); // function to read a character from the serial input stream
|
||||
virtual void pfSerialWrite(uint8_t); // function to write a byte to be sent out the serial port
|
||||
virtual uint32_t pfGetTime(void);
|
||||
|
||||
uint8_t retryCount; // how many times have we tried to transmit the 'send' packet
|
||||
uint8_t maxRetryCount; // max. times to try to transmit the 'send' packet
|
||||
uint16_t max_retry; // Maximum number of retrys for a single transmit.
|
||||
@ -54,22 +66,25 @@ public:
|
||||
uint8_t *rxBuf; // receive buffer. Used to store data as a packet is received.
|
||||
uint16_t sendSynch; // flag to indicate that we should send a synchronize packet to the host
|
||||
// this is required when switching from the application to the bootloader
|
||||
// and vice-versa. This fixes the firwmare download timeout.
|
||||
// when this flag is set to true, the next time we send a packet we will first // send a synchronize packet.
|
||||
ReceiveState InputState;
|
||||
decodeState_ DecodeState;
|
||||
// and vice-versa. This fixes the firmware download timeout.
|
||||
// when this flag is set to true, the next time we send a packet we will first
|
||||
// send a synchronize packet.
|
||||
ReceiveState inputState;
|
||||
DecodeState decodeState;
|
||||
uint16_t SendState;
|
||||
uint16_t crc;
|
||||
uint32_t RxError;
|
||||
uint32_t TxError;
|
||||
uint16_t flags;
|
||||
port(QString name);
|
||||
virtual ~port();
|
||||
portstatus status();
|
||||
|
||||
private:
|
||||
portstatus mstatus;
|
||||
QTime timer;
|
||||
QSerialPort *sport;
|
||||
|
||||
bool debug;
|
||||
QByteArray rxDebugBuff;
|
||||
QByteArray txDebugBuff;
|
||||
};
|
||||
|
||||
#endif // PORT_H
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qssp.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,12 +27,12 @@
|
||||
*/
|
||||
#include "qssp.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/** PRIVATE DEFINITIONS **/
|
||||
#define SYNC 225 // Sync character used in Serial Protocol
|
||||
#define ESC 224 // ESC character used in Serial Protocol
|
||||
@ -143,8 +144,8 @@ void qssp::ssp_Init(const PortConfig_t *const info)
|
||||
thisport->rxSeqNo = 255;
|
||||
thisport->txSeqNo = 255;
|
||||
thisport->SendState = SSP_IDLE;
|
||||
thisport->InputState = (ReceiveState)0;
|
||||
thisport->DecodeState = (decodeState_)0;
|
||||
thisport->inputState = (ReceiveState)0;
|
||||
thisport->decodeState = (DecodeState)0;
|
||||
thisport->TxError = 0;
|
||||
thisport->RxError = 0;
|
||||
thisport->txSeqNo = 0;
|
||||
@ -174,7 +175,7 @@ int16_t qssp::ssp_SendProcess()
|
||||
sf_SetSendTimeout();
|
||||
value = SSP_TX_WAITING;
|
||||
} else {
|
||||
// Give up, # of trys has exceded the limit
|
||||
// Give up, # of tries has exceeded the limit
|
||||
value = SSP_TX_TIMEOUT;
|
||||
CLEARBIT(thisport->flags, ACK_RECEIVED);
|
||||
thisport->SendState = SSP_IDLE;
|
||||
@ -258,6 +259,7 @@ uint16_t qssp::ssp_SendDataBlock(uint8_t *data, uint16_t length)
|
||||
uint16_t retval = FALSE;
|
||||
|
||||
packet_status = ssp_SendData(data, length); // send the data
|
||||
// TODO the loop is non blocking and will spin as fast as the CPU allows
|
||||
while (packet_status == SSP_TX_WAITING) { // check the status
|
||||
(void)ssp_ReceiveProcess(); // process any bytes received.
|
||||
packet_status = ssp_SendProcess(); // check the send status
|
||||
@ -343,7 +345,7 @@ int16_t qssp::ssp_SendData(const uint8_t *data, const uint16_t length)
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Attempts to synchronize the sequence numbers with the other end of the connectin.
|
||||
* \brief Attempts to synchronize the sequence numbers with the other end of the connection.
|
||||
* \param thisport = which port to use
|
||||
* \return true = success
|
||||
* \return false = failed to receive an ACK to our synch request
|
||||
@ -374,7 +376,7 @@ uint16_t qssp::ssp_Synchronise()
|
||||
packet_status = ssp_SendData(NULL, 0);
|
||||
#endif
|
||||
while (packet_status == SSP_TX_WAITING) { // we loop until we time out.
|
||||
(void)ssp_ReceiveProcess(); // do the receive process
|
||||
ssp_ReceiveProcess(); // do the receive process
|
||||
packet_status = ssp_SendProcess(); // do the send process
|
||||
}
|
||||
thisport->sendSynch = FALSE;
|
||||
@ -391,7 +393,6 @@ uint16_t qssp::ssp_Synchronise()
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -417,7 +418,6 @@ void qssp::sf_SendPacket()
|
||||
thisport->retryCount++;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief converts data to transport layer protocol packet format.
|
||||
* \param txbuf = buffer to use when forming the packet
|
||||
@ -523,9 +523,18 @@ void qssp::sf_write_byte(uint8_t c)
|
||||
|
||||
uint16_t qssp::sf_crc16(uint16_t crc, uint8_t data)
|
||||
{
|
||||
#ifdef SPP_USES_CRC
|
||||
return (crc >> 8) ^ CRC_TABLE[(crc ^ data) & 0x00FF];
|
||||
}
|
||||
|
||||
#else
|
||||
uint8_t cka = crc & 0xff;
|
||||
uint8_t ckb = (crc >> 8) & 0xff;
|
||||
cka += data;
|
||||
ckb += cka;
|
||||
return cka | ckb << 8;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief sets the timeout for the given packet
|
||||
@ -594,20 +603,20 @@ int16_t qssp::sf_ReceiveState(uint8_t c)
|
||||
{
|
||||
int16_t retval = SSP_RX_RECEIVING;
|
||||
|
||||
switch (thisport->InputState) {
|
||||
switch (thisport->inputState) {
|
||||
case state_unescaped_e:
|
||||
if (c == SYNC) {
|
||||
thisport->DecodeState = decode_len1_e;
|
||||
thisport->decodeState = decode_len1_e;
|
||||
} else if (c == ESC) {
|
||||
thisport->InputState = state_escaped_e;
|
||||
thisport->inputState = state_escaped_e;
|
||||
} else {
|
||||
retval = sf_DecodeState(c);
|
||||
}
|
||||
break; // end of unescaped state.
|
||||
case state_escaped_e:
|
||||
thisport->InputState = state_unescaped_e;
|
||||
thisport->inputState = state_unescaped_e;
|
||||
if (c == SYNC) {
|
||||
thisport->DecodeState = decode_len1_e;
|
||||
thisport->decodeState = decode_len1_e;
|
||||
} else if (c == ESC_SYNC) {
|
||||
retval = sf_DecodeState(SYNC);
|
||||
} else {
|
||||
@ -644,20 +653,26 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
{
|
||||
int16_t retval;
|
||||
|
||||
switch (thisport->DecodeState) {
|
||||
switch (thisport->decodeState) {
|
||||
case decode_idle_e:
|
||||
// 'c' is ignored in this state as the only way to leave the idle state is
|
||||
// recognition of the SYNC byte in the sf_ReceiveState function.
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
case decode_len1_e:
|
||||
if (c == 0) {
|
||||
thisport->decodeState = decode_idle_e;
|
||||
thisport->RxError++;
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
}
|
||||
thisport->rxBuf[LENGTH] = c;
|
||||
thisport->rxBufLen = c;
|
||||
if (thisport->rxBufLen <= thisport->rxBufSize) {
|
||||
thisport->DecodeState = decode_seqNo_e;
|
||||
thisport->decodeState = decode_seqNo_e;
|
||||
retval = SSP_RX_RECEIVING;
|
||||
} else {
|
||||
thisport->DecodeState = decode_idle_e;
|
||||
thisport->decodeState = decode_idle_e;
|
||||
retval = SSP_RX_IDLE;
|
||||
}
|
||||
break;
|
||||
@ -669,9 +684,9 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
if (thisport->rxBufLen > 0) {
|
||||
thisport->DecodeState = decode_data_e;
|
||||
thisport->decodeState = decode_data_e;
|
||||
} else {
|
||||
thisport->DecodeState = decode_crc1_e;
|
||||
thisport->decodeState = decode_crc1_e;
|
||||
}
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
@ -679,17 +694,17 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
thisport->rxBuf[(thisport->rxBufPos)++] = c;
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
if (thisport->rxBufPos == (thisport->rxBufLen + 2)) {
|
||||
thisport->DecodeState = decode_crc1_e;
|
||||
thisport->decodeState = decode_crc1_e;
|
||||
}
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_crc1_e:
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
thisport->DecodeState = decode_crc2_e;
|
||||
thisport->decodeState = decode_crc2_e;
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_crc2_e:
|
||||
thisport->DecodeState = decode_idle_e;
|
||||
thisport->decodeState = decode_idle_e;
|
||||
// verify the CRC value for the packet
|
||||
if (sf_crc16(thisport->crc, c) == 0) {
|
||||
// TODO shouldn't the return value of sf_ReceivePacket() be checked?
|
||||
@ -701,7 +716,7 @@ int16_t qssp::sf_DecodeState(uint8_t c)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
thisport->DecodeState = decode_idle_e; // unknown state so reset to idle state and wait for the next start of a packet.
|
||||
thisport->decodeState = decode_idle_e; // unknown state so reset to idle state and wait for the next start of a packet.
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
}
|
||||
@ -785,6 +800,7 @@ int16_t qssp::sf_ReceivePacket()
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
qssp::qssp(port *info, bool debug) : debug(debug)
|
||||
{
|
||||
thisport = info;
|
||||
@ -799,13 +815,14 @@ qssp::qssp(port *info, bool debug) : debug(debug)
|
||||
thisport->rxSeqNo = 255;
|
||||
thisport->txSeqNo = 255;
|
||||
thisport->SendState = SSP_IDLE;
|
||||
thisport->InputState = (ReceiveState)0;
|
||||
thisport->DecodeState = (decodeState_)0;
|
||||
thisport->inputState = (ReceiveState)0;
|
||||
thisport->decodeState = (DecodeState)0;
|
||||
thisport->TxError = 0;
|
||||
thisport->RxError = 0;
|
||||
thisport->txSeqNo = 0;
|
||||
thisport->rxSeqNo = 0;
|
||||
}
|
||||
|
||||
void qssp::pfCallBack(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qssp.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,9 +27,12 @@
|
||||
*/
|
||||
#ifndef QSSP_H
|
||||
#define QSSP_H
|
||||
#include <stdint.h>
|
||||
#include "port.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "port.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** LOCAL DEFINITIONS **/
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
@ -38,6 +42,8 @@
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define SPP_USES_CRC
|
||||
|
||||
#define SSP_TX_IDLE 0 // not expecting a ACK packet (no current transmissions in progress)
|
||||
#define SSP_TX_WAITING 1 // waiting for a valid ACK to arrive
|
||||
#define SSP_TX_TIMEOUT 2 // failed to receive a valid ACK in the timeout period, after retrying.
|
||||
@ -55,7 +61,6 @@
|
||||
#define SSP_RX_ACK 6
|
||||
#define SSP_RX_SYNCH 7
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t *pbuff;
|
||||
uint16_t length;
|
||||
@ -73,42 +78,41 @@ typedef struct {
|
||||
// function returns time in number of seconds that has elapsed from a given reference point
|
||||
} PortConfig_t;
|
||||
|
||||
|
||||
/** Public Data **/
|
||||
|
||||
|
||||
/** EXTERNAL FUNCTIONS **/
|
||||
|
||||
class qssp {
|
||||
private:
|
||||
port *thisport;
|
||||
decodeState_ DecodeState_t;
|
||||
/** PRIVATE FUNCTIONS **/
|
||||
bool debug;
|
||||
|
||||
// static void sf_SendSynchPacket( Port_t *thisport );
|
||||
uint16_t sf_crc16(uint16_t crc, uint8_t data);
|
||||
uint16_t sf_crc16(uint16_t crc, uint8_t data);
|
||||
void sf_write_byte(uint8_t c);
|
||||
void sf_SetSendTimeout();
|
||||
uint16_t sf_CheckTimeout();
|
||||
uint16_t sf_CheckTimeout();
|
||||
int16_t sf_DecodeState(uint8_t c);
|
||||
int16_t sf_ReceiveState(uint8_t c);
|
||||
|
||||
void sf_SendPacket();
|
||||
void sf_SendAckPacket(uint8_t seqNumber);
|
||||
void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo);
|
||||
void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo);
|
||||
int16_t sf_ReceivePacket();
|
||||
uint16_t ssp_SendDataBlock(uint8_t *data, uint16_t length);
|
||||
bool debug;
|
||||
uint16_t ssp_SendDataBlock(uint8_t *data, uint16_t length);
|
||||
|
||||
public:
|
||||
/** PUBLIC FUNCTIONS **/
|
||||
virtual void pfCallBack(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
|
||||
qssp(port *info, bool debug);
|
||||
|
||||
int16_t ssp_ReceiveProcess();
|
||||
int16_t ssp_SendProcess();
|
||||
uint16_t ssp_SendString(char *str);
|
||||
int16_t ssp_SendData(const uint8_t *data, const uint16_t length);
|
||||
void ssp_Init(const PortConfig_t *const info);
|
||||
int16_t ssp_ReceiveByte();
|
||||
int16_t ssp_ReceiveByte();
|
||||
uint16_t ssp_Synchronise();
|
||||
qssp(port *info, bool debug);
|
||||
|
||||
virtual void pfCallBack(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
|
||||
};
|
||||
|
||||
#endif // QSSP_H
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qsspt.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -26,18 +27,27 @@
|
||||
*/
|
||||
#include "qsspt.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
qsspt::qsspt(port *info, bool debug) : qssp(info, debug), endthread(false), datapending(false), debug(debug)
|
||||
{}
|
||||
|
||||
qsspt::~qsspt()
|
||||
{
|
||||
endthread = true;
|
||||
// TODO bad...
|
||||
wait(1000);
|
||||
}
|
||||
|
||||
void qsspt::run()
|
||||
{
|
||||
// TODO the loop is non blocking and will spin as fast as the CPU allows
|
||||
while (!endthread) {
|
||||
receivestatus = this->ssp_ReceiveProcess();
|
||||
sendstatus = this->ssp_SendProcess();
|
||||
msleep(1);
|
||||
receivestatus = ssp_ReceiveProcess();
|
||||
sendstatus = ssp_SendProcess();
|
||||
sendbufmutex.lock();
|
||||
if (datapending && receivestatus == SSP_TX_IDLE) {
|
||||
this->ssp_SendData(mbuf, msize);
|
||||
ssp_SendData(mbuf, msize);
|
||||
datapending = false;
|
||||
}
|
||||
sendbufmutex.unlock();
|
||||
@ -46,8 +56,13 @@ void qsspt::run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool qsspt::sendData(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
if (debug) {
|
||||
QByteArray data((const char *)buf, size);
|
||||
qDebug() << "SSP TX " << data.toHex();
|
||||
}
|
||||
if (datapending) {
|
||||
return false;
|
||||
}
|
||||
@ -56,6 +71,8 @@ bool qsspt::sendData(uint8_t *buf, uint16_t size)
|
||||
mbuf = buf;
|
||||
msize = size;
|
||||
sendbufmutex.unlock();
|
||||
// TODO why do we wait 10 seconds ? why do we then ignore the timeout ?
|
||||
// There is a ssp_SendDataBlock method...
|
||||
msendwait.lock();
|
||||
sendwait.wait(&msendwait, 10000);
|
||||
msendwait.unlock();
|
||||
@ -65,21 +82,19 @@ bool qsspt::sendData(uint8_t *buf, uint16_t size)
|
||||
void qsspt::pfCallBack(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
if (debug) {
|
||||
qDebug() << "receive callback" << buf[0] << buf[1] << buf[2] << buf[3] << buf[4] << "array size=" << queue.count();
|
||||
}
|
||||
QByteArray array;
|
||||
for (int x = 0; x < size; x++) {
|
||||
array.append(buf[x]);
|
||||
qDebug() << "receive callback" << buf[0] << buf[1] << buf[2] << buf[3] << buf[4] << "queue size=" << queue.count();
|
||||
}
|
||||
QByteArray data((const char *)buf, size);
|
||||
mutex.lock();
|
||||
queue.enqueue(array);
|
||||
// queue.enqueue((const char *)&buf);
|
||||
queue.enqueue(data);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
int qsspt::packets_Available()
|
||||
{
|
||||
return queue.count();
|
||||
}
|
||||
|
||||
int qsspt::read_Packet(void *data)
|
||||
{
|
||||
mutex.lock();
|
||||
@ -89,11 +104,9 @@ int qsspt::read_Packet(void *data)
|
||||
}
|
||||
QByteArray arr = queue.dequeue();
|
||||
memcpy(data, (uint8_t *)arr.data(), arr.length());
|
||||
if (debug) {
|
||||
qDebug() << "SSP RX " << arr.toHex();
|
||||
}
|
||||
mutex.unlock();
|
||||
return arr.length();
|
||||
}
|
||||
qsspt::~qsspt()
|
||||
{
|
||||
endthread = true;
|
||||
wait(1000);
|
||||
}
|
||||
|
@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file qsspt.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Serial and USB Uploader Plugin
|
||||
@ -28,20 +29,24 @@
|
||||
#define QSSPT_H
|
||||
|
||||
#include "qssp.h"
|
||||
|
||||
#include <QThread>
|
||||
#include <QQueue>
|
||||
#include <QWaitCondition>
|
||||
#include <QMutex>
|
||||
|
||||
class qsspt : public qssp, public QThread {
|
||||
public:
|
||||
qsspt(port *info, bool debug);
|
||||
~qsspt();
|
||||
|
||||
void run();
|
||||
|
||||
int packets_Available();
|
||||
int read_Packet(void *);
|
||||
~qsspt();
|
||||
bool sendData(uint8_t *buf, uint16_t size);
|
||||
|
||||
private:
|
||||
virtual void pfCallBack(uint8_t *, uint16_t);
|
||||
uint8_t *mbuf;
|
||||
uint16_t msize;
|
||||
QQueue<QByteArray> queue;
|
||||
@ -54,6 +59,8 @@ private:
|
||||
QWaitCondition sendwait;
|
||||
QMutex msendwait;
|
||||
bool debug;
|
||||
|
||||
virtual void pfCallBack(uint8_t *, uint16_t);
|
||||
};
|
||||
|
||||
#endif // QSSPT_H
|
||||
|
816
ground/gcs/src/plugins/uploader/SSP/ssp.cpp
Normal file
816
ground/gcs/src/plugins/uploader/SSP/ssp.cpp
Normal file
@ -0,0 +1,816 @@
|
||||
/***********************************************************************************************************
|
||||
*
|
||||
* NAME: ssp.c
|
||||
* DESCRIPTION: simple serial protocol - packet based serial transport layer.
|
||||
* AUTHOR: Joe Hlebasko
|
||||
* HISTORY: Created 1/1/2010
|
||||
*
|
||||
* Packet Formats
|
||||
* Format:
|
||||
* +------+----+------+---------------------------+--------+
|
||||
* | 225 | L1 | S# | App Data (0-254 bytes) | CRC 16 |
|
||||
* +------+----+------+---------------------------+--------+
|
||||
*
|
||||
* 225 = sync byte, indicates start of a packet
|
||||
* L1 = 1 byte for size of data payload. (sequence number is part of data payload.)
|
||||
* S# = 1 byte for sequence number.
|
||||
* Seq of 0 = seq # synchronise request, forces other end to reset receive sequence number to 1.
|
||||
* sender of synchronise request will reset the tx seq number to 1
|
||||
* Seq # of 1..127 = normal data packets. Sequence number is incremented by for each transmitted
|
||||
* packet. Rolls over from 127 to 1.
|
||||
* if most sig. bit is set then the packet is an ACK packet of data packet sequence number of the
|
||||
* lower 7 bits (1..127)
|
||||
* App Data may contain 0..254 bytes. The sequence number is consider part of the payload.
|
||||
* CRC 16 - 16 bits of CRC values of Sequence # and data bytes.
|
||||
*
|
||||
* Protocol has two types of packets: data and ack packets. ACK packets have the most sig. bit set in the
|
||||
* sequence number, this implies that valid sequence numbers are 1..127
|
||||
*
|
||||
* This protocol uses the concept of sequences numbers to determine if a given packet has been received. This
|
||||
* requires both devices to be able to synchronize sequence numbers. This is accomplished by sending a packet
|
||||
* length 1 and sequence number = 0. The receive then resets it's transmit sequence number to 1.
|
||||
*
|
||||
* ACTIVE_SYNCH is a version that will automatically send a synch request if it receives a synch packet. Only
|
||||
* one device in the communication should do otherwise you end up with an endless loops of synchronization.
|
||||
* Right now each side needs to manually issues a synch request.
|
||||
*
|
||||
* This protocol is best used in cases where one device is the master and the other is the slave, or a don't
|
||||
* speak unless spoken to type of approach.
|
||||
*
|
||||
* The following are items are required to initialize a port for communications:
|
||||
* 1. The number attempts for each packet
|
||||
* 2. time to wait for an ack.
|
||||
* 3. pointer to buffer to be used for receiving.
|
||||
* 4. pointer to a buffer to be used for transmission
|
||||
* 5. length of each buffer (rx and tx)
|
||||
* 6. Four functions:
|
||||
* 1. write byte = writes a byte out the serial port (or other comm device)
|
||||
* 2. read byte = retrieves a byte from the serial port. Returns -1 if a byte is not available
|
||||
* 3. callback = function to call when a valid data packet has been received. This function is responsible
|
||||
* to do what needs to be done with the data when it is received. The primary mission of this function
|
||||
* should be to copy the data to a private buffer out of the working receive buffer to prevent overrun.
|
||||
* processing should be kept to a minimum.
|
||||
* 4. get time = function should return the current time. Note that time units are not specified it just
|
||||
* needs to be some measure of time that increments as time passes by. The timeout values for a given
|
||||
* port should the units used/returned by the get time function.
|
||||
*
|
||||
* All of the state information of a communication port is contained in a Port_t structure. This allows this
|
||||
* module to operature on multiple communication ports with a single code base.
|
||||
*
|
||||
* The ssp_ReceiveProcess and ssp_SendProcess functions need to be called to process data through the
|
||||
* respective state machines. Typical implementation would have a serial ISR to pull bytes out of the UART
|
||||
* and place into a circular buffer. The serial read function would then pull bytes out this buffer
|
||||
* processing. The TX side has the write function placing bytes into a circular buffer with the TX ISR
|
||||
* pulling bytes out of the buffer and putting into the UART. It is possible to run the receive process from
|
||||
* the receive ISR but care must be taken on processing data when it is received to avoid holding up the ISR
|
||||
* and sending ACK packets from the receive ISR.
|
||||
*
|
||||
***********************************************************************************************************/
|
||||
|
||||
/** INCLUDE FILES **/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ssp.h"
|
||||
|
||||
/** PRIVATE DEFINITIONS **/
|
||||
#define SYNC 225 // Sync character used in Serial Protocol
|
||||
#define ESC 224 // ESC character used in Serial Protocol
|
||||
#define ESC_SYNC 1 // ESC_SYNC character used in Serial Protocol
|
||||
#define ACK_BIT 0x80 // Ack bit, bit 7 of sequence number, 1 = Acknowledge, 0 =
|
||||
// new packet
|
||||
// packet location definitions.
|
||||
#define LENGTH 0
|
||||
#define SEQNUM 1
|
||||
#define DATA 2
|
||||
|
||||
|
||||
// Make larger sized integers from smaller sized integers
|
||||
#define MAKEWORD16(ub, lb) ((uint16_t)0x0000 | ((uint16_t)(ub) << 8) | (uint16_t)(lb))
|
||||
#define MAKEWORD32(uw, lw) ((uint32_t)(0x0UL | ((uint32_t)(uw) << 16) | (uint32_t)(lw)))
|
||||
#define MAKEWORD32B(b3, b2, b1, b0) ((uint32_t)((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | ((uint32_t)(b0)))
|
||||
|
||||
|
||||
// Used to extract smaller integers from larger sized intergers
|
||||
#define LOWERBYTE(w) (uint8_t)((w) & 0x00ff)
|
||||
#define UPPERBYTE(w) (uint8_t)(((w) & 0xff00) >> 8)
|
||||
#define UPPERWORD(lw) (uint16_t)(((lw) & 0xffff0000) >> 16)
|
||||
#define LOWERWORD(lw) (uint16_t)((lw) & 0x0000ffff)
|
||||
|
||||
// Macros to operate on a target and bitmask.
|
||||
#define CLEARBIT(a, b) ((a) = (a) & ~(b))
|
||||
#define SETBIT(a, b) ((a) = (a) | (b))
|
||||
#define TOGGLEBIT(a, b) ((a) = (a) ^ (b))
|
||||
|
||||
// test bit macros operate using a bit mask.
|
||||
#define ISBITSET(a, b) (((a) & (b)) == (b) ? TRUE : FALSE)
|
||||
#define ISBITCLEAR(a, b) ((~(a) & (b)) == (b) ? TRUE : FALSE)
|
||||
|
||||
/** PRIVATE FUNCTIONS **/
|
||||
// static void sf_SendSynchPacket( Port_t *thisport );
|
||||
static uint16_t sf_crc16(uint16_t crc, uint8_t data);
|
||||
static void sf_write_byte(Port_t *thisport, uint8_t c);
|
||||
static void sf_SetSendTimeout(Port_t *thisport);
|
||||
static uint16_t sf_CheckTimeout(Port_t *thisport);
|
||||
static int16_t sf_DecodeState(Port_t *thisport, uint8_t c);
|
||||
static int16_t sf_ReceiveState(Port_t *thisport, uint8_t c);
|
||||
|
||||
static void sf_SendPacket(Port_t *thisport);
|
||||
static void sf_SendAckPacket(Port_t *thisport, uint8_t seqNumber);
|
||||
static void sf_MakePacket(uint8_t *buf, const uint8_t *pdata, uint16_t length, uint8_t seqNo);
|
||||
static int16_t sf_ReceivePacket(Port_t *thisport);
|
||||
|
||||
/* Flag bit masks...*/
|
||||
#define SENT_SYNCH (0x01)
|
||||
#define ACK_RECEIVED (0x02)
|
||||
#define ACK_EXPECTED (0x04)
|
||||
|
||||
#define SSP_AWAITING_ACK 0
|
||||
#define SSP_ACKED 1
|
||||
#define SSP_IDLE 2
|
||||
|
||||
/** PRIVATE DATA **/
|
||||
static const uint16_t CRC_TABLE[] = {
|
||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||||
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||||
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||||
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||||
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||||
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||||
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||||
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||||
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||||
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||||
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||||
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||||
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||||
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||||
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||||
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||||
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||||
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||||
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||||
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||||
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||||
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||||
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||||
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||||
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||||
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||||
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||||
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||||
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||||
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||||
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
|
||||
};
|
||||
|
||||
/** EXTERNAL DATA **/
|
||||
|
||||
/** EXTERNAL FUNCTIONS **/
|
||||
|
||||
/** VERIFICATION FUNCTIONS **/
|
||||
|
||||
|
||||
/***********************************************************************************************************/
|
||||
|
||||
/*!
|
||||
* \brief Initializes the communication port for use
|
||||
* \param thisport = pointer to port structure to initialize
|
||||
* \param info = config struct with default values.
|
||||
* \return None.
|
||||
*
|
||||
* \note
|
||||
* Must be called before calling the Send or REceive process functions.
|
||||
*/
|
||||
|
||||
void ssp_Init(Port_t *thisport, const PortConfig_t *const info)
|
||||
{
|
||||
thisport->pfCallBack = info->pfCallBack;
|
||||
thisport->pfSerialRead = info->pfSerialRead;
|
||||
thisport->pfSerialWrite = info->pfSerialWrite;
|
||||
thisport->pfGetTime = info->pfGetTime;
|
||||
|
||||
thisport->maxRetryCount = info->max_retry;
|
||||
thisport->timeoutLen = info->timeoutLen;
|
||||
thisport->txBufSize = info->txBufSize;
|
||||
thisport->rxBufSize = info->rxBufSize;
|
||||
thisport->txBuf = info->txBuf;
|
||||
thisport->rxBuf = info->rxBuf;
|
||||
thisport->retryCount = 0;
|
||||
thisport->sendSynch = FALSE; // TRUE;
|
||||
thisport->rxSeqNo = 255;
|
||||
thisport->txSeqNo = 255;
|
||||
thisport->SendState = SSP_IDLE;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Runs the send process, checks for receipt of ack, timeouts and resends if needed.
|
||||
* \param thisport = which port to use
|
||||
* \return SSP_TX_WAITING - waiting for a valid ACK to arrive
|
||||
* \return SSP_TX_TIMEOUT - failed to receive a valid ACK in the timeout period, after retrying.
|
||||
* \return SSP_TX_IDLE - not expecting a ACK packet (no current transmissions in progress)
|
||||
* \return SSP_TX_ACKED - valid ACK received before timeout period.
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
int16_t ssp_SendProcess(Port_t *thisport)
|
||||
{
|
||||
int16_t value = SSP_TX_WAITING;
|
||||
|
||||
if (thisport->SendState == SSP_AWAITING_ACK) {
|
||||
if (sf_CheckTimeout(thisport) == TRUE) {
|
||||
if (thisport->retryCount < thisport->maxRetryCount) {
|
||||
// Try again
|
||||
sf_SendPacket(thisport);
|
||||
sf_SetSendTimeout(thisport);
|
||||
value = SSP_TX_WAITING;
|
||||
} else {
|
||||
// Give up, # of trys has exceded the limit
|
||||
value = SSP_TX_TIMEOUT;
|
||||
CLEARBIT(thisport->flags, ACK_RECEIVED);
|
||||
thisport->SendState = SSP_IDLE;
|
||||
}
|
||||
} else {
|
||||
value = SSP_TX_WAITING;
|
||||
}
|
||||
} else if (thisport->SendState == SSP_ACKED) {
|
||||
SETBIT(thisport->flags, ACK_RECEIVED);
|
||||
value = SSP_TX_ACKED;
|
||||
thisport->SendState = SSP_IDLE;
|
||||
} else {
|
||||
thisport->SendState = SSP_IDLE;
|
||||
value = SSP_TX_IDLE;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Runs the receive process. fetches a byte at a time and runs the byte through the protocol receive state machine.
|
||||
* \param thisport - which port to use.
|
||||
* \return receive status.
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
int16_t ssp_ReceiveProcess(Port_t *thisport)
|
||||
{
|
||||
int16_t b;
|
||||
int16_t packet_status = SSP_RX_IDLE;
|
||||
|
||||
do {
|
||||
b = thisport->pfSerialRead(); // attempt to read a char from the serial buffer
|
||||
if (b != -1) {
|
||||
packet_status = sf_ReceiveState(thisport, b); // process the newly received byte in the receive state machine
|
||||
}
|
||||
// keep going until either we received a full packet or there are no more bytes to process
|
||||
} while (packet_status != SSP_RX_COMPLETE && b != -1);
|
||||
return packet_status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief processes a single byte through the receive state machine.
|
||||
* \param thisport = which port to use
|
||||
* \return current receive status
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
|
||||
int16_t ssp_ReceiveByte(Port_t *thisport)
|
||||
{
|
||||
int16_t b;
|
||||
int16_t packet_status = SSP_RX_IDLE;
|
||||
|
||||
b = thisport->pfSerialRead();
|
||||
if (b != -1) {
|
||||
packet_status = sf_ReceiveState(thisport, b);
|
||||
}
|
||||
return packet_status;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sends a data packet and blocks until timeout or ack is received.
|
||||
* \param thisport = which port to use
|
||||
* \param data = pointer to data to send
|
||||
* \param length = number of data bytes to send. Must be less than 254
|
||||
* \return true = ack was received within number of retries
|
||||
* \return false = ack was not received.
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
uint16_t ssp_SendDataBlock(Port_t *thisport, uint8_t *data, uint16_t length)
|
||||
{
|
||||
int16_t packet_status = SSP_TX_WAITING;
|
||||
uint16_t retval = FALSE;
|
||||
|
||||
packet_status = ssp_SendData(thisport, data, length); // send the data
|
||||
while (packet_status == SSP_TX_WAITING) { // check the status
|
||||
(void)ssp_ReceiveProcess(thisport); // process any bytes received.
|
||||
packet_status = ssp_SendProcess(thisport); // check the send status
|
||||
}
|
||||
if (packet_status == SSP_TX_ACKED) { // figure out what happened to the packet
|
||||
retval = TRUE;
|
||||
} else {
|
||||
retval = FALSE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief sends a chunk of data and does not block
|
||||
* \param thisport = which port to use
|
||||
* \param data = pointer to data to send
|
||||
* \param length = number of bytes to send
|
||||
* \return SSP_TX_BUFOVERRUN = tried to send too much data
|
||||
* \return SSP_TX_WAITING = data sent and waiting for an ack to arrive
|
||||
* \return SSP_TX_BUSY = a packet has already been sent, but not yet acked
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
int16_t ssp_SendData(Port_t *thisport, const uint8_t *data, const uint16_t length)
|
||||
{
|
||||
int16_t value = SSP_TX_WAITING;
|
||||
|
||||
if ((length + 2) > thisport->txBufSize) {
|
||||
// TRYING to send too much data.
|
||||
value = SSP_TX_BUFOVERRUN;
|
||||
} else if (thisport->SendState == SSP_IDLE) {
|
||||
#ifdef ACTIVE_SYNCH
|
||||
if (thisport->sendSynch == TRUE) {
|
||||
sf_SendSynchPacket(thisport);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SYNCH_SEND
|
||||
if (length == 0) {
|
||||
// TODO this method could allow a task/user to start a synchronisation step if a zero is mistakenly passed to this function.
|
||||
// could add a check for a NULL data pointer, or use some sort of static flag that can only be accessed by a static function
|
||||
// that must be called before calling this function.
|
||||
// we are attempting to send a synch packet
|
||||
thisport->txSeqNo = 0; // make this zero to cause the other end to re-synch with us
|
||||
SETBIT(thisport->flags, SENT_SYNCH);
|
||||
} else {
|
||||
// we are sending a data packet
|
||||
CLEARBIT(thisport->txSeqNo, ACK_BIT); // make sure we are not sending a ACK packet
|
||||
thisport->txSeqNo++; // update the sequence number.
|
||||
if (thisport->txSeqNo > 0x7F) { // check for sequence number rollover
|
||||
thisport->txSeqNo = 1; // if we do have rollover then reset to 1 not zero,
|
||||
// zero is reserviced for synchronization requests
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
CLEARBIT(thisport->txSeqNo, ACK_BIT); // make sure we are not sending a ACK packet
|
||||
thisport->txSeqNo++; // update the sequence number.
|
||||
if (thisport->txSeqNo > 0x7F) { // check for sequence number rollover
|
||||
thisport->txSeqNo = 1; // if we do have rollover then reset to 1 not zero,
|
||||
// zero is reserved for synchronization requests
|
||||
}
|
||||
#endif // ifdef SYNCH_SEND
|
||||
CLEARBIT(thisport->flags, ACK_RECEIVED);
|
||||
thisport->SendState = SSP_AWAITING_ACK;
|
||||
value = SSP_TX_WAITING;
|
||||
thisport->retryCount = 0; // zero out the retry counter for this transmission
|
||||
sf_MakePacket(thisport->txBuf, data, length, thisport->txSeqNo);
|
||||
sf_SendPacket(thisport); // punch out the packet to the serial port
|
||||
sf_SetSendTimeout(thisport); // do the timeout values
|
||||
} else {
|
||||
// error we are already sending a packet. Need to wait for the current packet to be acked or timeout.
|
||||
value = SSP_TX_BUSY;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Attempts to synchronize the sequence numbers with the other end of the connectin.
|
||||
* \param thisport = which port to use
|
||||
* \return true = success
|
||||
* \return false = failed to receive an ACK to our synch request
|
||||
*
|
||||
* \note
|
||||
* A. send a packet with a sequence number equal to zero
|
||||
* B. if timed out then:
|
||||
* send synch packet again
|
||||
* increment try counter
|
||||
* if number of tries exceed maximum try limit then exit
|
||||
* C. goto A
|
||||
*/
|
||||
uint16_t ssp_Synchronise(Port_t *thisport)
|
||||
{
|
||||
int16_t packet_status;
|
||||
uint16_t retval = FALSE;
|
||||
|
||||
#ifndef USE_SENDPACKET_DATA
|
||||
thisport->txSeqNo = 0; // make this zero to cause the other end to re-synch with us
|
||||
SETBIT(thisport->flags, SENT_SYNCH);
|
||||
// TODO - should this be using ssp_SendPacketData()??
|
||||
sf_MakePacket(thisport->txBuf, NULL, 0, thisport->txSeqNo); // construct the packet
|
||||
sf_SendPacket(thisport);
|
||||
sf_SetSendTimeout(thisport);
|
||||
thisport->SendState = SSP_AWAITING_ACK;
|
||||
packet_status = SSP_TX_WAITING;
|
||||
#else
|
||||
packet_status = ssp_SendData(thisport, NULL, 0);
|
||||
#endif
|
||||
while (packet_status == SSP_TX_WAITING) { // we loop until we time out.
|
||||
(void)ssp_ReceiveProcess(thisport); // do the receive process
|
||||
packet_status = ssp_SendProcess(thisport); // do the send process
|
||||
}
|
||||
thisport->sendSynch = FALSE;
|
||||
switch (packet_status) {
|
||||
case SSP_TX_ACKED:
|
||||
retval = TRUE;
|
||||
break;
|
||||
case SSP_TX_BUSY: // intentional fall through.
|
||||
case SSP_TX_TIMEOUT: // intentional fall through.
|
||||
case SSP_TX_BUFOVERRUN:
|
||||
retval = FALSE;
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief sends out a preformatted packet for a give port
|
||||
* \param thisport = which port to use.
|
||||
* \return none.
|
||||
*
|
||||
* \note
|
||||
* Packet should be formed through the use of sf_MakePacket before calling this function.
|
||||
*/
|
||||
static void sf_SendPacket(Port_t *thisport)
|
||||
{
|
||||
// add 3 to packet data length for: 1 length + 2 CRC (packet overhead)
|
||||
uint8_t packetLen = thisport->txBuf[LENGTH] + 3;
|
||||
|
||||
// use the raw serial write function so the SYNC byte does not get 'escaped'
|
||||
thisport->pfSerialWrite(SYNC);
|
||||
for (uint8_t x = 0; x < packetLen; x++) {
|
||||
sf_write_byte(thisport, thisport->txBuf[x]);
|
||||
}
|
||||
thisport->retryCount++;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief converts data to transport layer protocol packet format.
|
||||
* \param txbuf = buffer to use when forming the packet
|
||||
* \param pdata = pointer to data to use
|
||||
* \param length = number of bytes to use
|
||||
* \param seqNo = sequence number of this packet
|
||||
* \return none.
|
||||
*
|
||||
* \note
|
||||
* 1. This function does not try to interpret ACK or SYNCH packets. This should
|
||||
* be done by the caller of this function.
|
||||
* 2. This function will attempt to format all data upto the size of the tx buffer.
|
||||
* Any extra data beyond that will be ignored.
|
||||
* 3. TODO: Should this function return an error if data length to be sent is greater th tx buffer size?
|
||||
*
|
||||
*/
|
||||
void sf_MakePacket(uint8_t *txBuf, const uint8_t *pdata, uint16_t length, uint8_t seqNo)
|
||||
{
|
||||
uint16_t crc = 0xffff;
|
||||
uint16_t bufPos = 0;
|
||||
uint8_t b;
|
||||
|
||||
// add 1 for the seq. number
|
||||
txBuf[LENGTH] = length + 1;
|
||||
txBuf[SEQNUM] = seqNo;
|
||||
crc = sf_crc16(crc, seqNo);
|
||||
|
||||
length = length + 2; // add two for the length and seqno bytes which are added before the loop.
|
||||
for (bufPos = 2; bufPos < length; bufPos++) {
|
||||
b = *pdata++;
|
||||
txBuf[bufPos] = b;
|
||||
crc = sf_crc16(crc, b); // update CRC value
|
||||
}
|
||||
txBuf[bufPos++] = LOWERBYTE(crc);
|
||||
txBuf[bufPos] = UPPERBYTE(crc);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief sends out an ack packet to given sequence number
|
||||
* \param thisport = which port to use
|
||||
* \param seqNumber = sequence number of the packet we would like to ack
|
||||
* \return none.
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
|
||||
static void sf_SendAckPacket(Port_t *thisport, uint8_t seqNumber)
|
||||
{
|
||||
uint8_t AckSeqNumber = SETBIT(seqNumber, ACK_BIT);
|
||||
|
||||
// create the packet, note we pass AckSequenceNumber directly
|
||||
sf_MakePacket(thisport->txBuf, NULL, 0, AckSeqNumber);
|
||||
sf_SendPacket(thisport);
|
||||
// we don't set the timeout for an ACK because we don't ACK our ACKs in this protocol
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief writes a byte out the output channel. Adds escape byte where needed
|
||||
* \param thisport = which port to use
|
||||
* \param c = byte to send
|
||||
* \return none.
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
static void sf_write_byte(Port_t *thisport, uint8_t c)
|
||||
{
|
||||
if (c == SYNC) { // check for SYNC byte
|
||||
thisport->pfSerialWrite(ESC); // since we are not starting a packet we must ESCAPE the SYNCH byte
|
||||
thisport->pfSerialWrite(ESC_SYNC); // now send the escaped synch char
|
||||
} else if (c == ESC) { // Check for ESC character
|
||||
thisport->pfSerialWrite(ESC); // if it is, we need to send it twice
|
||||
thisport->pfSerialWrite(ESC);
|
||||
} else {
|
||||
thisport->pfSerialWrite(c); // otherwise write the byte to serial port
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************
|
||||
*
|
||||
* NAME: uint16_t ssp_crc16( uint16_t crc, uint16_t data )
|
||||
* DESCRIPTION: Uses crc_table to calculate new crc
|
||||
* ARGUMENTS:
|
||||
* arg1: crc
|
||||
* arg2: data - byte to calculate into CRC
|
||||
* RETURN: New crc
|
||||
* CREATED: 5/8/02
|
||||
*
|
||||
*************************************************************************************************************/
|
||||
/*!
|
||||
* \brief calculates the new CRC value for 'data'
|
||||
* \param crc = current CRC value
|
||||
* \param data = new byte
|
||||
* \return updated CRC value
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
|
||||
static uint16_t sf_crc16(uint16_t crc, uint8_t data)
|
||||
{
|
||||
return (crc >> 8) ^ CRC_TABLE[(crc ^ data) & 0x00FF];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief sets the timeout for the given packet
|
||||
* \param thisport = which port to use
|
||||
* \return none.
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
|
||||
static void sf_SetSendTimeout(Port_t *thisport)
|
||||
{
|
||||
uint32_t timeout;
|
||||
|
||||
timeout = thisport->pfGetTime() + thisport->timeoutLen;
|
||||
thisport->timeout = timeout;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief checks to see if a timeout occured
|
||||
* \param thisport = which port to use
|
||||
* \return true = a timeout has occurred
|
||||
* \return false = has not timed out
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
static uint16_t sf_CheckTimeout(Port_t *thisport)
|
||||
{
|
||||
uint16_t retval = FALSE;
|
||||
uint32_t current_time;
|
||||
|
||||
current_time = thisport->pfGetTime();
|
||||
if (current_time > thisport->timeout) {
|
||||
retval = TRUE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* NAME: sf_ReceiveState
|
||||
* DESC: Implements the receive state handling code for escaped and unescaped data
|
||||
* ARGS: thisport - which port to operate on
|
||||
* c - incoming byte
|
||||
* RETURN:
|
||||
* CREATED:
|
||||
* NOTES:
|
||||
* 1. change from using pointer to functions.
|
||||
****************************************************************************/
|
||||
/*!
|
||||
* \brief implements the receive state handling code for escaped and unescaped data
|
||||
* \param thisport = which port to use
|
||||
* \param c = byte to process through the receive state machine
|
||||
* \return receive status
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
static int16_t sf_ReceiveState(Port_t *thisport, uint8_t c)
|
||||
{
|
||||
int16_t retval = SSP_RX_RECEIVING;
|
||||
|
||||
switch (thisport->InputState) {
|
||||
case state_unescaped_e:
|
||||
if (c == SYNC) {
|
||||
thisport->DecodeState = decode_len1_e;
|
||||
} else if (c == ESC) {
|
||||
thisport->InputState = state_escaped_e;
|
||||
} else {
|
||||
retval = sf_DecodeState(thisport, c);
|
||||
}
|
||||
break; // end of unescaped state.
|
||||
case state_escaped_e:
|
||||
thisport->InputState = state_unescaped_e;
|
||||
if (c == SYNC) {
|
||||
thisport->DecodeState = decode_len1_e;
|
||||
} else if (c == ESC_SYNC) {
|
||||
retval = sf_DecodeState(thisport, SYNC);
|
||||
} else {
|
||||
retval = sf_DecodeState(thisport, c);
|
||||
}
|
||||
break; // end of the escaped state.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* NAME: sf_DecodeState
|
||||
* DESC: Implements the receive state finite state machine
|
||||
* ARGS: thisport - which port to operate on
|
||||
* c - incoming byte
|
||||
* RETURN:
|
||||
* CREATED:
|
||||
* NOTES:
|
||||
* 1. change from using pointer to functions.
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
* \brief implements the receiving decoding state machine
|
||||
* \param thisport = which port to use
|
||||
* \param c = byte to process
|
||||
* \return receive status
|
||||
*
|
||||
* \note
|
||||
*
|
||||
*/
|
||||
static int16_t sf_DecodeState(Port_t *thisport, uint8_t c)
|
||||
{
|
||||
int16_t retval;
|
||||
|
||||
switch (thisport->DecodeState) {
|
||||
case decode_idle_e:
|
||||
// 'c' is ignored in this state as the only way to leave the idle state is
|
||||
// recognition of the SYNC byte in the sf_ReceiveState function.
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
case decode_len1_e:
|
||||
thisport->rxBuf[LENGTH] = c;
|
||||
thisport->rxBufLen = c;
|
||||
if (thisport->rxBufLen <= thisport->rxBufSize) {
|
||||
thisport->DecodeState = decode_seqNo_e;
|
||||
retval = SSP_RX_RECEIVING;
|
||||
} else {
|
||||
thisport->DecodeState = decode_idle_e;
|
||||
retval = SSP_RX_IDLE;
|
||||
}
|
||||
break;
|
||||
case decode_seqNo_e:
|
||||
thisport->rxBuf[SEQNUM] = c;
|
||||
thisport->crc = 0xffff;
|
||||
thisport->rxBufLen--; // subtract 1 for the seq. no.
|
||||
thisport->rxBufPos = 2;
|
||||
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
if (thisport->rxBufLen > 0) {
|
||||
thisport->DecodeState = decode_data_e;
|
||||
} else {
|
||||
thisport->DecodeState = decode_crc1_e;
|
||||
}
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_data_e:
|
||||
thisport->rxBuf[(thisport->rxBufPos)++] = c;
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
if (thisport->rxBufPos == (thisport->rxBufLen + 2)) {
|
||||
thisport->DecodeState = decode_crc1_e;
|
||||
}
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_crc1_e:
|
||||
thisport->crc = sf_crc16(thisport->crc, c);
|
||||
thisport->DecodeState = decode_crc2_e;
|
||||
retval = SSP_RX_RECEIVING;
|
||||
break;
|
||||
case decode_crc2_e:
|
||||
thisport->DecodeState = decode_idle_e;
|
||||
// verify the CRC value for the packet
|
||||
if (sf_crc16(thisport->crc, c) == 0) {
|
||||
// TODO shouldn't the return value of sf_ReceivePacket() be checked?
|
||||
sf_ReceivePacket(thisport);
|
||||
retval = SSP_RX_COMPLETE;
|
||||
} else {
|
||||
thisport->RxError++;
|
||||
retval = SSP_RX_IDLE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
thisport->DecodeState = decode_idle_e; // unknown state so reset to idle state and wait for the next start of a packet.
|
||||
retval = SSP_RX_IDLE;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/************************************************************************************************************
|
||||
*
|
||||
* NAME: int16_t sf_ReceivePacket( )
|
||||
* DESCRIPTION: Receive one packet, assumed that data is in rec.buff[]
|
||||
* ARGUMENTS:
|
||||
* RETURN: 0 . no new packet was received, could be ack or same packet
|
||||
* 1 . new packet received
|
||||
* SSP_PACKET_?
|
||||
* SSP_PACKET_COMPLETE
|
||||
* SSP_PACKET_ACK
|
||||
* CREATED: 5/8/02
|
||||
*
|
||||
*************************************************************************************************************/
|
||||
/*!
|
||||
* \brief receive one packet. calls the callback function if needed.
|
||||
* \param thisport = which port to use
|
||||
* \return true = valid data packet received.
|
||||
* \return false = otherwise
|
||||
*
|
||||
* \note
|
||||
*
|
||||
* Created: Oct 7, 2010 12:07:22 AM by joe
|
||||
*/
|
||||
|
||||
static int16_t sf_ReceivePacket(Port_t *thisport)
|
||||
{
|
||||
int16_t value = FALSE;
|
||||
|
||||
if (ISBITSET(thisport->rxBuf[SEQNUM], ACK_BIT)) {
|
||||
// Received an ACK packet, need to check if it matches the previous sent packet
|
||||
if ((thisport->rxBuf[SEQNUM] & 0x7F) == (thisport->txSeqNo & 0x7f)) {
|
||||
// It matches the last packet sent by us
|
||||
SETBIT(thisport->txSeqNo, ACK_BIT);
|
||||
thisport->SendState = SSP_ACKED;
|
||||
value = FALSE;
|
||||
}
|
||||
// else ignore the ACK packet
|
||||
} else {
|
||||
// Received a 'data' packet, figure out what type of packet we received...
|
||||
if (thisport->rxBuf[SEQNUM] == 0) {
|
||||
// Synchronize sequence number with host
|
||||
#ifdef ACTIVE_SYNCH
|
||||
thisport->sendSynch = TRUE;
|
||||
#endif
|
||||
sf_SendAckPacket(thisport, thisport->rxBuf[SEQNUM]);
|
||||
thisport->rxSeqNo = 0;
|
||||
value = FALSE;
|
||||
} else if (thisport->rxBuf[SEQNUM] == thisport->rxSeqNo) {
|
||||
// Already seen this packet, just ack it, don't act on the packet.
|
||||
sf_SendAckPacket(thisport, thisport->rxBuf[SEQNUM]);
|
||||
value = FALSE;
|
||||
} else {
|
||||
// New Packet
|
||||
thisport->rxSeqNo = thisport->rxBuf[SEQNUM];
|
||||
// Let the application do something with the data/packet.
|
||||
if (thisport->pfCallBack != NULL) {
|
||||
// skip the first two bytes (length and seq. no.) in the buffer.
|
||||
thisport->pfCallBack(&(thisport->rxBuf[2]), thisport->rxBufLen);
|
||||
}
|
||||
// after we send the ACK, it is possible for the host to send a new packet.
|
||||
// Thus the application needs to copy the data and reset the receive buffer
|
||||
// inside of thisport->pfCallBack()
|
||||
sf_SendAckPacket(thisport, thisport->rxBuf[SEQNUM]);
|
||||
value = TRUE;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
118
ground/gcs/src/plugins/uploader/SSP/ssp.h
Normal file
118
ground/gcs/src/plugins/uploader/SSP/ssp.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME: ssp.h
|
||||
*
|
||||
*
|
||||
*******************************************************************/
|
||||
#ifndef SSP_H
|
||||
#define SSP_H
|
||||
/** INCLUDE FILES **/
|
||||
#include <stdint.h>
|
||||
|
||||
/** LOCAL DEFINITIONS **/
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#define SSP_TX_IDLE 0 // not expecting a ACK packet (no current transmissions in progress)
|
||||
#define SSP_TX_WAITING 1 // waiting for a valid ACK to arrive
|
||||
#define SSP_TX_TIMEOUT 2 // failed to receive a valid ACK in the timeout period, after retrying.
|
||||
#define SSP_TX_ACKED 3 // valid ACK received before timeout period.
|
||||
#define SSP_TX_BUFOVERRUN 4 // amount of data to send execeds the transmission buffer sizeof
|
||||
#define SSP_TX_BUSY 5 // Attempted to start a transmission while a transmission was already in progress.
|
||||
// #define SSP_TX_FAIL - failure...
|
||||
|
||||
#define SSP_RX_IDLE 0
|
||||
#define SSP_RX_RECEIVING 1
|
||||
#define SSP_RX_COMPLETE 2
|
||||
|
||||
// types of packet that can be received
|
||||
#define SSP_RX_DATA 5
|
||||
#define SSP_RX_ACK 6
|
||||
#define SSP_RX_SYNCH 7
|
||||
|
||||
typedef enum decodeState_ {
|
||||
decode_len1_e = 0,
|
||||
decode_seqNo_e,
|
||||
decode_data_e,
|
||||
decode_crc1_e,
|
||||
decode_crc2_e,
|
||||
decode_idle_e
|
||||
} DecodeState_t;
|
||||
|
||||
typedef enum ReceiveState {
|
||||
state_escaped_e = 0,
|
||||
state_unescaped_e
|
||||
} ReceiveState_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *pbuff;
|
||||
uint16_t length;
|
||||
uint16_t crc;
|
||||
uint8_t seqNo;
|
||||
} Packet_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *rxBuf; // Buffer used to store rcv data
|
||||
uint16_t rxBufSize; // rcv buffer size.
|
||||
uint8_t *txBuf; // Length of data in buffer
|
||||
uint16_t txBufSize; // CRC for data in Packet buff
|
||||
uint16_t max_retry; // Maximum number of retrys for a single transmit.
|
||||
int32_t timeoutLen; // how long to wait for each retry to succeed
|
||||
void (*pfCallBack)(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
|
||||
int16_t (*pfSerialRead)(void); // function to call to read a byte from serial hardware
|
||||
void (*pfSerialWrite)(uint8_t); // function used to write a byte to serial hardware for transmission
|
||||
uint32_t (*pfGetTime)(void); // function returns time in number of seconds that has elapsed from a given reference point
|
||||
} PortConfig_t;
|
||||
|
||||
typedef struct Port_tag {
|
||||
void (*pfCallBack)(uint8_t *, uint16_t); // call back function that is called when a full packet has been received
|
||||
int16_t (*pfSerialRead)(void); // function to read a character from the serial input stream
|
||||
void (*pfSerialWrite)(uint8_t); // function to write a byte to be sent out the serial port
|
||||
uint32_t (*pfGetTime)(void); // function returns time in number of seconds that has elapsed from a given reference point
|
||||
uint8_t retryCount; // how many times have we tried to transmit the 'send' packet
|
||||
uint8_t maxRetryCount; // max. times to try to transmit the 'send' packet
|
||||
int32_t timeoutLen; // how long to wait for each retry to succeed
|
||||
int32_t timeout; // current timeout. when 'time' reaches this point we have timed out
|
||||
uint8_t txSeqNo; // current 'send' packet sequence number
|
||||
uint16_t rxBufPos; // current buffer position in the receive packet
|
||||
uint16_t rxBufLen; // number of 'data' bytes in the buffer
|
||||
uint8_t rxSeqNo; // current 'receive' packet number
|
||||
uint16_t rxBufSize; // size of the receive buffer.
|
||||
uint16_t txBufSize; // size of the transmit buffer.
|
||||
uint8_t *txBuf; // transmit buffer. REquired to store a copy of packet data in case a retry is needed.
|
||||
uint8_t *rxBuf; // receive buffer. Used to store data as a packet is received.
|
||||
uint16_t sendSynch; // flag to indicate that we should send a synchronize packet to the host
|
||||
// this is required when switching from the application to the bootloader
|
||||
// and vice-versa. This fixes the firwmare download timeout.
|
||||
// when this flag is set to true, the next time we send a packet we will first
|
||||
// send a synchronize packet.
|
||||
ReceiveState_t InputState;
|
||||
DecodeState_t DecodeState;
|
||||
uint16_t SendState;
|
||||
uint16_t crc;
|
||||
uint32_t RxError;
|
||||
uint32_t TxError;
|
||||
uint16_t flags;
|
||||
} Port_t;
|
||||
|
||||
|
||||
/** Public Data **/
|
||||
|
||||
/** PUBLIC FUNCTIONS **/
|
||||
int16_t ssp_ReceiveProcess(Port_t *thisport);
|
||||
int16_t ssp_SendProcess(Port_t *thisport);
|
||||
uint16_t ssp_SendString(Port_t *thisport, char *str);
|
||||
int16_t ssp_SendData(Port_t *thisport, const uint8_t *data, const uint16_t length);
|
||||
void ssp_Init(Port_t *thisport, const PortConfig_t *const info);
|
||||
int16_t ssp_ReceiveByte(Port_t *thisport);
|
||||
uint16_t ssp_Synchronise(Port_t *thisport);
|
||||
|
||||
|
||||
/** EXTERNAL FUNCTIONS **/
|
||||
|
||||
#endif // ifndef SSP_H
|
50
ground/gcs/src/plugins/uploader/SSP/ssp_test.pro
Normal file
50
ground/gcs/src/plugins/uploader/SSP/ssp_test.pro
Normal file
@ -0,0 +1,50 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2010-07-24T11:26:38
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = ssp_test
|
||||
|
||||
QT += core
|
||||
QT -= gui
|
||||
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
DEFINES += QEXTSERIALPORT_LIBRARY
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
qssp.cpp \
|
||||
port.cpp \
|
||||
qsspt.cpp
|
||||
|
||||
HEADERS += \
|
||||
../../../libs/qextserialport/src/qextserialport.h \
|
||||
../../../libs/qextserialport/src/qextserialenumerator.h \
|
||||
../../../libs/qextserialport/src/qextserialport_global.h \
|
||||
qssp.h \
|
||||
port.h \
|
||||
common.h \
|
||||
qsspt.h
|
||||
|
||||
SOURCES += ../../../libs/qextserialport/src/qextserialport.cpp
|
||||
|
||||
unix:SOURCES += ../../../libs/qextserialport/src/posix_qextserialport.cpp
|
||||
unix:!macx:SOURCES += ../../../libs/qextserialport/src/qextserialenumerator_unix.cpp
|
||||
macx {
|
||||
SOURCES += ../../../libs/qextserialport/src/qextserialenumerator_osx.cpp
|
||||
LIBS += -framework IOKit -framework CoreFoundation
|
||||
}
|
||||
|
||||
win32 {
|
||||
SOURCES += \
|
||||
../../../libs/qextserialport/src/win_qextserialport.cpp \
|
||||
../../../libs/qextserialport/src/qextserialenumerator_win.cpp
|
||||
|
||||
# needed for mingw to pull in appropriate dbt business...probably a better way to do this
|
||||
DEFINES += WINVER=0x0501
|
||||
LIBS += -lsetupapi
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "delay.h"
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#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
|
@ -27,6 +27,11 @@
|
||||
*/
|
||||
#include "devicewidget.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
DeviceWidget::DeviceWidget(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
@ -132,7 +137,7 @@ void DeviceWidget::populate()
|
||||
myDevice->lblMaxCode->setText(tr("Max code size: ") + QString::number(m_dfu->devices[deviceID].SizeOfCode));
|
||||
myDevice->lblCRC->setText(QString::number(m_dfu->devices[deviceID].FW_CRC));
|
||||
myDevice->lblBLVer->setText(tr("BL version: ") + QString::number(m_dfu->devices[deviceID].BL_Version));
|
||||
int size = ((OP_DFU::device)m_dfu->devices[deviceID]).SizeOfDesc;
|
||||
int size = ((DFU::device)m_dfu->devices[deviceID]).SizeOfDesc;
|
||||
m_dfu->enterDFU(deviceID);
|
||||
QByteArray desc = m_dfu->DownloadDescriptionAsBA(size);
|
||||
|
||||
@ -409,13 +414,13 @@ void DeviceWidget::uploadFirmware()
|
||||
updateButtons(true);
|
||||
return;
|
||||
}
|
||||
OP_DFU::Status ret = m_dfu->StatusRequest();
|
||||
DFU::Status ret = m_dfu->StatusRequest();
|
||||
qDebug() << m_dfu->StatusToString(ret);
|
||||
m_dfu->AbortOperation(); // Necessary, otherwise I get random failures.
|
||||
|
||||
connect(m_dfu, SIGNAL(progressUpdated(int)), this, SLOT(setProgress(int)));
|
||||
connect(m_dfu, SIGNAL(operationProgress(QString)), this, SLOT(dfuStatus(QString)));
|
||||
connect(m_dfu, SIGNAL(uploadFinished(OP_DFU::Status)), this, SLOT(uploadFinished(OP_DFU::Status)));
|
||||
connect(m_dfu, SIGNAL(uploadFinished(DFU::Status)), this, SLOT(uploadFinished(DFU::Status)));
|
||||
bool retstatus = m_dfu->UploadFirmware(filename, verify, deviceID);
|
||||
if (!retstatus) {
|
||||
emit uploadEnded(false);
|
||||
@ -478,7 +483,7 @@ void DeviceWidget::downloadFinished()
|
||||
disconnect(m_dfu, SIGNAL(downloadFinished()), this, SLOT(downloadFinished()));
|
||||
disconnect(m_dfu, SIGNAL(progressUpdated(int)), this, SLOT(setProgress(int)));
|
||||
|
||||
// Now save the result (use the utility function from OP_DFU)
|
||||
// Now save the result (use the utility function from DFU)
|
||||
m_dfu->SaveByteArrayToFile(filename, downloadedFirmware);
|
||||
|
||||
emit downloadEnded(true);
|
||||
@ -489,13 +494,13 @@ void DeviceWidget::downloadFinished()
|
||||
/**
|
||||
Callback for the firmware upload result
|
||||
*/
|
||||
void DeviceWidget::uploadFinished(OP_DFU::Status retstatus)
|
||||
void DeviceWidget::uploadFinished(DFU::Status retstatus)
|
||||
{
|
||||
disconnect(m_dfu, SIGNAL(uploadFinished(OP_DFU::Status)), this, SLOT(uploadFinished(OP_DFU::Status)));
|
||||
disconnect(m_dfu, SIGNAL(uploadFinished(DFU::Status)), this, SLOT(uploadFinished(DFU::Status)));
|
||||
disconnect(m_dfu, SIGNAL(progressUpdated(int)), this, SLOT(setProgress(int)));
|
||||
disconnect(m_dfu, SIGNAL(operationProgress(QString)), this, SLOT(dfuStatus(QString)));
|
||||
|
||||
if (retstatus != OP_DFU::Last_operation_Success) {
|
||||
if (retstatus != DFU::Last_operation_Success) {
|
||||
emit uploadEnded(false);
|
||||
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
||||
updateButtons(true);
|
||||
@ -505,7 +510,7 @@ void DeviceWidget::uploadFinished(OP_DFU::Status retstatus)
|
||||
status(QString("Updating description"), STATUSICON_RUNNING);
|
||||
repaint(); // Make sure the text above shows right away
|
||||
retstatus = m_dfu->UploadDescription(descriptionArray);
|
||||
if (retstatus != OP_DFU::Last_operation_Success) {
|
||||
if (retstatus != DFU::Last_operation_Success) {
|
||||
emit uploadEnded(false);
|
||||
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
||||
updateButtons(true);
|
||||
@ -516,7 +521,7 @@ void DeviceWidget::uploadFinished(OP_DFU::Status retstatus)
|
||||
status(QString("Updating description"), STATUSICON_RUNNING);
|
||||
repaint(); // Make sure the text above shows right away
|
||||
retstatus = m_dfu->UploadDescription(myDevice->description->text());
|
||||
if (retstatus != OP_DFU::Last_operation_Success) {
|
||||
if (retstatus != DFU::Last_operation_Success) {
|
||||
emit uploadEnded(false);
|
||||
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
||||
updateButtons(true);
|
||||
|
@ -29,22 +29,18 @@
|
||||
#define DEVICEWIDGET_H
|
||||
|
||||
#include "ui_devicewidget.h"
|
||||
|
||||
#include "uploader_global.h"
|
||||
#include "uploadergadgetwidget.h"
|
||||
#include "op_dfu.h"
|
||||
#include <QWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QErrorMessage>
|
||||
#include <QByteArray>
|
||||
#include <QtSvg/QGraphicsSvgItem>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include "dfu.h"
|
||||
#include "uavobjectutilmanager.h"
|
||||
#include "devicedescriptorstruct.h"
|
||||
#include <QDir>
|
||||
#include <QCoreApplication>
|
||||
#include "uploader_global.h"
|
||||
|
||||
using namespace OP_DFU;
|
||||
#include <QWidget>
|
||||
#include <QByteArray>
|
||||
|
||||
using namespace DFU;
|
||||
class UPLOADER_EXPORT DeviceWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -87,7 +83,7 @@ public slots:
|
||||
void downloadFirmware();
|
||||
void setProgress(int);
|
||||
void downloadFinished();
|
||||
void uploadFinished(OP_DFU::Status);
|
||||
void uploadFinished(DFU::Status);
|
||||
void dfuStatus(QString);
|
||||
void confirmCB(int);
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file op_dfu.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @file dfu.cpp
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Uploader Plugin
|
||||
@ -24,25 +25,37 @@
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "dfu.h"
|
||||
|
||||
#include "op_dfu.h"
|
||||
#include "SSP/port.h"
|
||||
#include "SSP/qsspt.h"
|
||||
|
||||
#include <ophid/inc/ophid_hidapi.h>
|
||||
#include <ophid/inc/ophid_usbmon.h>
|
||||
#include <ophid/inc/ophid_usbsignal.h>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <qwaitcondition.h>
|
||||
#include <QMetaType>
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
using namespace OP_DFU;
|
||||
using namespace std;
|
||||
using namespace DFU;
|
||||
|
||||
DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
debug(_debug), use_serial(_use_serial), mready(true)
|
||||
{
|
||||
info = NULL;
|
||||
numberOfDevices = 0;
|
||||
serialhandle = NULL;
|
||||
port *info = NULL;
|
||||
|
||||
qRegisterMetaType<OP_DFU::Status>("Status");
|
||||
qRegisterMetaType<DFU::Status>("Status");
|
||||
|
||||
if (use_serial) {
|
||||
info = new port(portname);
|
||||
info = new port(portname, false);
|
||||
info->rxBuf = sspRxBuf;
|
||||
info->rxBufSize = MAX_PACKET_DATA_LEN;
|
||||
info->txBuf = sspTxBuf;
|
||||
@ -54,42 +67,50 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
mready = false;
|
||||
return;
|
||||
}
|
||||
serialhandle = new qsspt(info, debug);
|
||||
serialhandle = new qsspt(info, false /*debug*/);
|
||||
|
||||
int count = 0;
|
||||
while ((serialhandle->ssp_Synchronise() == false) && (count < 10)) {
|
||||
while (!serialhandle->ssp_Synchronise() && (count < 10)) {
|
||||
if (debug) {
|
||||
qDebug() << "SYNC failed, resending";
|
||||
qDebug() << "SYNC failed, resending...";
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (count == 10) {
|
||||
mready = false;
|
||||
qDebug() << "SYNC failed";
|
||||
return;
|
||||
}
|
||||
qDebug() << "SYNC Succeded";
|
||||
|
||||
// transfer ownership of port to serialhandle thread
|
||||
info->moveToThread(serialhandle);
|
||||
connect(serialhandle, SIGNAL(finished()), info, SLOT(deleteLater()));
|
||||
|
||||
// start the serialhandle thread
|
||||
serialhandle->start();
|
||||
} else {
|
||||
mready = false;
|
||||
hidHandle = new opHID_hidapi();
|
||||
|
||||
mready = false;
|
||||
QEventLoop m_eventloop;
|
||||
QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
|
||||
m_eventloop.exec();
|
||||
QList<USBPortInfo> devices;
|
||||
devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
|
||||
if (devices.length() == 1) {
|
||||
if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
mready = true;
|
||||
QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
|
||||
m_eventloop.exec();
|
||||
} else {
|
||||
hidHandle.close(0);
|
||||
hidHandle->close(0);
|
||||
}
|
||||
} else {
|
||||
// Wait for the board to appear on the USB bus:
|
||||
USBSignalFilter filter(0x20a0, -1, -1, USBMonitor::Bootloader);
|
||||
connect(&filter, SIGNAL(deviceDiscovered()), &m_eventloop, SLOT(quit()));
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
qDebug() << "OP_DFU trying to detect bootloader:" << x;
|
||||
qDebug() << "DFU trying to detect bootloader:" << x;
|
||||
|
||||
if (x == 0) {
|
||||
QTimer::singleShot(10000, &m_eventloop, SLOT(quit()));
|
||||
@ -101,15 +122,15 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
qDebug() << "Devices length: " << devices.length();
|
||||
if (devices.length() == 1) {
|
||||
qDebug() << "Opening device";
|
||||
if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
|
||||
QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
|
||||
m_eventloop.exec();
|
||||
qDebug() << "OP_DFU detected after delay";
|
||||
qDebug() << "DFU detected after delay";
|
||||
mready = true;
|
||||
qDebug() << "Detected";
|
||||
break;
|
||||
} else {
|
||||
hidHandle.close(0);
|
||||
hidHandle->close(0);
|
||||
}
|
||||
} else {
|
||||
qDebug() << devices.length() << " device(s) detected, don't know what to do!";
|
||||
@ -123,12 +144,12 @@ DFUObject::DFUObject(bool _debug, bool _use_serial, QString portname) :
|
||||
DFUObject::~DFUObject()
|
||||
{
|
||||
if (use_serial) {
|
||||
if (mready) {
|
||||
delete serialhandle;
|
||||
delete info;
|
||||
}
|
||||
delete serialhandle;
|
||||
} else {
|
||||
hidHandle.close(0);
|
||||
if (hidHandle) {
|
||||
hidHandle->close(0);
|
||||
delete hidHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +159,7 @@ bool DFUObject::SaveByteArrayToFile(QString const & sfile, const QByteArray &arr
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
if (debug) {
|
||||
qDebug() << "Can't open file";
|
||||
qDebug() << "Can't open file" << sfile;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -155,7 +176,7 @@ bool DFUObject::enterDFU(int const &devNumber)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::EnterDFU; // DFU Command
|
||||
buf[1] = DFU::EnterDFU; // DFU Command
|
||||
buf[2] = 0; // DFU Count
|
||||
buf[3] = 0; // DFU Count
|
||||
buf[4] = 0; // DFU Count
|
||||
@ -194,7 +215,7 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
|
||||
}
|
||||
char buf[BUF_LEN];
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = setStartBit(OP_DFU::Upload); // DFU Command
|
||||
buf[1] = setStartBit(DFU::Upload); // DFU Command
|
||||
buf[2] = numberOfPackets >> 24; // DFU Count
|
||||
buf[3] = numberOfPackets >> 16; // DFU Count
|
||||
buf[4] = numberOfPackets >> 8; // DFU Count
|
||||
@ -210,7 +231,7 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
|
||||
}
|
||||
|
||||
int result = sendData(buf, BUF_LEN);
|
||||
delay::msleep(1000);
|
||||
QThread::msleep(1000);
|
||||
|
||||
if (debug) {
|
||||
qDebug() << result << " bytes sent";
|
||||
@ -221,7 +242,6 @@ bool DFUObject::StartUpload(qint32 const & numberOfBytes, TransferTypes const &
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Does the actual data upload to the board. Needs to be called once the
|
||||
board is ready to accept data following a StartUpload command, and it is erased.
|
||||
@ -243,7 +263,7 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
||||
}
|
||||
char buf[BUF_LEN];
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Upload; // DFU Command
|
||||
buf[1] = DFU::Upload; // DFU Command
|
||||
int packetsize;
|
||||
float percentage;
|
||||
int laspercentage = 0;
|
||||
@ -265,40 +285,43 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
||||
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];
|
||||
// if (debug) {
|
||||
// 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)
|
||||
// {
|
||||
|
||||
// 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);
|
||||
// QThread::msleep(send_delay);
|
||||
|
||||
// if(StatusRequest()!=OP_DFU::uploading) return false;
|
||||
// if (StatusRequest() != DFU::uploading) {
|
||||
// return false;
|
||||
// }
|
||||
int result = sendData(buf, BUF_LEN);
|
||||
// qDebug()<<"sent:"<<result;
|
||||
// if (debug) {
|
||||
// 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";
|
||||
// if (debug) {
|
||||
// qDebug() << "UPLOAD:" << "Data=" << (int)buf[6] << (int)buf[7] << (int)buf[8] << (int)buf[9] << ";" << result << " bytes sent";
|
||||
// }
|
||||
}
|
||||
cout << "\n";
|
||||
// while(true){}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Sends the firmware description to the device
|
||||
*/
|
||||
OP_DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||
DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||
{
|
||||
cout << "Starting uploading description\n";
|
||||
QByteArray array;
|
||||
|
||||
emit operationProgress("Uploading description");
|
||||
|
||||
QByteArray array;
|
||||
if (desc.type() == QVariant::String) {
|
||||
QString description = desc.toString();
|
||||
if (description.length() % 4 != 0) {
|
||||
@ -314,17 +337,16 @@ OP_DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||
array = desc.toByteArray();
|
||||
}
|
||||
|
||||
if (!StartUpload(array.length(), OP_DFU::Descript, 0)) {
|
||||
return OP_DFU::abort;
|
||||
if (!StartUpload(array.length(), DFU::Descript, 0)) {
|
||||
return DFU::abort;
|
||||
}
|
||||
if (!UploadData(array.length(), array)) {
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
if (!EndOperation()) {
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
OP_DFU::Status ret = StatusRequest();
|
||||
|
||||
DFU::Status ret = StatusRequest();
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Upload description Status=" << StatusToString(ret);
|
||||
@ -341,7 +363,7 @@ QString DFUObject::DownloadDescription(int const & numberOfChars)
|
||||
{
|
||||
QByteArray arr;
|
||||
|
||||
StartDownloadT(&arr, numberOfChars, OP_DFU::Descript);
|
||||
StartDownloadT(&arr, numberOfChars, DFU::Descript);
|
||||
|
||||
int index = arr.indexOf(255);
|
||||
return QString((index == -1) ? arr : arr.left(index));
|
||||
@ -351,7 +373,7 @@ QByteArray DFUObject::DownloadDescriptionAsBA(int const & numberOfChars)
|
||||
{
|
||||
QByteArray arr;
|
||||
|
||||
StartDownloadT(&arr, numberOfChars, OP_DFU::Descript);
|
||||
StartDownloadT(&arr, numberOfChars, DFU::Descript);
|
||||
|
||||
return arr;
|
||||
}
|
||||
@ -366,28 +388,27 @@ bool DFUObject::DownloadFirmware(QByteArray *firmwareArray, int device)
|
||||
if (isRunning()) {
|
||||
return false;
|
||||
}
|
||||
requestedOperation = OP_DFU::Download;
|
||||
requestedOperation = DFU::Download;
|
||||
requestSize = devices[device].SizeOfCode;
|
||||
requestTransferType = OP_DFU::FW;
|
||||
requestTransferType = DFU::FW;
|
||||
requestStorage = firmwareArray;
|
||||
start();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Runs the upload or download operations.
|
||||
*/
|
||||
void DFUObject::run()
|
||||
{
|
||||
switch (requestedOperation) {
|
||||
case OP_DFU::Download:
|
||||
case DFU::Download:
|
||||
StartDownloadT(requestStorage, requestSize, requestTransferType);
|
||||
emit(downloadFinished());
|
||||
break;
|
||||
case OP_DFU::Upload:
|
||||
case DFU::Upload:
|
||||
{
|
||||
OP_DFU::Status ret = UploadFirmwareT(requestFilename, requestVerify, requestDevice);
|
||||
DFU::Status ret = UploadFirmwareT(requestFilename, requestVerify, requestDevice);
|
||||
emit(uploadFinished(ret));
|
||||
break;
|
||||
}
|
||||
@ -418,7 +439,7 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Download_Req; // DFU Command
|
||||
buf[1] = DFU::Download_Req; // DFU Command
|
||||
buf[2] = numberOfPackets >> 24; // DFU Count
|
||||
buf[3] = numberOfPackets >> 16; // DFU Count
|
||||
buf[4] = numberOfPackets >> 8; // DFU Count
|
||||
@ -460,7 +481,6 @@ bool DFUObject::StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, Tra
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets the device
|
||||
*/
|
||||
@ -469,7 +489,7 @@ int DFUObject::ResetDevice(void)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Reset; // DFU Command
|
||||
buf[1] = DFU::Reset; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -480,7 +500,7 @@ int DFUObject::ResetDevice(void)
|
||||
buf[9] = 0;
|
||||
|
||||
return sendData(buf, BUF_LEN);
|
||||
// return hidHandle.send(0,buf, BUF_LEN, 500);
|
||||
// return hidHandle->send(0,buf, BUF_LEN, 500);
|
||||
}
|
||||
|
||||
int DFUObject::AbortOperation(void)
|
||||
@ -488,7 +508,7 @@ int DFUObject::AbortOperation(void)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Abort_Operation; // DFU Command
|
||||
buf[1] = DFU::Abort_Operation; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -500,6 +520,7 @@ int DFUObject::AbortOperation(void)
|
||||
|
||||
return sendData(buf, BUF_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the firmware (leaves bootloader and boots the main software)
|
||||
*/
|
||||
@ -508,7 +529,7 @@ int DFUObject::JumpToApp(bool safeboot, bool erase)
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::JumpFW; // DFU Command
|
||||
buf[1] = DFU::JumpFW; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -559,12 +580,12 @@ int DFUObject::JumpToApp(bool safeboot, bool erase)
|
||||
return sendData(buf, BUF_LEN);
|
||||
}
|
||||
|
||||
OP_DFU::Status DFUObject::StatusRequest()
|
||||
DFU::Status DFUObject::StatusRequest()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Status_Request; // DFU Command
|
||||
buf[1] = DFU::Status_Request; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -580,13 +601,13 @@ OP_DFU::Status DFUObject::StatusRequest()
|
||||
while (result < 0 && retry_cnt < MaxSendRetry) {
|
||||
retry_cnt++;
|
||||
qWarning() << "StatusRequest failed, sleeping" << SendRetryIntervalMS << "ms";
|
||||
delay::msleep(SendRetryIntervalMS);
|
||||
QThread::msleep(SendRetryIntervalMS);
|
||||
qWarning() << "StatusRequest retry attempt" << retry_cnt;
|
||||
result = sendData(buf, BUF_LEN);
|
||||
}
|
||||
if (retry_cnt >= MaxSendRetry) {
|
||||
qWarning() << "StatusRequest failed too many times, aborting";
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
if (debug) {
|
||||
qDebug() << "StatusRequest: " << result << " bytes sent";
|
||||
@ -595,10 +616,10 @@ OP_DFU::Status DFUObject::StatusRequest()
|
||||
if (debug) {
|
||||
qDebug() << "StatusRequest: " << result << " bytes received";
|
||||
}
|
||||
if (buf[1] == OP_DFU::Status_Rep) {
|
||||
return (OP_DFU::Status)buf[6];
|
||||
if (buf[1] == DFU::Status_Rep) {
|
||||
return (DFU::Status)buf[6];
|
||||
} else {
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
}
|
||||
|
||||
@ -610,7 +631,7 @@ bool DFUObject::findDevices()
|
||||
devices.clear();
|
||||
char buf[BUF_LEN];
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Req_Capabilities; // DFU Command
|
||||
buf[1] = DFU::Req_Capabilities; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -634,14 +655,14 @@ bool DFUObject::findDevices()
|
||||
RWFlags = buf[8];
|
||||
RWFlags = RWFlags << 8 | buf[9];
|
||||
|
||||
if (buf[1] == OP_DFU::Rep_Capabilities) {
|
||||
if (buf[1] == 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[1] = DFU::Req_Capabilities; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -689,13 +710,12 @@ bool DFUObject::findDevices()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DFUObject::EndOperation()
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
|
||||
buf[0] = 0x02; // reportID
|
||||
buf[1] = OP_DFU::Op_END; // DFU Command
|
||||
buf[1] = DFU::END; // DFU Command
|
||||
buf[2] = 0;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0;
|
||||
@ -715,8 +735,6 @@ bool DFUObject::EndOperation()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
/**
|
||||
Starts a firmware upload (asynchronous)
|
||||
*/
|
||||
@ -725,7 +743,7 @@ bool DFUObject::UploadFirmware(const QString &sfile, const bool &verify, int dev
|
||||
if (isRunning()) {
|
||||
return false;
|
||||
}
|
||||
requestedOperation = OP_DFU::Upload;
|
||||
requestedOperation = DFU::Upload;
|
||||
requestFilename = sfile;
|
||||
requestDevice = device;
|
||||
requestVerify = verify;
|
||||
@ -733,9 +751,9 @@ bool DFUObject::UploadFirmware(const QString &sfile, const bool &verify, int dev
|
||||
return true;
|
||||
}
|
||||
|
||||
OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &verify, int device)
|
||||
DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &verify, int device)
|
||||
{
|
||||
OP_DFU::Status ret;
|
||||
DFU::Status ret;
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Starting Firmware Uploading...";
|
||||
@ -745,9 +763,9 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
if (debug) {
|
||||
qDebug() << "Cant open file";
|
||||
qDebug() << "Failed to open file" << sfile;
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
|
||||
QByteArray arr = file.readAll();
|
||||
@ -766,7 +784,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
if (debug) {
|
||||
qDebug() << "ERROR file to big for device";
|
||||
}
|
||||
return OP_DFU::abort;;
|
||||
return DFU::abort;;
|
||||
}
|
||||
|
||||
quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode);
|
||||
@ -774,7 +792,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
qDebug() << "NEW FIRMWARE CRC=" << crc;
|
||||
}
|
||||
|
||||
if (!StartUpload(arr.length(), OP_DFU::FW, crc)) {
|
||||
if (!StartUpload(arr.length(), DFU::FW, crc)) {
|
||||
ret = StatusRequest();
|
||||
if (debug) {
|
||||
qDebug() << "StartUpload failed";
|
||||
@ -783,13 +801,13 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
return ret;
|
||||
}
|
||||
|
||||
emit operationProgress(QString("Erasing, please wait..."));
|
||||
emit operationProgress("Erasing, please wait...");
|
||||
|
||||
if (debug) {
|
||||
qDebug() << "Erasing memory";
|
||||
}
|
||||
if (StatusRequest() == OP_DFU::abort) {
|
||||
return OP_DFU::abort;
|
||||
if (StatusRequest() == DFU::abort) {
|
||||
return DFU::abort;
|
||||
}
|
||||
|
||||
// TODO: why is there a loop there? The "if" statement
|
||||
@ -799,14 +817,14 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
if (debug) {
|
||||
qDebug() << "Erase returned: " << StatusToString(ret);
|
||||
}
|
||||
if (ret == OP_DFU::uploading) {
|
||||
if (ret == DFU::uploading) {
|
||||
break;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
emit operationProgress(QString("Uploading firmware"));
|
||||
emit operationProgress("Uploading firmware");
|
||||
if (!UploadData(arr.length(), arr)) {
|
||||
ret = StatusRequest();
|
||||
if (debug) {
|
||||
@ -824,18 +842,18 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
return ret;
|
||||
}
|
||||
ret = StatusRequest();
|
||||
if (ret != OP_DFU::Last_operation_Success) {
|
||||
if (ret != DFU::Last_operation_Success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
emit operationProgress(QString("Verifying firmware"));
|
||||
emit operationProgress("Verifying firmware");
|
||||
cout << "Starting code verification\n";
|
||||
QByteArray arr2;
|
||||
StartDownloadT(&arr2, arr.length(), OP_DFU::FW);
|
||||
StartDownloadT(&arr2, arr.length(), DFU::FW);
|
||||
if (arr != arr2) {
|
||||
cout << "Verify:FAILED\n";
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
}
|
||||
|
||||
@ -846,8 +864,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareType &type, int device)
|
||||
DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareType &type, int device)
|
||||
{
|
||||
cout << "Starting Firmware Compare...\n";
|
||||
QFile file(sfile);
|
||||
@ -855,7 +872,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
|
||||
if (debug) {
|
||||
qDebug() << "Cant open file";
|
||||
}
|
||||
return OP_DFU::abort;
|
||||
return DFU::abort;
|
||||
}
|
||||
QByteArray arr = file.readAll();
|
||||
|
||||
@ -869,7 +886,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
|
||||
pad = pad - arr.length();
|
||||
arr.append(QByteArray(pad, 255));
|
||||
}
|
||||
if (type == OP_DFU::crccompare) {
|
||||
if (type == DFU::crccompare) {
|
||||
quint32 crc = DFUObject::CRCFromQBArray(arr, devices[device].SizeOfCode);
|
||||
if (crc == devices[device].FW_CRC) {
|
||||
cout << "Compare Successfull CRC MATCH!\n";
|
||||
@ -879,7 +896,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp
|
||||
return StatusRequest();
|
||||
} else {
|
||||
QByteArray arr2;
|
||||
StartDownloadT(&arr2, arr.length(), OP_DFU::FW);
|
||||
StartDownloadT(&arr2, arr.length(), DFU::FW);
|
||||
if (arr == arr2) {
|
||||
cout << "Compare Successfull ALL Bytes MATCH!\n";
|
||||
} else {
|
||||
@ -898,7 +915,8 @@ void DFUObject::CopyWords(char *source, char *destination, int count)
|
||||
*(destination + x + 3) = source[x + 0];
|
||||
}
|
||||
}
|
||||
QString DFUObject::StatusToString(OP_DFU::Status const & status)
|
||||
|
||||
QString DFUObject::StatusToString(DFU::Status const & status)
|
||||
{
|
||||
switch (status) {
|
||||
case DFUidle:
|
||||
@ -955,11 +973,10 @@ QString DFUObject::StatusToString(OP_DFU::Status const & status)
|
||||
*/
|
||||
void DFUObject::printProgBar(int const & percent, QString const & label)
|
||||
{
|
||||
std::string bar;
|
||||
|
||||
emit(progressUpdated(percent));
|
||||
|
||||
if (debug) {
|
||||
std::string bar;
|
||||
for (int i = 0; i < 50; i++) {
|
||||
if (i < (percent / 2)) {
|
||||
bar.replace(i, 1, "=");
|
||||
@ -984,7 +1001,8 @@ quint32 DFUObject::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
|
||||
// Nibble lookup table for 0x04C11DB7 polynomial
|
||||
static const quint32 CrcTable[16] = {
|
||||
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
|
||||
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
|
||||
};
|
||||
@ -1016,7 +1034,7 @@ quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size)
|
||||
quint32 pad = Size - array.length();
|
||||
|
||||
array.append(QByteArray(pad, 255));
|
||||
quint32 *t = new quint32[Size / 4];
|
||||
quint32 t[Size / 4];
|
||||
for (int x = 0; x < array.length() / 4; x++) {
|
||||
quint32 aux = 0;
|
||||
aux = (char)array[x * 4 + 3] & 0xFF;
|
||||
@ -1028,14 +1046,9 @@ quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size)
|
||||
aux += (char)array[x * 4 + 0] & 0xFF;
|
||||
t[x] = aux;
|
||||
}
|
||||
quint32 ret = DFUObject::CRC32WideFast(0xFFFFFFFF, Size / 4, t);
|
||||
|
||||
delete[] t;
|
||||
|
||||
return ret;
|
||||
return DFUObject::CRC32WideFast(0xFFFFFFFF, Size / 4, (quint32 *)t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send data to the bootloader, either through the serial port
|
||||
of through the HID handle, depending on the mode we're using
|
||||
@ -1043,7 +1056,7 @@ quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size)
|
||||
int DFUObject::sendData(void *data, int size)
|
||||
{
|
||||
if (!use_serial) {
|
||||
return hidHandle.send(0, data, size, 5000);
|
||||
return hidHandle->send(0, data, size, 5000);
|
||||
}
|
||||
|
||||
// Serial Mode:
|
||||
@ -1059,7 +1072,6 @@ int DFUObject::sendData(void *data, int size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Receive data from the bootloader, either through the serial port
|
||||
of through the HID handle, depending on the mode we're using
|
||||
@ -1067,18 +1079,24 @@ int DFUObject::sendData(void *data, int size)
|
||||
int DFUObject::receiveData(void *data, int size)
|
||||
{
|
||||
if (!use_serial) {
|
||||
return hidHandle.receive(0, data, size, 10000);
|
||||
return hidHandle->receive(0, data, size, 10000);
|
||||
}
|
||||
|
||||
// Serial Mode:
|
||||
int x;
|
||||
QTime time;
|
||||
|
||||
time.start();
|
||||
while (true) {
|
||||
if ((x = serialhandle->read_Packet(((char *)data) + 1) != -1) || time.elapsed() > 10000) {
|
||||
// QThread::msleep(10);
|
||||
if (time.elapsed() > 10000) {
|
||||
qDebug() << "____timeout";
|
||||
}
|
||||
if (x > size - 1) {
|
||||
qDebug() << "Error buffer overrun";
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
}
|
||||
@ -1094,9 +1112,9 @@ int DFUObject::receiveData(void *data, int size)
|
||||
/**
|
||||
Gets the type of board connected
|
||||
*/
|
||||
OP_DFU::eBoardType DFUObject::GetBoardType(int boardNum)
|
||||
DFU::eBoardType DFUObject::GetBoardType(int boardNum)
|
||||
{
|
||||
OP_DFU::eBoardType brdType = eBoardUnkwn;
|
||||
DFU::eBoardType brdType = eBoardUnkwn;
|
||||
|
||||
// First of all, check what Board type we are talking to
|
||||
int board = devices[boardNum].ID;
|
@ -1,36 +1,51 @@
|
||||
#ifndef OP_DFU_H
|
||||
#define OP_DFU_H
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file dfu.h
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
|
||||
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup Uploader Uploader Plugin
|
||||
* @{
|
||||
* @brief The uploader plugin
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef DFU_H
|
||||
#define DFU_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <ophid/inc/ophid_hidapi.h>
|
||||
#include <ophid/inc/ophid_usbmon.h>
|
||||
#include <ophid/inc/ophid_usbsignal.h>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QMetaType>
|
||||
#include <QCryptographicHash>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <iostream>
|
||||
#include "delay.h"
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include "SSP/qssp.h"
|
||||
#include "SSP/port.h"
|
||||
#include "SSP/qsspt.h"
|
||||
|
||||
using namespace std;
|
||||
#define BUF_LEN 64
|
||||
|
||||
#define MAX_PACKET_DATA_LEN 255
|
||||
#define MAX_PACKET_BUF_SIZE (1 + 1 + MAX_PACKET_DATA_LEN + 2)
|
||||
|
||||
namespace OP_DFU {
|
||||
#define BUF_LEN 64
|
||||
|
||||
// serial
|
||||
class qsspt;
|
||||
|
||||
// usb
|
||||
class opHID_hidapi;
|
||||
|
||||
namespace DFU {
|
||||
enum TransferTypes {
|
||||
FW,
|
||||
Descript
|
||||
@ -81,7 +96,7 @@ enum Commands {
|
||||
Reset, // 5
|
||||
Abort_Operation, // 6
|
||||
Upload, // 7
|
||||
Op_END, // 8
|
||||
END, // 8
|
||||
Download_Req, // 9
|
||||
Download, // 10
|
||||
Status_Request, // 11
|
||||
@ -108,13 +123,12 @@ struct device {
|
||||
bool Writable;
|
||||
};
|
||||
|
||||
|
||||
class DFUObject : public QThread {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
static quint32 CRCFromQBArray(QByteArray array, quint32 Size);
|
||||
// DFUObject(bool debug);
|
||||
|
||||
DFUObject(bool debug, bool use_serial, QString port);
|
||||
|
||||
virtual ~DFUObject();
|
||||
@ -124,7 +138,7 @@ public:
|
||||
bool findDevices();
|
||||
int JumpToApp(bool safeboot, bool erase);
|
||||
int ResetDevice(void);
|
||||
OP_DFU::Status StatusRequest();
|
||||
DFU::Status StatusRequest();
|
||||
bool EndOperation();
|
||||
int AbortOperation(void);
|
||||
bool ready()
|
||||
@ -133,7 +147,7 @@ public:
|
||||
}
|
||||
|
||||
// Upload (send to device) commands
|
||||
OP_DFU::Status UploadDescription(QVariant description);
|
||||
DFU::Status UploadDescription(QVariant description);
|
||||
bool UploadFirmware(const QString &sfile, const bool &verify, int device);
|
||||
|
||||
// Download (get from device) commands:
|
||||
@ -146,11 +160,10 @@ public:
|
||||
bool DownloadFirmware(QByteArray *byteArray, int device);
|
||||
|
||||
// Comparison functions (is this needed?)
|
||||
OP_DFU::Status CompareFirmware(const QString &sfile, const CompareType &type, int device);
|
||||
DFU::Status CompareFirmware(const QString &sfile, const CompareType &type, int device);
|
||||
|
||||
bool SaveByteArrayToFile(QString const & file, QByteArray const &array);
|
||||
|
||||
|
||||
// Variables:
|
||||
QList<device> devices;
|
||||
int numberOfDevices;
|
||||
@ -158,15 +171,14 @@ public:
|
||||
bool use_delay;
|
||||
|
||||
// Helper functions:
|
||||
QString StatusToString(OP_DFU::Status const & status);
|
||||
QString StatusToString(DFU::Status const & status);
|
||||
static quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer);
|
||||
OP_DFU::eBoardType GetBoardType(int boardNum);
|
||||
|
||||
DFU::eBoardType GetBoardType(int boardNum);
|
||||
|
||||
signals:
|
||||
void progressUpdated(int);
|
||||
void downloadFinished();
|
||||
void uploadFinished(OP_DFU::Status);
|
||||
void uploadFinished(DFU::Status);
|
||||
void operationProgress(QString status);
|
||||
|
||||
private:
|
||||
@ -175,16 +187,18 @@ private:
|
||||
bool use_serial;
|
||||
bool mready;
|
||||
int RWFlags;
|
||||
|
||||
// Serial
|
||||
qsspt *serialhandle;
|
||||
|
||||
// USB
|
||||
opHID_hidapi *hidHandle;
|
||||
|
||||
int sendData(void *, int);
|
||||
int receiveData(void *data, int size);
|
||||
uint8_t sspTxBuf[MAX_PACKET_BUF_SIZE];
|
||||
uint8_t sspRxBuf[MAX_PACKET_BUF_SIZE];
|
||||
port *info;
|
||||
|
||||
|
||||
// USB Bootloader:
|
||||
opHID_hidapi hidHandle;
|
||||
int setStartBit(int command)
|
||||
{
|
||||
return command | 0x20;
|
||||
@ -198,11 +212,11 @@ private:
|
||||
// Thread management:
|
||||
// Same as startDownload except that we store in an external array:
|
||||
bool StartDownloadT(QByteArray *fw, qint32 const & numberOfBytes, TransferTypes const & type);
|
||||
OP_DFU::Status UploadFirmwareT(const QString &sfile, const bool &verify, int device);
|
||||
DFU::Status UploadFirmwareT(const QString &sfile, const bool &verify, int device);
|
||||
QMutex mutex;
|
||||
OP_DFU::Commands requestedOperation;
|
||||
DFU::Commands requestedOperation;
|
||||
qint32 requestSize;
|
||||
OP_DFU::TransferTypes requestTransferType;
|
||||
DFU::TransferTypes requestTransferType;
|
||||
QByteArray *requestStorage;
|
||||
QString requestFilename;
|
||||
bool requestVerify;
|
||||
@ -213,7 +227,7 @@ protected:
|
||||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(OP_DFU::Status)
|
||||
Q_DECLARE_METATYPE(DFU::Status)
|
||||
|
||||
|
||||
#endif // OP_DFU_H
|
||||
#endif // DFU_H
|
@ -23,8 +23,7 @@ HEADERS += \
|
||||
uploadergadgetoptionspage.h \
|
||||
uploadergadgetwidget.h \
|
||||
uploaderplugin.h \
|
||||
op_dfu.h \
|
||||
delay.h \
|
||||
dfu.h \
|
||||
devicewidget.h \
|
||||
SSP/port.h \
|
||||
SSP/qssp.h \
|
||||
@ -42,8 +41,7 @@ SOURCES += \
|
||||
uploadergadgetoptionspage.cpp \
|
||||
uploadergadgetwidget.cpp \
|
||||
uploaderplugin.cpp \
|
||||
op_dfu.cpp \
|
||||
delay.cpp \
|
||||
dfu.cpp \
|
||||
devicewidget.cpp \
|
||||
SSP/port.cpp \
|
||||
SSP/qssp.cpp \
|
||||
|
@ -26,8 +26,8 @@
|
||||
*/
|
||||
|
||||
#include "uploadergadgetconfiguration.h"
|
||||
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
|
||||
/**
|
||||
* Loads a saved configuration or defaults if non exist.
|
||||
|
@ -28,11 +28,12 @@
|
||||
#ifndef UPLOADERGADGETCONFIGURATION_H
|
||||
#define UPLOADERGADGETCONFIGURATION_H
|
||||
|
||||
#include <coreplugin/iuavgadgetconfiguration.h>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include "uploader_global.h"
|
||||
|
||||
#include <coreplugin/iuavgadgetconfiguration.h>
|
||||
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
|
||||
using namespace Core;
|
||||
|
||||
/**
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <QtAlgorithms>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
UploaderGadgetOptionsPage::UploaderGadgetOptionsPage(UploaderGadgetConfiguration *config, QObject *parent) :
|
||||
IOptionsPage(parent),
|
||||
m_config(config)
|
||||
|
@ -30,14 +30,13 @@
|
||||
#define UPLOADERGADGETOPTIONSPAGE_H
|
||||
|
||||
#include "uploader_global.h"
|
||||
|
||||
#include "coreplugin/dialogs/ioptionspage.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
|
||||
class UploaderGadgetConfiguration;
|
||||
|
||||
|
@ -29,8 +29,9 @@
|
||||
|
||||
#include "ui_uploader.h"
|
||||
|
||||
#include <ophid/inc/ophid_usbmon.h>
|
||||
|
||||
#include "flightstatus.h"
|
||||
#include "delay.h"
|
||||
#include "devicewidget.h"
|
||||
#include "runningdevicewidget.h"
|
||||
|
||||
@ -45,6 +46,7 @@
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QDebug>
|
||||
|
||||
#define DFU_DEBUG true
|
||||
@ -484,7 +486,7 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success)
|
||||
|
||||
if (m_resetOnly) {
|
||||
m_resetOnly = false;
|
||||
delay::msleep(3500);
|
||||
QThread::msleep(3500);
|
||||
systemBoot();
|
||||
break;
|
||||
}
|
||||
@ -804,7 +806,7 @@ bool UploaderGadgetWidget::autoUpdate(bool erase)
|
||||
firmware = file.readAll();
|
||||
QEventLoop eventLoop2;
|
||||
connect(m_dfu, SIGNAL(progressUpdated(int)), this, SLOT(autoUpdateFlashProgress(int)));
|
||||
connect(m_dfu, SIGNAL(uploadFinished(OP_DFU::Status)), &eventLoop2, SLOT(quit()));
|
||||
connect(m_dfu, SIGNAL(uploadFinished(DFU::Status)), &eventLoop2, SLOT(quit()));
|
||||
emit progressUpdate(UPLOADING_FW, QVariant());
|
||||
if (!m_dfu->enterDFU(0)) {
|
||||
emit progressUpdate(FAILURE, QVariant(tr("Could not enter direct firmware upload mode.")));
|
||||
@ -820,7 +822,7 @@ bool UploaderGadgetWidget::autoUpdate(bool erase)
|
||||
eventLoop2.exec();
|
||||
QByteArray desc = firmware.right(100);
|
||||
emit progressUpdate(UPLOADING_DESC, QVariant());
|
||||
if (m_dfu->UploadDescription(desc) != OP_DFU::Last_operation_Success) {
|
||||
if (m_dfu->UploadDescription(desc) != DFU::Last_operation_Success) {
|
||||
emit progressUpdate(FAILURE, QVariant(tr("Failed to upload firmware description.")));
|
||||
emit autoUpdateFailed();
|
||||
return false;
|
||||
|
@ -30,13 +30,14 @@
|
||||
|
||||
#include "uploader_global.h"
|
||||
|
||||
#include "dfu.h"
|
||||
#include "enums.h"
|
||||
#include "op_dfu.h"
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QProgressDialog>
|
||||
#include <QTimer>
|
||||
|
||||
using namespace OP_DFU;
|
||||
using namespace DFU;
|
||||
using namespace uploader;
|
||||
|
||||
class Ui_UploaderWidget;
|
||||
|
Loading…
x
Reference in New Issue
Block a user