Compare commits

...

14 Commits

Author SHA1 Message Date
Francesco Valla b815fece31
Merge 31d4a750d8 into 563c444def 2025-11-03 11:51:24 -06:00
Nicholas Zamora 563c444def Device: Add RAD-Gemini 2025-11-03 09:37:50 -05:00
Kyle Schwarz 3f3300d677 Communication: EthernetStatusMessage: Handle BASE-T invalid case 2025-10-31 12:31:03 -04:00
Max Brombach b9e3542bcf Device: Use variant Core chip and fix ZChip flash for FIRE2 2025-10-31 12:02:02 -04:00
Kyle Schwarz 7f192a0cea Network: Use Type::AutomotiveEthernet 2025-10-30 23:40:30 -04:00
Kyle Schwarz 3b60bfc986 CI: Add Fedora 43 & drop 41 2025-10-30 21:21:07 -04:00
Kyle Schwarz d51f88d023 Communication: EthernetStatusMessage: Add BASE-T support 2025-10-30 21:13:20 -04:00
Kyle Schwarz f3cb41d60b Communication: Network: Add Type::AutomotiveEthernet
Also condense switch statements
2025-10-30 21:11:23 -04:00
Yasser Yassine 1b00c6a05b Gigastar(2): Fix bootloaders steps 2025-10-30 14:37:12 -04:00
Kyle Schwarz ebf9409c18 Device: Guard mutex usage 2025-10-30 11:18:12 -04:00
Kyle Schwarz 83ab65b062 Device: Fix NeoVI message guard 2025-10-29 15:37:58 -04:00
Kyle Schwarz 7f1668a55b Device: Move network mutex to goOnline 2025-10-29 15:24:03 -04:00
Max Brombach 10ffd756a1 Device: Remove erroneous API error in VSA buffer overlap check 2025-10-29 12:56:46 -04:00
Francesco Valla 31d4a750d8 EthernetPacketizer: do a size check on incoming bytestream
An incoming bytestream can be less than 24 bytes, leading to exceptions
when accessing its data (or allocating the vector for its payload).
Perform a size check before trying to decode the bytestream and discard
invalid incoming streams.

Signed-off-by: Francesco Valla <francesco.valla@mta.it>
2025-07-04 10:57:28 +02:00
32 changed files with 961 additions and 1079 deletions

View File

@ -243,30 +243,6 @@ unit_test linux/ubuntu/2404/amd64/clang:
- linux-build
timeout: 5m
build linux/fedora/41/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:41
unit_test linux/fedora/41/amd64/gcc:
<<: *test_linux_fedora_gcc
image: fedora:41
dependencies:
- build linux/fedora/41/amd64/gcc
needs:
- build linux/fedora/41/amd64/gcc
build linux/fedora/41/amd64/clang:
<<: *build_linux_fedora_clang
image: fedora:41
unit_test linux/fedora/41/amd64/clang:
<<: *test_linux_fedora_clang
image: fedora:41
dependencies:
- build linux/fedora/41/amd64/clang
needs:
- build linux/fedora/41/amd64/clang
build linux/fedora/42/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:42
@ -291,6 +267,30 @@ unit_test linux/fedora/42/amd64/clang:
needs:
- build linux/fedora/42/amd64/clang
build linux/fedora/43/amd64/gcc:
<<: *build_linux_fedora_gcc
image: fedora:43
unit_test linux/fedora/43/amd64/gcc:
<<: *test_linux_fedora_gcc
image: fedora:43
dependencies:
- build linux/fedora/43/amd64/gcc
needs:
- build linux/fedora/43/amd64/gcc
build linux/fedora/43/amd64/clang:
<<: *build_linux_fedora_clang
image: fedora:43
unit_test linux/fedora/43/amd64/clang:
<<: *test_linux_fedora_clang
image: fedora:43
dependencies:
- build linux/fedora/43/amd64/clang
needs:
- build linux/fedora/43/amd64/clang
#-------------------------------------------------------------------------------
# Python Module
#-------------------------------------------------------------------------------

View File

@ -27,6 +27,7 @@ each of the respective APIs.
- RAD-EpsilonXL
- RAD-Galaxy
- RAD-Galaxy 2
- RAD-Gemini
- RAD-Gigastar
- RAD-Gigastar 2
- RAD-Moon 2

