Device: Add reconnect()

pull/76/merge
Yasser Yassine 2025-10-11 20:33:22 +00:00 committed by Kyle Schwarz
parent 5d672d48d4
commit b48160286b
19 changed files with 118 additions and 54 deletions

View File

@ -71,8 +71,12 @@ bool Driver::write(const std::vector<uint8_t>& bytes) {
if(writeBlocks) {
if(writeQueueFull()) {
while(writeQueueAlmostFull()) // Wait until we have some decent amount of space
while(writeQueueAlmostFull() && !isDisconnected() && !isClosing()) // Wait until we have some decent amount of space
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if(isDisconnected() || isClosing()) {
return false;
}
}
} else {
if(writeQueueFull()) {

View File

@ -229,8 +229,12 @@ std::vector<VersionReport> Device::getChipVersions(bool refreshComponents) {
result[i] = (uint8_t)((dotVersion & 0x000000FFul) >> 0);
return result;
};
for(const auto& chipInfo : getChipInfo()) {
for(const auto& component : compVersions) {
if(!component.valid) {
continue;
}
if(component.identifier == (uint32_t)chipInfo.id) {
chipVersions.emplace_back();
auto& version = chipVersions.back();
@ -407,6 +411,38 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
return true;
}
bool Device::reconnect(std::chrono::milliseconds timeout, std::chrono::milliseconds interval) {
if(isOnline()) {
goOffline();
}
bool readsArePaused = com->readsArePaused();
if(!com->close()) {
return false;
}
std::vector<FoundDevice> foundDevices;
auto findAll = com->driver->getFinder();
auto start = std::chrono::system_clock::now();
while((std::chrono::system_clock::now() - start) < timeout) {
foundDevices.clear();
findAll(foundDevices);
for(auto& fd : foundDevices) {
if(!memcmp(fd.serial, data.serial, 6)) {
com->driver = fd.makeDriver(report, getWritableNeoDevice());
if(readsArePaused) {
// Pause reads again
com->pauseReads();
}
return com->open();
}
}
std::this_thread::sleep_for(interval);
}
return false;
}
APIEvent::Type Device::attemptToBeginCommunication() {
versions.clear();

View File

@ -42,6 +42,7 @@ public:
bool close();
bool isOpen();
bool isDisconnected();
virtual void spawnThreads();
virtual void joinThreads();
void modeChangeIncoming() { driver->modeChangeIncoming(); }

View File

@ -12,9 +12,12 @@
#include "icsneo/api/eventmanager.h"
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
#include "icsneo/communication/ringbuffer.h"
#include "icsneo/device/founddevice.h"
namespace icsneo {
typedef std::function<void(std::vector<FoundDevice>&)> driver_finder_t;
#define ICSNEO_DRIVER_RINGBUFFER_SIZE (512 * 1024)
class Driver {
public:
@ -25,6 +28,7 @@ public:
virtual void modeChangeIncoming() {}
virtual void awaitModeChangeComplete() {}
virtual bool close() = 0;
virtual driver_finder_t getFinder() = 0;
inline bool isDisconnected() const { return disconnected; };
inline bool isClosing() const { return closing; }
@ -37,6 +41,7 @@ public:
bool readAvailable() { return readBuffer.size() > 0; }
RingBuffer& getReadBuffer() { return readBuffer; }
virtual bool enableCommunication(bool /* enable */, bool& sendMsg) { sendMsg = true; return true; }
device_eventhandler_t report;

View File

@ -229,6 +229,7 @@ public:
virtual bool goOffline();
virtual bool enableLogData();
virtual bool disableLogData();
virtual bool reconnect(std::chrono::milliseconds timeout, std::chrono::milliseconds interval = std::chrono::milliseconds(100));
enum class PreloadReturn : uint8_t
{

View File

@ -1,11 +1,12 @@
#ifndef __FOUNDDEVICE_H_
#define __FOUNDDEVICE_H_
#include "icsneo/communication/driver.h"
#include "icsneo/device/neodevice.h"
#include "icsneo/api/eventmanager.h"
namespace icsneo {
class Driver;
typedef std::function< std::unique_ptr<Driver>(device_eventhandler_t err, neodevice_t& forDevice) > driver_factory_t;
class FoundDevice {

View File

@ -25,10 +25,6 @@ public:
return supportedNetworks;
}
bool supportsComponentVersions() const override { return true; }
bool getEthPhyRegControlSupported() const override { return true; }
ProductID getProductID() const override {
return ProductID::RADEpsilon;
}
@ -46,7 +42,9 @@ public:
.add<FlashPhase>(ChipID::RADEpsilon_MCHIP, BootloaderCommunication::RED)
.add<ReconnectPhase>();
}
bool supportsComponentVersions() const override { return true; }
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADEpsilon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADEpsilonSettings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);

View File

@ -28,6 +28,7 @@ public:
bool supportsComponentVersions() const override { return true; }
bool getEthPhyRegControlSupported() const override { return true; }
ProductID getProductID() const override {
return ProductID::RADEpsilon;
}

View File

@ -30,7 +30,7 @@ public:
const std::vector<ChipInfo>& getChipInfo() const override {
static std::vector<ChipInfo> chips = {
{ChipID::RADGigastar_ZYNQ, true, "ZCHIP", "RADGigastar2_T1S_LIN_SW_bin", 1, FirmwareType::Zip},
{ChipID::RADGigastar_ZYNQ, true, "ZCHIP", "RADGigastar_SW_bin", 1, FirmwareType::Zip},
{ChipID::RADGigastar_FFG_ZYNQ, false, "ZCHIP", "RADGigastar_FFG_SW_bin", 1, FirmwareType::Zip},
{ChipID::RADGigastar_USBZ_ZYNQ, true, "USB ZCHIP", "RADGigastar_USBz_SW_bin", 2, FirmwareType::Zip},
{ChipID::RADGigastar_USBZ_Z7010_ZYNQ, false, "USB ZCHIP", "RADGigastar_USBz_Z7010_SW_bin", 2, FirmwareType::Zip},
@ -41,16 +41,32 @@ public:
BootloaderPipeline getBootloader() override {
if(supportsComponentVersions()) {
// main: 16.1, usb: 14.0
auto chipVersions = getChipVersions();
auto mainVersion = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& ver) { return ver.name == "ZCHIP"; });
if(mainVersion != chipVersions.end()) {
static constexpr uint8_t NewBootloaderMajor = 0;
static constexpr uint8_t NewBootloaderMinor = 0;
auto usbVersion = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& ver) { return ver.name == "USB ZCHIP"; });
bool useNewBootloader = false;
if(mainVersion != chipVersions.end()) {
static constexpr uint8_t NewBootloaderMajor = 16;
static constexpr uint8_t NewBootloaderMinor = 1;
if(
mainVersion->major > NewBootloaderMajor ||
(mainVersion->major == NewBootloaderMajor && mainVersion->minor > NewBootloaderMinor)
(mainVersion->major == NewBootloaderMajor && mainVersion->minor >= NewBootloaderMinor)
) {
useNewBootloader = true;
}
} else if(usbVersion != chipVersions.end()) {
static constexpr uint8_t NewBootloaderMajorUSB = 14;
static constexpr uint8_t NewBootloaderMinorUSB= 0;
if(
usbVersion->major > NewBootloaderMajorUSB ||
(usbVersion->major == NewBootloaderMajorUSB && usbVersion->minor >= NewBootloaderMinorUSB)
) {
useNewBootloader = true;
}
}
if(useNewBootloader) {
BootloaderPipeline pipeline;
for(const auto& version : chipVersions) {
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip);
@ -60,7 +76,6 @@ public:
return pipeline;
}
}
}
// If we've reached this point, then we use the legacy flashing
if(com->driver->isEthernet()) {
return BootloaderPipeline()

View File

@ -15,9 +15,9 @@ namespace icsneo
class RADGigastar2 : public Device {
public:
enum class FirmwareVariant {
T1Sx6_CANx1_LINx16,
T1Sx8_CANx4_LINx6,
Invalid
T1Sx6_CANx1_LINx16 = 0,
T1Sx8_CANx4_LINx6 = 1,
Invalid = 2
};
// Serial numbers start with GT
@ -100,6 +100,8 @@ public:
FirmwareVariant getCurrentVariant() {
if(supportsComponentVersions()) {
refreshComponentVersions();
const auto& components = getComponentVersions();
for(const auto& component : components) {
if(!component.valid) {
@ -107,7 +109,10 @@ public:
}
if(component.identifier == static_cast<uint32_t>(ChipID::RADGigastar2_ZYNQ)) {
auto res = static_cast<FirmwareVariant>(std::clamp<uint8_t>(component.componentInfo, 0, 2));
if(component.componentInfo > 2) {
return FirmwareVariant::Invalid;
}
auto res = static_cast<FirmwareVariant>(component.componentInfo);
if(variantToFlash == FirmwareVariant::Invalid) {
variantToFlash = res; // Set the variantToFlash if it hasn't been set yet, we always flash the same firmware variant as the current if it is unspecified
}
@ -140,17 +145,7 @@ public:
}
BootloaderPipeline getBootloader() override {
if(supportsComponentVersions()) {
auto chipVersions = getChipVersions();
auto mainVersion = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& ver) { return ver.name == "ZCHIP"; });
if(mainVersion != chipVersions.end()) {
static constexpr uint8_t NewBootloaderMajor = 0;
static constexpr uint8_t NewBootloaderMinor = 0;
if(
mainVersion->major > NewBootloaderMajor ||
(mainVersion->major == NewBootloaderMajor && mainVersion->minor > NewBootloaderMinor)
) {
BootloaderPipeline pipeline;
for(const auto& version : chipVersions) {
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip);
@ -159,22 +154,12 @@ public:
pipeline.add<WaitPhase>(std::chrono::milliseconds(3000));
return pipeline;
}
}
}
// If we've reached this point, then we use the legacy flashing
if(com->driver->isEthernet()) {
return BootloaderPipeline()
.add<FlashPhase>(ChipID::RADGigastar2_ZYNQ, BootloaderCommunication::RAD)
.add<ReconnectPhase>()
.add<WaitPhase>(std::chrono::milliseconds(3000));
}
return BootloaderPipeline()
.add<FlashPhase>(ChipID::RADGigastar_USBZ_ZYNQ, BootloaderCommunication::RAD)
.add<ReconnectPhase>()
.add<WaitPhase>(std::chrono::milliseconds(3000));
}
std::vector<VersionReport> getChipVersions(bool refreshComponents = true) override {
if(variantToFlash == FirmwareVariant::Invalid) {
getCurrentVariant();
}
if(refreshComponents) {
refreshComponentVersions();
}

View File

@ -4,6 +4,7 @@
#ifdef __cplusplus
#include "icsneo/device/chipid.h"
#include "icsneo/device/deviceversion.h"
#include <vector>
#include <string>
@ -17,6 +18,10 @@ struct VersionReport {
uint8_t minor;
uint8_t maintenance;
uint8_t build;
icsneo::DeviceAppVersion makeAppVersion() const {
return {major, minor};
}
};
}

View File

@ -21,6 +21,7 @@ public:
bool isOpen() override;
bool close() override;
driver_finder_t getFinder() override { return DXX::Find; }
private:
void read();

View File

@ -32,6 +32,7 @@ public:
bool open() override;
bool isOpen() override;
bool close() override;
driver_finder_t getFinder() override { return CDCACM::Find; }
void modeChangeIncoming() override;
void awaitModeChangeComplete() override;

View File

@ -24,6 +24,8 @@ public:
bool open() override;
bool isOpen() override;
bool close() override;
driver_finder_t getFinder() override { return FirmIO::Find; }
private:
std::thread readThread, writeThread;

View File

@ -24,6 +24,8 @@ public:
bool isOpen() override;
bool close() override;
bool isEthernet() const override { return true; }
driver_finder_t getFinder() override { return PCAP::Find; }
private:
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
neodevice_t& device;

View File

@ -25,6 +25,8 @@ public:
bool close() override;
bool faa(const std::string& key, int32_t inc, int32_t& orig);
bool enableCommunication(bool enable, bool& sendMsg) override;
driver_finder_t getFinder() override { return Servd::Find; }
private:
void alive();
void read(Address&& address);

View File

@ -6,7 +6,6 @@
#include <memory>
#include "icsneo/communication/driver.h"
#include "icsneo/device/founddevice.h"
namespace icsneo {
@ -25,6 +24,8 @@ public:
bool isOpen() override;
bool close() override;
bool isEthernet() const override { return true; }
driver_finder_t getFinder() override { return TCP::Find; }
private:
#ifdef _WIN32
typedef size_t SocketFileDescriptor;

View File

@ -21,6 +21,7 @@ public:
bool open() override;
bool isOpen() override;
bool close() override;
driver_finder_t getFinder() override { return CDCACM::Find; }
private:
void read();

View File

@ -24,6 +24,8 @@ public:
bool isOpen() override;
bool close() override;
bool isEthernet() const override { return true; }
driver_finder_t getFinder() override { return PCAP::Find; }
private:
const PCAPDLL& pcap;
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };