Added support for flashing AVR multi on horus targets (#6888)

* Added support for flashing AVR multi on horus targets

taranis soft serial

Added support for flashing AVR multi on horus targets

taranis soft serial

* Added support for multi V2 signature (hex code)

* Check multi signature before flashing

* small clean-up

* Cosmetics

* Fix v2 signature check

* Cosmetics
This commit is contained in:
Raphael Coeffic
2019-10-16 15:29:10 +02:00
committed by 3djc
parent f1d8083064
commit aaafe445db
26 changed files with 544 additions and 88 deletions
+168 -63
View File
@@ -26,8 +26,6 @@
#define UPDATE_MULTI_EXT_BIN ".bin"
//#define DEBUG_EXT_MODULE_FLASH
class MultiFirmwareUpdateDriver
{
public:
@@ -39,6 +37,7 @@ class MultiFirmwareUpdateDriver
virtual bool getByte(uint8_t& byte) const = 0;
virtual void sendByte(uint8_t byte) const = 0;
virtual void clear() const = 0;
virtual void deinit() const {}
private:
bool getRxByte(uint8_t& byte) const;
@@ -47,6 +46,7 @@ class MultiFirmwareUpdateDriver
const char * getDeviceSignature(uint8_t* signature) const;
const char * loadAddress(uint32_t offset) const;
const char * progPage(uint8_t* buffer, uint16_t size) const;
void leaveProgMode() const;
};
#if defined(INTERNAL_MODULE_MULTI)
@@ -77,16 +77,21 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver
{
intmoduleFifo.clear();
}
void deinit() const override
{
clear();
}
};
static const MultiInternalUpdateDriver multiInternalUpdateDriver;
#endif
class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
class MultiExternalSoftSerialUpdateDriver: public MultiFirmwareUpdateDriver
{
public:
MultiExternalUpdateDriver() = default;
MultiExternalSoftSerialUpdateDriver() = default;
protected:
void init() const override
@@ -102,7 +107,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
#endif
EXTERNAL_MODULE_ON();
telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT);
telemetryPortInvertedInit(57600);
}
bool getByte(uint8_t& byte) const override
@@ -119,9 +124,15 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver
{
telemetryClearFifo();
}
void deinit() const override
{
telemetryPortInvertedInit(0);
clear();
}
};
static const MultiExternalUpdateDriver multiExternalUpdateDriver;
static const MultiExternalSoftSerialUpdateDriver multiExternalSoftSerialUpdateDriver;
bool MultiFirmwareUpdateDriver::getRxByte(uint8_t& byte) const
{
@@ -150,10 +161,10 @@ bool MultiFirmwareUpdateDriver::checkRxByte(uint8_t byte) const
const char * MultiFirmwareUpdateDriver::waitForInitialSync() const
{
clear();
uint8_t byte;
int retries = 1000;
clear();
do {
// Send sync request
sendByte(STK_GET_SYNC);
@@ -214,16 +225,14 @@ const char * MultiFirmwareUpdateDriver::loadAddress(uint32_t offset) const
const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size) const
{
sendByte(STK_PROG_PAGE);
// page size 256
sendByte(1);
sendByte(0);
// page size
sendByte(size >> 8);
sendByte(size & 0xFF);
// flash/eeprom flag
sendByte(0);
// #if defined(DEBUG_EXT_MODULE_FLASH)
// TRACE("writing at 0x%X", writeOffset << 1);
// #endif
for (uint16_t i=0; i < size; i++) {
sendByte(buffer[i]);
}
@@ -245,6 +254,16 @@ const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size)
return nullptr;
}
void MultiFirmwareUpdateDriver::leaveProgMode() const
{
sendByte(STK_LEAVE_PROGMODE);
sendByte(CRC_EOP);
// eat last sync byte
checkRxByte(STK_INSYNC);
deinit();
}
const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* label) const
{
const char* result = nullptr;
@@ -255,24 +274,39 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
RTOS_WAIT_MS(500);
result = waitForInitialSync();
if (result != nullptr)
if (result) {
leaveProgMode();
return result;
}
unsigned char signature[4]; // 3 bytes signature + STK_OK
result = getDeviceSignature(signature);
if (result != nullptr)
if (result) {
leaveProgMode();
return result;
}
uint8_t buffer[256]; // page size = 256
uint32_t writeOffset = 0x1000; // start offset (word address)
uint8_t buffer[256];
uint16_t pageSize = 128;
uint32_t writeOffset = 0;
if (signature[0] != 0x1E) {
leaveProgMode();
return "Wrong signature";
}
if (signature[1] == 0x55 && signature[2] == 0xAA) {
pageSize = 256;
writeOffset = 0x1000; // start offset (word address)
}
while (!f_eof(file)) {
drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize);
UINT count=0;
memclear(buffer, 256);
if (f_read(file, buffer, 256, &count) != FR_OK) {
memclear(buffer, pageSize);
if (f_read(file, buffer, pageSize, &count) != FR_OK) {
result = "Error reading file";
break;
}
@@ -283,28 +317,23 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
clear();
result = loadAddress(writeOffset);
if (result != nullptr) {
if (result) {
break;
}
result = progPage(buffer, 256);
if (result != nullptr) {
result = progPage(buffer, pageSize);
if (result) {
break;
}
writeOffset += 128; // page / 2
writeOffset += pageSize / 2;
}
if (f_eof(file)) {
drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize);
}
sendByte(STK_LEAVE_PROGMODE);
sendByte(CRC_EOP);
// eat last sync byte
checkRxByte(STK_INSYNC);
leaveProgMode();
return result;
}
@@ -316,19 +345,9 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab
#define MULTI_SIGN_TELEM_INVERSION_OFFSET 13
#define MULTI_SIGN_VERSION_OFFSET 15
const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename)
const char * MultiFirmwareInformation::readV1Signature(const char * buffer)
{
FIL file;
f_open(&file, filename, FA_READ);
char buffer[MULTI_SIGN_SIZE];
UINT count;
f_lseek(&file, f_size(&file) - MULTI_SIGN_SIZE);
if (f_read(&file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) {
return "Error reading file";
}
if(!memcmp(buffer, "multi-stm", 9))
if (!memcmp(buffer, "multi-stm", 9))
boardType = FIRMWARE_MULTI_STM;
else if (!memcmp(buffer, "multi-avr", 9))
boardType = FIRMWARE_MULTI_AVR;
@@ -348,9 +367,9 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char *
bootloaderCheck = false;
if(buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 't')
telemetryType = FIRMWARE_MULTI_TELEM_MULTI;
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_STATUS;
else if (buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 's')
telemetryType = FIRMWARE_MULTI_TELEM_STATUS;
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY;
else
telemetryType = FIRMWARE_MULTI_TELEM_NONE;
@@ -362,23 +381,115 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char *
return nullptr;
}
const char * MultiFirmwareInformation::readV2Signature(const char * buffer)
{
// new format
uint32_t options = 0;
const char * beg = buffer + 7;
const char * cursor = beg;
while (cursor - beg < 8) {
options <<= 4;
if (*cursor >= '0' && *cursor <= '9')
options |= *cursor - '0';
else if (*cursor >= 'a' && *cursor <= 'f')
options |= *cursor - 'a' + 10;
else if (*cursor >= 'A' && *cursor <= 'F')
options |= *cursor - 'A' + 10;
else
break; // should be '-'
cursor++;
}
if (cursor - beg < 8)
return "Invalid signature";
const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
boardType = options & 0x3;
optibootSupport = options & 0x80 ? true : false;
telemetryInversion = options & 0x200 ? true : false;
bootloaderCheck = options & 0x100 ? true : false;
telemetryType = FIRMWARE_MULTI_TELEM_NONE;
if (options & 0x400)
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_STATUS;
if (options & 0x800)
telemetryType = FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY;
return nullptr;
}
const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename)
{
FIL file;
const char * result = nullptr;
if (f_open(&file, filename, FA_READ) != FR_OK)
return "Error opening file";
const char * ext = getFileExtension(filename);
if (ext && strcasecmp(ext, UPDATE_MULTI_EXT_BIN)) {
return "Wrong file extension";
const char * err = readMultiFirmwareInformation(&file);
f_close(&file);
return err;
}
const char * MultiFirmwareInformation::readMultiFirmwareInformation(FIL * file)
{
char buffer[MULTI_SIGN_SIZE];
UINT count;
if (f_size(file) < MULTI_SIGN_SIZE)
return "File too small";
f_lseek(file, f_size(file) - MULTI_SIGN_SIZE);
if (f_read(file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) {
return "Error reading file";
}
if (!memcmp(buffer, "multi-x", 7)) {
return readV2Signature(buffer);
}
return readV1Signature(buffer);
}
bool multiFlashFirmware(uint8_t moduleIdx, const char * filename)
{
FIL file;
if (f_open(&file, filename, FA_READ) != FR_OK) {
return "Error opening file";
POPUP_WARNING("Not a valid file");
return false;
}
MultiFirmwareInformation firmwareFile;
if (firmwareFile.readMultiFirmwareInformation(&file)) {
f_close(&file);
POPUP_WARNING("Not a valid file");
return false;
}
f_lseek(&file, 0);
if (moduleIdx == EXTERNAL_MODULE) {
if (!firmwareFile.isMultiExternalFirmware()) {
f_close(&file);
POPUP_WARNING(STR_NEEDS_FILE);
SET_WARNING_INFO(STR_EXT_MULTI_SPEC, strlen(STR_EXT_MULTI_SPEC), 0);
return false;
}
}
else {
if (!firmwareFile.isMultiInternalFirmware()) {
f_close(&file);
POPUP_WARNING(STR_NEEDS_FILE);
SET_WARNING_INFO(STR_INT_MULTI_SPEC, strlen(STR_INT_MULTI_SPEC), 0);
return false;
}
}
const MultiFirmwareUpdateDriver* driver = &multiExternalSoftSerialUpdateDriver;
#if defined(INTERNAL_MODULE_MULTI)
if (moduleIdx == INTERNAL_MODULE)
driver = &multiInternalUpdateDriver;
#endif
pausePulses();
#if defined(INTERNAL_MODULE_MULTI)
@@ -397,14 +508,7 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
watchdogSuspend(2000);
RTOS_WAIT_MS(2000);
// TODO: real update here
const MultiFirmwareUpdateDriver* driver = &multiExternalUpdateDriver;
#if defined(INTERNAL_MODULE_MULTI)
if (moduleIdx == INTERNAL_MODULE)
driver = &multiInternalUpdateDriver;
#endif
result = driver->flashFirmware(&file, getBasename(filename));
const char * result = driver->flashFirmware(&file, getBasename(filename));
f_close(&file);
AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1 );
@@ -425,8 +529,10 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
/* wait 2s off */
watchdogSuspend(2000);
RTOS_WAIT_MS(2000);
telemetryClearFifo();
// reset telemetry protocol
telemetryInit(255);
#if defined(INTERNAL_MODULE_MULTI)
if (intPwr) {
INTERNAL_MODULE_ON();
@@ -439,9 +545,8 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename)
setupPulsesExternalModule();
}
//state = SPORT_IDLE;
resumePulses();
return result;
return result == nullptr;
}
#endif
#endif