View File

@ -90,6 +90,7 @@ static bool NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t
copyFrameData();
break;
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet:
oldmsg.Protocol = SPY_PROTOCOL_ETHERNET;
oldmsg.NumberBytesData = static_cast<uint8_t>(frame.length & 0xFF);
oldmsg.NumberBytesHeader = static_cast<uint8_t>(frame.length >> 8);
@ -1075,6 +1076,9 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
case NEODEVICE_RADMOON3:
*pDeviceSettingsType = DeviceRADMoon3SettingsType;
break;
case NEODEVICE_RADGEMINI:
*pDeviceSettingsType = DeviceRADGeminiSettingsType;
break;
case NEODEVICE_RED2:
*pDeviceSettingsType = DeviceRed2SettingsType;
break;

View File

@ -22,7 +22,8 @@ void init_ethernetstatusmessage(pybind11::module_& m) {
.value("LinkModeAuto", EthernetStatusMessage::LinkMode::LinkModeAuto)
.value("LinkModeMaster", EthernetStatusMessage::LinkMode::LinkModeMaster)
.value("LinkModeSlave", EthernetStatusMessage::LinkMode::LinkModeSlave)
.value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid);
.value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid)
.value("LinkModeNone", EthernetStatusMessage::LinkMode::LinkModeNone);
ethernetStatusMessage
.def_readonly("network", &EthernetStatusMessage::network)

View File

@ -179,10 +179,11 @@ void init_network(pybind11::module_& m) {
.value("LSFTCAN", Network::Type::LSFTCAN)
.value("SWCAN", Network::Type::SWCAN)
.value("ISO9141", Network::Type::ISO9141)
.value("I2C_01", Network::Type::I2C)
.value("I2C", Network::Type::I2C)
.value("A2B", Network::Type::A2B)
.value("SPI", Network::Type::SPI)
.value("MDIO", Network::Type::MDIO)
.value("AutomotiveEthernet", Network::Type::AutomotiveEthernet)
.value("Any", Network::Type::Any)
.value("Other", Network::Type::Other);

View File

@ -129,6 +129,7 @@ void init_chipid(pybind11::module_& m) {
.value("RADCOMET3_ZCHIP", ChipID::RADCOMET3_ZCHIP)
.value("Connect_LINUX", ChipID::Connect_LINUX)
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
.value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP)
.value("Invalid", ChipID::Invalid);
}

View File

@ -36,6 +36,7 @@ void init_devicetype(pybind11::module_& m) {
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
.value("RADMoon3", DeviceType::Enum::RADMoon3)
.value("RADGemini", DeviceType::Enum::RADGemini)
.value("RADComet", DeviceType::Enum::RADComet)
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
.value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN)

View File

