Device: Add CoreMini flashing support
parent
ec51393dfc
commit
4248c1a538
|
|
@ -510,7 +510,33 @@ bool Device::stopScript()
|
|||
}
|
||||
|
||||
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);
|
||||
if(!startAddress) {
|
||||
return false;
|
||||
|
|
@ -531,29 +557,12 @@ bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::Memory
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!stream || stream->bad()) {
|
||||
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
if(!clearScript(memType)) {
|
||||
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);
|
||||
if(!eraseScriptMemory(memType, static_cast<uint64_t>(bin.size()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -563,7 +572,7 @@ bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::Memory
|
|||
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);
|
||||
return false; // Failed to write
|
||||
}
|
||||
|
|
@ -571,16 +580,60 @@ bool Device::uploadCoremini(std::unique_ptr<std::istream>&& stream, Disk::Memory
|
|||
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())
|
||||
return false;
|
||||
|
||||
|
||||
auto startAddress = getCoreminiStartAddress(memType);
|
||||
if(!startAddress) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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(ScriptLocation, clearData.data(), clearData.size());
|
||||
auto written = writeLogicalDisk(*startAddress, clearData.data(), clearData.size(), std::chrono::milliseconds(2000), memType);
|
||||
|
||||
return written > 0;
|
||||
if(!written) {
|
||||
return false;
|
||||
}
|
||||
if(*written == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Device::transmit(std::shared_ptr<Frame> frame) {
|
||||
|
|
|
|||
|
|
@ -18,18 +18,20 @@ std::optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communicatio
|
|||
|
||||
const uint64_t currentSector = pos / SectorSize;
|
||||
const uint8_t memLocation = (uint8_t)memType;
|
||||
|
||||
uint64_t numWords = amount / 2;
|
||||
|
||||
auto msg = com.waitForMessageSync([¤tSector, &memLocation, &com] {
|
||||
auto msg = com.waitForMessageSync([¤tSector, &memLocation, &com, &numWords] {
|
||||
return com.sendCommand(Command::NeoReadMemory, {
|
||||
memLocation,
|
||||
uint8_t(currentSector & 0xFF),
|
||||
uint8_t((currentSector >> 8) & 0xFF),
|
||||
uint8_t((currentSector >> 16) & 0xFF),
|
||||
uint8_t((currentSector >> 24) & 0xFF),
|
||||
uint8_t(SectorSize & 0xFF),
|
||||
uint8_t((SectorSize >> 8) & 0xFF),
|
||||
uint8_t((SectorSize >> 16) & 0xFF),
|
||||
uint8_t((SectorSize >> 24) & 0xFF)
|
||||
uint8_t(numWords & 0xFF),
|
||||
uint8_t((numWords >> 8) & 0xFF),
|
||||
uint8_t((numWords >> 16) & 0xFF),
|
||||
uint8_t((numWords >> 24) & 0xFF)
|
||||
});
|
||||
}, NeoMemorySDRead, timeout);
|
||||
|
||||
|
|
@ -60,15 +62,17 @@ std::optional<uint64_t> NeoMemoryDiskDriver::writeLogicalDiskAligned(Communicati
|
|||
const uint64_t currentSector = pos / SectorSize;
|
||||
const uint8_t memLocation = (uint8_t)memType;
|
||||
|
||||
auto msg = com.waitForMessageSync([¤tSector, &memLocation, &com, from, amount] {
|
||||
uint64_t numWords = amount / 2;
|
||||
|
||||
auto msg = com.waitForMessageSync([¤tSector, &memLocation, &com, from, amount, &numWords] {
|
||||
std::vector<uint8_t> command = {
|
||||
memLocation,
|
||||
uint8_t(currentSector & 0xFF),
|
||||
uint8_t((currentSector >> 8) & 0xFF),
|
||||
uint8_t((currentSector >> 16) & 0xFF),
|
||||
uint8_t((currentSector >> 24) & 0xFF),
|
||||
uint8_t(SectorSize & 0xFF),
|
||||
uint8_t((SectorSize >> 8) & 0xFF),
|
||||
uint8_t(numWords & 0xFF),
|
||||
uint8_t((numWords >> 8) & 0xFF),
|
||||
};
|
||||
command.insert(command.end(), from, from + amount);
|
||||
return com.sendCommand(Command::NeoWriteMemory, command);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Usage:
|
||||
// ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH]
|
||||
// ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH] [FLASH | SD]
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
void displayUsage() {
|
||||
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) {
|
||||
std::vector<std::string> arguments(argv, argv + argc);
|
||||
|
||||
if(arguments.size() != 3) {
|
||||
if(arguments.size() != 4) {
|
||||
displayUsage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
@ -50,14 +50,25 @@ int main(int argc, char** argv) {
|
|||
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 << 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 << icsneo::GetLastError() << std::endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ enum class Command : uint8_t {
|
|||
GetVBattReq = 0xDF, // Previously known as RED_CMD_VBATT_REQUEST
|
||||
ScriptStatus = 0xE0, // Previously known as RED_CMD_SCRIPT_STATUS
|
||||
MiscControl = 0xE7,
|
||||
NeoEraseMemory = 0xEA, // Previously known as RED_CMD_ERASE_MEMORY
|
||||
Extended = 0xF0, // Previously known as RED_CMD_EXT_COMM
|
||||
ExtendedData = 0xF2, // Previously known as RED_CMD_EXTENDED_DATA
|
||||
FlexRayControl = 0xF3,
|
||||
|
|
|
|||
|
|
@ -148,9 +148,11 @@ public:
|
|||
int8_t prepareScriptLoad();
|
||||
bool startScript(Disk::MemoryType memType = Disk::MemoryType::SD);
|
||||
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 eraseScriptMemory(Disk::MemoryType memType, uint64_t amount);
|
||||
|
||||
virtual std::optional<MemoryAddress> getCoreminiStartAddressFlash() const {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/device/devicetype.h"
|
||||
#include "icsneo/device/tree/neovifire2/neovifire2settings.h"
|
||||
|
||||
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||
namespace icsneo {
|
||||
|
||||
class NeoVIFIRE2 : public Device {
|
||||
|
|
@ -89,7 +89,7 @@ public:
|
|||
|
||||
protected:
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue