Device: Add CoreMini flashing support

pull/62/head
Yasser Yassine 2023-11-08 23:41:26 +00:00
parent ec51393dfc
commit 4248c1a538
6 changed files with 113 additions and 42 deletions

View File

@ -510,7 +510,33 @@ bool Device::stopScript()
} }
bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::MemoryType memType) { bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::MemoryType memType) {
if(!stream || stream->bad()) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return false;
}
std::vector<char> bin(std::istreambuf_iterator<char>(*stream), {}); // Read the whole stream
if(bin.size() < 4) {
report(APIEvent::Type::BufferInsufficient, APIEvent::Severity::Error);
return false;
}
uint16_t scriptVersion = *(uint16_t*)(&bin[2]); // Third and fourth byte are version number stored in little endian
auto scriptStatus = getScriptStatus();
if(!scriptStatus) {
return false; // Already added an API error
}
if(scriptStatus->coreminiVersion != scriptVersion) {
// Version on device and script are not the same
report(APIEvent::Type::CoreminiUploadVersionMismatch, APIEvent::Severity::Error);
return false;
}
auto startAddress = getCoreminiStartAddress(memType); auto startAddress = getCoreminiStartAddress(memType);
if(!startAddress) { if(!startAddress) {
return false; return false;
@ -531,29 +557,12 @@ bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::Memory
return false; return false;
} }
if(!stream || stream->bad()) { if(!clearScript(memType)) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return false; return false;
} }
std::vector<char> bin(std::istreambuf_iterator<char>(*stream), {}); // Read the whole stream
if(bin.size() < 4) { if(!eraseScriptMemory(memType, static_cast<uint64_t>(bin.size()))) {
report(APIEvent::Type::BufferInsufficient, APIEvent::Severity::Error);
return false;
}
uint16_t scriptVersion = *(uint16_t*)(&bin[2]); // Third and fourth byte are version number stored in little endian
auto scriptStatus = getScriptStatus();
if(!scriptStatus) {
return false; // Already added an API error
}
if(scriptStatus->coreminiVersion != scriptVersion) {
// Version on device and script are not the same
report(APIEvent::Type::CoreminiUploadVersionMismatch, APIEvent::Severity::Error);
return false; return false;
} }
@ -563,7 +572,7 @@ bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::Memory
return false; // Already added an API error return false; // Already added an API error
} }
if(*numWritten == 0) { if(*numWritten != static_cast<uint64_t>(bin.size())) {
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error); report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
return false; // Failed to write return false; // Failed to write
} }
@ -571,16 +580,60 @@ bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::Memory
return true; return true;
} }
bool Device::clearScript() bool Device::eraseScriptMemory(Disk::MemoryType memType, uint64_t amount) {
static std::shared_ptr<MessageFilter> NeoEraseDone = std::make_shared<MessageFilter>(Network::NetID::NeoMemoryWriteDone);
auto startAddress = getCoreminiStartAddress(memType);
if(!startAddress) {
return false;
}
if(memType != Disk::MemoryType::Flash) {
// Only need to erase on flash
return true;
}
std::vector<uint8_t> arguments(9, 0);
uint32_t numWords = static_cast<uint32_t>(amount / 2);
arguments[0] = static_cast<uint8_t>(memType);
*reinterpret_cast<uint32_t*>(&arguments[1]) = static_cast<uint32_t>(*startAddress / 512);
*reinterpret_cast<uint32_t*>(&arguments[5])= numWords;
auto msg = com->waitForMessageSync([this, &arguments] {
return com->sendCommand(Command::NeoEraseMemory, arguments);
}, NeoEraseDone, std::chrono::milliseconds(3000));
if(!msg) {
return false;
}
return true;
}
bool Device::clearScript(Disk::MemoryType memType)
{ {
if(!stopScript()) if(!stopScript())
return false; return false;
auto startAddress = getCoreminiStartAddress(memType);
if(!startAddress) {
return false;
}
std::vector<uint8_t> clearData(512, 0xCD); std::vector<uint8_t> clearData(512, 0xCD);
uint64_t ScriptLocation = 0; //We only support a coremini in an SDCard, which is at the very beginning of the card auto written = writeLogicalDisk(*startAddress, clearData.data(), clearData.size(), std::chrono::milliseconds(2000), memType);
auto written = writeLogicalDisk(ScriptLocation, clearData.data(), clearData.size());
return written > 0; if(!written) {
return false;
}
if(*written == 0) {
return false;
}
return true;
} }
bool Device::transmit(std::shared_ptr<Frame> frame) { bool Device::transmit(std::shared_ptr<Frame> frame) {

View File

@ -18,18 +18,20 @@ std::optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communicatio
const uint64_t currentSector = pos / SectorSize; const uint64_t currentSector = pos / SectorSize;
const uint8_t memLocation = (uint8_t)memType; const uint8_t memLocation = (uint8_t)memType;
uint64_t numWords = amount / 2;
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com] { auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com, &numWords] {
return com.sendCommand(Command::NeoReadMemory, { return com.sendCommand(Command::NeoReadMemory, {
memLocation, memLocation,
uint8_t(currentSector & 0xFF), uint8_t(currentSector & 0xFF),
uint8_t((currentSector >> 8) & 0xFF), uint8_t((currentSector >> 8) & 0xFF),
uint8_t((currentSector >> 16) & 0xFF), uint8_t((currentSector >> 16) & 0xFF),
uint8_t((currentSector >> 24) & 0xFF), uint8_t((currentSector >> 24) & 0xFF),
uint8_t(SectorSize & 0xFF), uint8_t(numWords & 0xFF),
uint8_t((SectorSize >> 8) & 0xFF), uint8_t((numWords >> 8) & 0xFF),
uint8_t((SectorSize >> 16) & 0xFF), uint8_t((numWords >> 16) & 0xFF),
uint8_t((SectorSize >> 24) & 0xFF) uint8_t((numWords >> 24) & 0xFF)
}); });
}, NeoMemorySDRead, timeout); }, NeoMemorySDRead, timeout);
@ -60,15 +62,17 @@ std::optional<uint64_t> NeoMemoryDiskDriver::writeLogicalDiskAligned(Communicati
const uint64_t currentSector = pos / SectorSize; const uint64_t currentSector = pos / SectorSize;
const uint8_t memLocation = (uint8_t)memType; const uint8_t memLocation = (uint8_t)memType;
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com, from, amount] { uint64_t numWords = amount / 2;
auto msg = com.waitForMessageSync([&currentSector, &memLocation, &com, from, amount, &numWords] {
std::vector<uint8_t> command = { std::vector<uint8_t> command = {
memLocation, memLocation,
uint8_t(currentSector & 0xFF), uint8_t(currentSector & 0xFF),
uint8_t((currentSector >> 8) & 0xFF), uint8_t((currentSector >> 8) & 0xFF),
uint8_t((currentSector >> 16) & 0xFF), uint8_t((currentSector >> 16) & 0xFF),
uint8_t((currentSector >> 24) & 0xFF), uint8_t((currentSector >> 24) & 0xFF),
uint8_t(SectorSize & 0xFF), uint8_t(numWords & 0xFF),
uint8_t((SectorSize >> 8) & 0xFF), uint8_t((numWords >> 8) & 0xFF),
}; };
command.insert(command.end(), from, from + amount); command.insert(command.end(), from, from + amount);
return com.sendCommand(Command::NeoWriteMemory, command); return com.sendCommand(Command::NeoWriteMemory, command);

View File

@ -1,5 +1,5 @@
// Usage: // Usage:
// ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH] // ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH] [FLASH | SD]
#include <iostream> #include <iostream>
@ -8,14 +8,14 @@
void displayUsage() { void displayUsage() {
std::cout << "Usage:\n"; std::cout << "Usage:\n";
std::cout << "./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH]\n"; std::cout << "./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH] [FLASH | SD]\n";
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
std::vector<std::string> arguments(argv, argv + argc); std::vector<std::string> arguments(argv, argv + argc);
if(arguments.size() != 3) { if(arguments.size() != 4) {
displayUsage(); displayUsage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -50,14 +50,25 @@ int main(int argc, char** argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!device->uploadCoremini(std::make_unique<std::ifstream>(arguments[2], std::ios::binary), icsneo::Disk::MemoryType::Flash)) std::string memTypeString = arguments[3];
{
icsneo::Disk::MemoryType type;
if(memTypeString == "FLASH") {
type = icsneo::Disk::MemoryType::Flash;
} else if(memTypeString == "SD") {
type = icsneo::Disk::MemoryType::SD;
} else {
std::cout << "Incorrect memory type option" << std::endl;
displayUsage();
return EXIT_FAILURE;
}
if (!device->uploadCoremini(std::make_unique<std::ifstream>(arguments[2], std::ios::binary), type)) {
std::cout << "Failed to upload coremini" << std::endl; std::cout << "Failed to upload coremini" << std::endl;
std::cout << icsneo::GetLastError() << std::endl; std::cout << icsneo::GetLastError() << std::endl;
} }
if (!device->startScript(icsneo::Disk::MemoryType::Flash)) if (!device->startScript(type)) {
{
std::cout << "Failed to start script" << std::endl; std::cout << "Failed to start script" << std::endl;
std::cout << icsneo::GetLastError() << std::endl; std::cout << icsneo::GetLastError() << std::endl;
} }

View File

@ -31,6 +31,7 @@ enum class Command : uint8_t {
GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST
ScriptStatus = 0xE0, // Previously known as RED_CMD_SCRIPT_STATUS ScriptStatus = 0xE0, // Previously known as RED_CMD_SCRIPT_STATUS
MiscControl = 0xE7, MiscControl = 0xE7,
NeoEraseMemory = 0xEA, // Previously known as RED_CMD_ERASE_MEMORY
Extended = 0xF0, // Previously known as RED_CMD_EXT_COMM Extended = 0xF0, // Previously known as RED_CMD_EXT_COMM
ExtendedData = 0xF2, // Previously known as RED_CMD_EXTENDED_DATA ExtendedData = 0xF2, // Previously known as RED_CMD_EXTENDED_DATA
FlexRayControl = 0xF3, FlexRayControl = 0xF3,

View File

@ -148,9 +148,11 @@ public:
int8_t prepareScriptLoad(); int8_t prepareScriptLoad();
bool startScript(Disk::MemoryType memType = Disk::MemoryType::SD); bool startScript(Disk::MemoryType memType = Disk::MemoryType::SD);
bool stopScript(); bool stopScript();
bool clearScript(); bool clearScript(Disk::MemoryType memType = Disk::MemoryType::SD);
bool uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::MemoryType memType = Disk::MemoryType::SD); bool uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::MemoryType memType = Disk::MemoryType::SD);
bool eraseScriptMemory(Disk::MemoryType memType, uint64_t amount);
virtual std::optional<MemoryAddress> getCoreminiStartAddressFlash() const { virtual std::optional<MemoryAddress> getCoreminiStartAddressFlash() const {
return std::nullopt; return std::nullopt;
} }

View File

@ -6,7 +6,7 @@
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/neovifire2/neovifire2settings.h" #include "icsneo/device/tree/neovifire2/neovifire2settings.h"
#include "icsneo/disk/neomemorydiskdriver.h"
namespace icsneo { namespace icsneo {
class NeoVIFIRE2 : public Device { class NeoVIFIRE2 : public Device {
@ -89,7 +89,7 @@ public:
protected: protected:
NeoVIFIRE2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { NeoVIFIRE2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<NeoVIFIRE2Settings>(makeDriver); initialize<NeoVIFIRE2Settings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
} }
void setupSettings(IDeviceSettings& ssettings) override { void setupSettings(IDeviceSettings& ssettings) override {