@ -62,7 +62,8 @@ uint64_t Decoder::GetUInt64FromLEBytes(const uint8_t* bytes) {
bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet) {
switch(packet->network.getType()) {
case Network::Type::Ethernet: {
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
result = HardwareEthernetPacket::DecodeToMessage(packet->data);
if(!result) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);

View File

@ -32,7 +32,8 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
netid = uint16_t(frame->network.getNetID());
switch(frame->network.getType()) {
case Network::Type::Ethernet: {
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message);
if(!ethmsg) {
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);

View File

@ -133,6 +133,10 @@ EthernetPacketizer::EthernetPacket::EthernetPacket(const uint8_t* data, size_t s
int EthernetPacketizer::EthernetPacket::loadBytestream(const std::vector<uint8_t>& bytestream) {
errorWhileDecodingFromBytestream = 0;
if (bytestream.size() < 24) {
errorWhileDecodingFromBytestream = 1;
return errorWhileDecodingFromBytestream;
}
for(size_t i = 0; i < 6; i++)
destMAC[i] = bytestream[i];
for(size_t i = 0; i < 6; i++)

View File

@ -13,7 +13,15 @@ enum LinkSpeed {
ethSpeed10000,
};
enum LinkMode {
enum TLinkMode {
T_LINK_NONE,
T_LINK_MASTER,
T_LINK_SLAVE,
T_LINK_AUTO,
T_LINK_INVALID = 255,
};
enum AELinkMode {
AE_LINK_AUTO,
AE_LINK_MASTER,
AE_LINK_SLAVE,
@ -46,11 +54,26 @@ std::shared_ptr<Message> EthernetStatusMessage::DecodeToMessage(const std::vecto
default: return nullptr;
}
LinkMode mode;
switch(packet->mode) {
case AE_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
case AE_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
case AE_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
case AE_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
switch(Network::GetTypeOfNetID((Network::NetID)packet->network, false)) {
case Network::Type::Ethernet:
switch(packet->mode) {
case T_LINK_NONE: mode = EthernetStatusMessage::LinkMode::LinkModeNone; break;
case T_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
case T_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
case T_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
case T_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
default: return nullptr;
}
break;
case Network::Type::AutomotiveEthernet:
switch(packet->mode) {
case AE_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
case AE_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
case AE_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
case AE_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
default: return nullptr;
}
break;
default: return nullptr;
}
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state, speed, packet->duplex, mode);

View File

@ -44,7 +44,8 @@ neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
can.status.canfdESI = canmsg->errorStateIndicator;
break;
}
case Network::Type::Ethernet: {
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg;
auto ethmsg = std::static_pointer_cast<EthernetMessage>(message);
eth.preemptionFlags = ethmsg->preemptionFlags;
@ -142,7 +143,8 @@ std::shared_ptr<Message> icsneo::CreateMessageFromNeoMessage(const neomessage_t*
canmsg->errorStateIndicator = can.status.canfdESI;
return canmsg;
}
case Network::Type::Ethernet: {
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet: {
neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage;
auto ethmsg = std::make_shared<EthernetMessage>();
ethmsg->network = network;

View File

@ -136,6 +136,7 @@ std::vector<uint8_t> TransmitMessage::EncodeFromMessage(std::shared_ptr<Frame> f
std::vector<uint8_t> result;
switch(frame->network.getType()) {
case Network::Type::Ethernet:
case Network::Type::AutomotiveEthernet:
result = EncodeFromMessageEthernet(frame, report);
break;
case Network::Type::CAN:

View File

@ -459,29 +459,6 @@ APIEvent::Type Device::attemptToBeginCommunication() {
return getCommunicationNotEstablishedError();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
assignedClientId = com->getClientIDSync();
networkMutexCallbackHandle = addMessageCallback(
std::make_shared<MessageCallback>(
[this](std::shared_ptr<Message> message) {
auto netMutexMsg = std::static_pointer_cast<NetworkMutexMessage>(message);
if(netMutexMsg->networks.size() && netMutexMsg->event.has_value()) {
switch(*netMutexMsg->event) {
case NetworkMutexEvent::Acquired:
lockedNetworks.emplace(*netMutexMsg->networks.begin());
break;
case NetworkMutexEvent::Released: {
auto it = lockedNetworks.find(*netMutexMsg->networks.begin());
if (it != lockedNetworks.end())
lockedNetworks.erase(it);
break;
}
}
}
},
std::make_shared<MessageFilter>(Message::Type::NetworkMutex)
)
);
auto serial = com->getSerialNumberSync();
int i = 0;
while(!serial) {
@ -577,6 +554,30 @@ bool Device::goOnline() {
return false;
}
if(supportsNetworkMutex()) {
assignedClientId = com->getClientIDSync();
if(assignedClientId) {
// firmware supports clientid/mutex
networkMutexCallbackHandle = lockAllNetworks(std::numeric_limits<uint32_t>::max(), std::numeric_limits<uint32_t>::max(), NetworkMutexType::Shared, [this](std::shared_ptr<Message> message) {
auto netMutexMsg = std::static_pointer_cast<NetworkMutexMessage>(message);
if(netMutexMsg->networks.size() && netMutexMsg->event.has_value()) {
switch(*netMutexMsg->event) {
case NetworkMutexEvent::Acquired:
lockedNetworks.emplace(*netMutexMsg->networks.begin());
break;
case NetworkMutexEvent::Released: {
auto it = lockedNetworks.find(*netMutexMsg->networks.begin());
if (it != lockedNetworks.end())
lockedNetworks.erase(it);
break;
}
}
}
}
);
}
}
// (re)start the keeponline
keeponline = std::make_unique<Periodic>([this] { return enableNetworkCommunication(true, onlineTimeoutMs); }, std::chrono::milliseconds(onlineTimeoutMs / 4));
@ -590,6 +591,9 @@ bool Device::goOnline() {
bool Device::goOffline() {
keeponline.reset();
if(networkMutexCallbackHandle)
removeMessageCallback(*networkMutexCallbackHandle);
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; });
if(isDisconnected()) {
@ -1999,6 +2003,15 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
case Message::Type::RawMessage: {
auto rawMessage = std::static_pointer_cast<RawMessage>(message);
switch(rawMessage->network.getNetID()) {
case Network::NetID::Device: {
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
// if it couldn't be decoded to a CANMessage. We only care about the
// CANMessage decoding right now.
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
if(canmsg)
handleNeoVIMessage(std::move(canmsg));
break;
}
case Network::NetID::DeviceStatus:
// Device Status format is unique per device, so the devices need to decode it themselves
handleDeviceStatus(rawMessage);
@ -2008,15 +2021,6 @@ void Device::handleInternalMessage(std::shared_ptr<Message> message) {
}
break;
}
case Message::Type::Frame: {
// Device is not guaranteed to be a CANMessage, it might be a RawMessage
// if it couldn't be decoded to a CANMessage. We only care about the
// CANMessage decoding right now.
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
if(canmsg)
handleNeoVIMessage(std::move(canmsg));
break;
}
default: break;
}
forEachExtension([&](const std::shared_ptr<DeviceExtension>& ext) {
@ -3049,7 +3053,6 @@ std::optional<bool> Device::isVSAOverlapped(std::optional<VSAMetadata> optMetada
lastSectorRecord->getTimestamp() > metadata.coreMiniTimestamp;
} else if(lastSectorStatus == VSAParser::RecordParseStatus::NotARecordStart) {
// The vsa record buffer is not full
report(APIEvent::Type::VSAOtherError, APIEvent::Severity::Error);
return false;
}
report(APIEvent::Type::VSABufferFormatError, APIEvent::Severity::Error);
@ -3891,10 +3894,6 @@ std::shared_ptr<DiskDetails> Device::getDiskDetails(std::chrono::milliseconds ti
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return std::nullopt;
}
if(!isOnline()) {
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
return std::nullopt;
}
if(!assignedClientId.has_value()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return std::nullopt;
@ -4007,10 +4006,6 @@ std::shared_ptr<NetworkMutexMessage> Device::getNetworkMutexStatus(Network::NetI
report(APIEvent::Type::NotSupported, APIEvent::Severity::Error);
return std::nullopt;
}
if(!isOnline()) {
report(APIEvent::Type::DeviceCurrentlyOffline, APIEvent::Severity::Error);
return std::nullopt;
}
if(!assignedClientId.has_value()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return std::nullopt;

View File

@ -225,6 +225,10 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
makeIfSerialMatches<RADMoon3>(dev, newFoundDevices);
#endif
#ifdef __RADGEMINI_H_
makeIfSerialMatches<RADGemini>(dev, newFoundDevices);
#endif
#ifdef __RADMOONDUO_H_
makeIfSerialMatches<RADMoonDuo>(dev, newFoundDevices);
#endif
@ -384,6 +388,10 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
RADMoon3::DEVICE_TYPE,
#endif
#ifdef __RADGEMINI_H_
RADGemini::DEVICE_TYPE,
#endif
#ifdef __RADMOONDUO_H_
RADMoonDuo::DEVICE_TYPE,
#endif

View File

@ -214,7 +214,8 @@ void printMessage(const std::shared_ptr<icsneo::Message>& message) {
std::cout << std::dec << '(' << canMessage->timestamp << " ns since 1/1/2007)\n";
break;
}
case icsneo::Network::Type::Ethernet: {
case icsneo::Network::Type::Ethernet:
case icsneo::Network::Type::AutomotiveEthernet: {
auto ethMessage = std::static_pointer_cast<icsneo::EthernetMessage>(message);
std::cout << "\t\t" << ethMessage->network << " Frame - " << std::dec

View File

@ -199,7 +199,8 @@ int main() {
std::cout << std::dec << '(' << canMessage->timestamp << " ns since 1/1/2007)\n";
break;
}
case icsneo::Network::Type::Ethernet: {
case icsneo::Network::Type::Ethernet:
case icsneo::Network::Type::AutomotiveEthernet: {
auto ethMessage = std::static_pointer_cast<icsneo::EthernetMessage>(message);
std::cout << "\t\t" << ethMessage->network << " Frame - " << std::dec

View File

@ -172,7 +172,7 @@ int main(int argc, char* argv[]) {
const auto frame = std::static_pointer_cast<icsneo::Frame>(msg);
if(frame->network.getType() == icsneo::Network::Type::CAN) {
++canFrameCount;
} else if(frame->network.getType() == icsneo::Network::Type::Ethernet) {
} else if(frame->network.getType() == icsneo::Network::Type::AutomotiveEthernet || frame->network.getType() == icsneo::Network::Type::Ethernet) {
++ethFrameCount;
}
}));

View File

@ -25,6 +25,7 @@ public:
LinkModeMaster,
LinkModeSlave,
LinkModeInvalid,
LinkModeNone,
};
EthernetStatusMessage(Network net, bool state, LinkSpeed speed, bool duplex, LinkMode mode) : Message(Type::EthernetStatus),
network(net), state(state), speed(speed), duplex(duplex), mode(mode) {}

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,8 @@ struct BootloaderPhase {
Finalize,
Reconnect,
EnterBootloader,
Wait
Wait,
EnterApplication
};
virtual Type getType() const = 0;
@ -70,6 +71,16 @@ struct EnterBootloaderPhase : public BootloaderPhase {
}
};
struct EnterApplicationPhase : public BootloaderPhase {
Type getType() const override {
return Type::EnterApplication;
}
ChipID chip;
EnterApplicationPhase(ChipID chip) : chip(chip) {}
};
struct FlashPhase : public BootloaderPhase {
Type getType() const override {
return Type::Flash;

View File

@ -129,6 +129,7 @@ enum class ChipID : uint8_t {
RADCOMET3_ZCHIP = 125,
Connect_LINUX = 126,
RADGigastar2_ZYNQ = 131,
RADGemini_MCHIP = 135,
Invalid = 255
};

View File

@ -13,6 +13,7 @@
#include <optional>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <chrono>
#include "icsneo/api/eventmanager.h"
#include "icsneo/api/lifetime.h"
@ -136,7 +137,8 @@ public:
Connect = 51,
RADComet3 = 54,
RADMoonT1S = 56,
RADGigastar2 = 57
RADGigastar2 = 57,
RADGemini = 60,
};
virtual ProductID getProductID() const = 0;
@ -1139,9 +1141,8 @@ private:
std::unique_ptr<Periodic> keeponline;
std::optional<uint32_t> assignedClientId;
std::set<icsneo::Network::NetID> lockedNetworks;
std::unordered_set<icsneo::Network::NetID> lockedNetworks;
std::optional<int> networkMutexCallbackHandle;
};
}

View File

@ -58,6 +58,7 @@ public:
RADGigastar2 = (0x00000029),
FIRE3_T1S_LIN = (0x0000002A),
FIRE3_T1S_SENT = (0x0000002B),
RADGemini = (0x0000002C),
RED = (0x00000040),
ECU = (0x00000080),
IEVB = (0x00000100),
@ -148,6 +149,8 @@ public:
return "RAD-EpsilonXL";
case RADMoon3:
return "RAD-Moon 3";
case RADGemini:
return "RAD-Gemini";
case RADComet:
return "RAD-Comet";
case RED:
@ -271,6 +274,7 @@ private:
#define ICSNEO_DEVICETYPE_RADGIGASTAR2 ((devicetype_t)0x00000029)
#define ICSNEO_DEVICETYPE_FIRE3_T1S_LIN ((devicetype_t)0x0000002A)
#define ICSNEO_DEVICETYPE_FIRE3_T1S_SENT ((devicetype_t)0x0000002B)
#define ICSNEO_DEVICETYPE_RADGEMINI ((devicetype_t)0x0000002C)
#define ICSNEO_DEVICETYPE_RED ((devicetype_t)0x00000040)
#define ICSNEO_DEVICETYPE_ECU ((devicetype_t)0x00000080)
#define ICSNEO_DEVICETYPE_IEVB ((devicetype_t)0x00000100)

View File

@ -11,6 +11,12 @@ namespace icsneo {
class NeoVIFIRE2 : public Device {
public:
enum class CoreChipVariant {
Core = 0,
Core_SG4 = 1,
Invalid = 2
};
// Serial numbers start with CY
// USB PID is 0x1000, standard driver is DXX
// Ethernet MAC allocation is 0x04, standard driver is Raw
@ -91,22 +97,65 @@ public:
return ProductID::neoVIFIRE2;
}
CoreChipVariant getCoreChipVariant() {
const auto& hardwareInfo = getHardwareInfo(std::chrono::milliseconds(1000));
if(!hardwareInfo) {
chipVariant = CoreChipVariant::Invalid;
return chipVariant;
}
const auto& bootloaderVersion = hardwareInfo->bootloaderVersion;
if(bootloaderVersion.major >= CORE_SG4_BL_MAJOR_VERSION_CUTOFF) {
chipVariant = CoreChipVariant::Core_SG4;
} else {
chipVariant = CoreChipVariant::Core;
}
return chipVariant;
}
const std::vector<ChipInfo>& getChipInfo() const override {
static std::vector<ChipInfo> chips = {
{ChipID::neoVIFIRE2_MCHIP, true, "MCHIP", "fire2_mchip_ief", 0, FirmwareType::IEF},
{ChipID::neoVIFIRE2_ZYNQ, true, "ZCHIP", "fire2_zchip_ief", 1, FirmwareType::IEF},
{ChipID::neoVIFIRE2_Core, true, "Core", "fire2_core", 2, FirmwareType::IEF},
};
return chips;
static std::vector<ChipInfo> chipsSG4 = {
{ChipID::neoVIFIRE2_MCHIP, true, "MCHIP", "fire2_mchip_ief", 0, FirmwareType::IEF},
{ChipID::neoVIFIRE2_ZYNQ, true, "ZCHIP", "fire2_zchip_ief", 1, FirmwareType::IEF},
{ChipID::neoVIFIRE2_CORE_SG4, true, "Core", "fire2_core_sg4", 2, FirmwareType::IEF}
};
if(chipVariant == CoreChipVariant::Core_SG4) {
return chipsSG4;
}
return chips; // Return the base chips even if the mode is invalid
}
BootloaderPipeline getBootloader() override {
return BootloaderPipeline()
.add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::neoVIFIRE2_MCHIP, BootloaderCommunication::RED)
.add<FlashPhase>(ChipID::neoVIFIRE2_ZYNQ, BootloaderCommunication::RED, false, true)
.add<FlashPhase>(ChipID::neoVIFIRE2_Core, BootloaderCommunication::REDCore, false, false)
.add<ReconnectPhase>();
BootloaderPipeline pipeline;
pipeline.add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::neoVIFIRE2_MCHIP, BootloaderCommunication::RED);
if(chipVariant == CoreChipVariant::Core_SG4) {
pipeline.add<FlashPhase>(ChipID::neoVIFIRE2_CORE_SG4, BootloaderCommunication::REDCore, false, false);
} else {
pipeline.add<FlashPhase>(ChipID::neoVIFIRE2_Core, BootloaderCommunication::REDCore, false, false);
}
pipeline.add<FlashPhase>(ChipID::neoVIFIRE2_ZYNQ, BootloaderCommunication::RED, false, false)
.add<EnterApplicationPhase>(ChipID::neoVIFIRE2_MCHIP)
.add<ReconnectPhase>();
return pipeline;
}
std::vector<VersionReport> getChipVersions(bool refreshComponents = true) override {
if(chipVariant == CoreChipVariant::Invalid) {
getCoreChipVariant();
}
if(refreshComponents) {
refreshComponentVersions();
}
return Device::getChipVersions();
}
protected:
@ -167,6 +216,10 @@ protected:
size_t getDiskCount() const override {
return 1;
}
private:
CoreChipVariant chipVariant = CoreChipVariant::Invalid;
constexpr static uint8_t CORE_SG4_BL_MAJOR_VERSION_CUTOFF = 5;
};
}

View File

@ -0,0 +1,70 @@
#ifndef __RADGEMINI_H_
#define __RADGEMINI_H_
#ifdef __cplusplus
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radgemini/radgeminisettings.h"
namespace icsneo {
class RADGemini : public Device {
public:
// Serial numbers start with GE
// USB PID is 0x110E, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(RADGemini, DeviceType::RADGemini, "GE");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::MDIO_01,
};
return supportedNetworks;
}
bool getEthPhyRegControlSupported() const override { return true; }
bool isOnlineSupported() const override { return false; }
bool supportsTC10() const override { return true; }
ProductID getProductID() const override { return ProductID::RADGemini; }
BootloaderPipeline getBootloader() override {
return BootloaderPipeline()
.add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::RADGemini_MCHIP, BootloaderCommunication::RED)
.add<ReconnectPhase>()
.add<WaitPhase>(std::chrono::milliseconds(3000));
}
protected:
RADGemini(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADGeminiSettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer);
packetizer.align16bit = true;
}
void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder);
encoder.supportEthPhy = true;
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}
#endif // __cplusplus
#endif // __RADGEMINI_H_

View File

@ -0,0 +1,51 @@
#ifndef LIBICSNEO_RADGEMINISETTINGS_H
#define LIBICSNEO_RADGEMINISETTINGS_H
#include <stdint.h>
#include "icsneo/device/idevicesettings.h"
#ifdef __cplusplus
namespace icsneo {
#endif // __cplusplus
#pragma pack(push, 2)
typedef struct {
uint16_t perf_en; // 2
ETHERNET_SETTINGS2 ethernet1; // 16
ETHERNET_SETTINGS2 ethernet2; // 16
ETHERNET_SETTINGS2 autoEthernet1; // 16
ETHERNET_SETTINGS2 autoEthernet2; // 16
uint16_t network_enabled_on_boot; // 2
uint16_t network_enables; // 2
uint16_t network_enables_2; // 2
uint16_t network_enables_3; // 2
uint16_t network_enables_4; // 2
uint64_t network_enables_5; // 8
struct
{
uint16_t enableLatencyTest : 1;
uint16_t reserved : 15;
} flags; // 2
} radgemini_settings_t;
#pragma pack(pop)
#ifdef __cplusplus
#include <iostream>
class RADGeminiSettings : public IDeviceSettings {
public:
RADGeminiSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgemini_settings_t)) {}
};
}
#endif // __cplusplus
#endif // LIBICSNEO_RADGEMINISETTINGS_H

View File

@ -67,10 +67,23 @@ public:
}
}
if(useNewBootloader) {
auto mainChip = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& chip) { return chip.name == "ZCHIP"; });
auto usbChip = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& chip) { return chip.name == "USB ZCHIP"; });
ChipID mainChipID;
if(mainChip != chipVersions.end()) {
mainChipID = mainChip->id;
} else if(usbChip != chipVersions.end()) {
mainChipID = usbChip->id;
} else {
return {};
}
BootloaderPipeline pipeline;
for(const auto& version : chipVersions) {
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip);
}
pipeline.add<EnterApplicationPhase>(mainChipID);
pipeline.add<ReconnectPhase>();
pipeline.add<WaitPhase>(std::chrono::milliseconds(3000));
return pipeline;

View File

@ -146,10 +146,23 @@ public:
BootloaderPipeline getBootloader() override {
auto chipVersions = getChipVersions();
auto mainChip = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& chip) { return chip.name == "ZCHIP"; });
auto usbChip = std::find_if(chipVersions.begin(), chipVersions.end(), [](const auto& chip) { return chip.name == "USB ZCHIP"; });
ChipID mainChipID;
if(mainChip != chipVersions.end()) {
mainChipID = mainChip->id;
} else if(usbChip != chipVersions.end()) {
mainChipID = usbChip->id;
} else {
return {};
}
BootloaderPipeline pipeline;
for(const auto& version : chipVersions) {
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip);
}
pipeline.add<EnterApplicationPhase>(mainChipID);
pipeline.add<ReconnectPhase>();
pipeline.add<WaitPhase>(std::chrono::milliseconds(3000));
return pipeline;

View File

@ -231,6 +231,7 @@ typedef unsigned __int64 uint64_t;
#define NEODEVICE_GIGASTAR2 (0x00000029)
#define NEODEVICE_FIRE3_T1S_LIN (0x0000002A)
#define NEODEVICE_FIRE3_T1S_SENT (0x0000002B)
#define NEODEVICE_RADGEMINI (0x0000002C)
#define NEODEVICE_RED (0x00000040)
#define NEODEVICE_ECU (0x00000080)
#define NEODEVICE_IEVB (0x00000100)
@ -1032,6 +1033,11 @@ typedef union _stChipVersions
uint8_t mchip_minor;
} radmoon3_versions;
struct
{
uint8_t mchip_major;
uint8_t mchip_minor;
} radgemini_versions;
struct
{
uint8_t mchip_major;
uint8_t mchip_minor;
@ -2842,6 +2848,31 @@ typedef struct _SRADMoon3Settings
#define SRADMoon3Settings_SIZE 68
typedef struct _SRADGeminiSettings
{
uint16_t perf_en; // 2
ETHERNET_SETTINGS2 ethernet1; // 16
ETHERNET_SETTINGS2 ethernet2; // 16
ETHERNET_SETTINGS2 autoEthernet1; // 16
ETHERNET_SETTINGS2 autoEthernet2; // 16
uint16_t network_enabled_on_boot; // 2
uint16_t network_enables; // 2
uint16_t network_enables_2; // 2
uint16_t network_enables_3; // 2
uint16_t network_enables_4; // 2
uint64_t network_enables_5; // 8
struct
{
uint16_t enableLatencyTest : 1;
uint16_t reserved : 15;
} flags; // 2
} SRADGeminiSettings;
#define SRADGeminiSettings_SIZE 86
typedef struct _SRADGigalogSettings
{
uint32_t ecu_id;
@ -4626,6 +4657,7 @@ typedef struct _GLOBAL_SETTINGS
SRADEpsilonSettings epsilon;
SRADBMSSettings rad_bms;
SRADMoon3Settings radmoon3;
SRADGeminiSettings radgemini;
SRADCometSettings radcomet;
// Make sure SDeviceSettings matches this
};
@ -4676,6 +4708,11 @@ typedef enum _EDeviceSettingsType
DeviceFire3FlexraySettingsType,
DeviceRADCometSettingsType,
DeviceRed2OemSettingsType,
DeviceRADComet3SettingsType,
DeviceRADGalaxy2SettingsType,
DeviceRADGigastar2SettingsType,
DeviceRADMoonT1SSettingsType,
DeviceRADGeminiSettingsType,
// add new settings type here
DeviceSettingsTypeMax,
DeviceSettingsNone = 0xFFFFFFFF // just wanted to reserve this
@ -4726,6 +4763,7 @@ typedef struct _SDeviceSettings
SRADEpsilonSettings epsilon;
SRADBMSSettings rad_bms;
SRADMoon3Settings radmoon3;
SRADGeminiSettings radgemini;
SFire3FlexraySettings fire3Flexray;
SRADCometSettings radcomet;
// Make sure GLOBAL_SETTINGS matches this
@ -5558,6 +5596,7 @@ CHECK_STRUCT_SIZE(SRADEpsilonSettings);
CHECK_STRUCT_SIZE(RAD_GPTP_SETTINGS);
CHECK_STRUCT_SIZE(SRADBMSSettings);
CHECK_STRUCT_SIZE(SRADMoon3Settings);
CHECK_STRUCT_SIZE(SRADGeminiSettings);
CHECK_STRUCT_SIZE(SFire3FlexraySettings);
CHECK_STRUCT_SIZE(CANHubSettings);
CHECK_STRUCT_SIZE(SRADCometSettings);

View File

@ -29,6 +29,7 @@
#include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
#include "icsneo/device/tree/radmoon3/radmoon3.h"
#include "icsneo/device/tree/radgemini/radgemini.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h"

View File

@ -29,6 +29,7 @@
#include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
#include "icsneo/device/tree/radmoon3/radmoon3.h"
#include "icsneo/device/tree/radgemini/radgemini.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h"