1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-25 09:15:38 +03:00

OTA Update added

This commit is contained in:
Bertrand Songis 2019-05-07 11:18:39 +02:00
parent daba1ffcb1
commit ad9d8001b2
6 changed files with 243 additions and 43 deletions

View file

@ -88,7 +88,9 @@ void onSdFormatConfirm(const char * result)
void onUpdateConfirmation(const char * result)
{
if (result == STR_OK) {
// TODO OTA Update
OtaUpdateInformation * destination = moduleState[EXTERNAL_MODULE].otaUpdateInformation;
Pxx2OtaUpdate otaUpdate(EXTERNAL_MODULE, destination->candidateReceiversNames[destination->selectedReceiverIndex]);
otaUpdate.flashFirmware(destination->filename);
}
else {
moduleState[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
@ -97,14 +99,14 @@ void onUpdateConfirmation(const char * result)
void onUpdateStateChanged()
{
if (reusableBuffer.sdManager.otaInformation.step == BIND_INFO_REQUEST) {
POPUP_CONFIRMATION(PXX2receiversModels[reusableBuffer.sdManager.otaInformation.receiverInformation.modelID], onUpdateConfirmation);
if (reusableBuffer.sdManager.otaUpdateInformation.step == BIND_INFO_REQUEST) {
POPUP_CONFIRMATION(PXX2receiversModels[reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.modelID], onUpdateConfirmation);
char * tmp = strAppend(reusableBuffer.sdManager.otaReceiverVersion, TR_CURRENT_VERSION);
tmp = strAppendUnsigned(tmp, 1 + reusableBuffer.sdManager.otaInformation.receiverInformation.swVersion.major);
tmp = strAppendUnsigned(tmp, 1 + reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.major);
*tmp++ = '.';
tmp = strAppendUnsigned(tmp, reusableBuffer.sdManager.otaInformation.receiverInformation.swVersion.minor);
tmp = strAppendUnsigned(tmp, reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.minor);
*tmp++ = '.';
tmp = strAppendUnsigned(tmp, reusableBuffer.sdManager.otaInformation.receiverInformation.swVersion.revision);
tmp = strAppendUnsigned(tmp, reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.swVersion.revision);
SET_WARNING_INFO(reusableBuffer.sdManager.otaReceiverVersion, tmp - reusableBuffer.sdManager.otaReceiverVersion, 0);
}
}
@ -203,9 +205,9 @@ void onSdManagerMenu(const char * result)
}
#endif
else if (result == STR_FLASH_RECEIVER_OTA) {
getSelectionFullPath(lfn);
memclear(&reusableBuffer.sdManager.otaInformation, sizeof(BindInformation));
moduleState[EXTERNAL_MODULE].startBind(&reusableBuffer.sdManager.otaInformation, onUpdateStateChanged);
memclear(&reusableBuffer.sdManager.otaUpdateInformation, sizeof(OtaUpdateInformation));
getSelectionFullPath(reusableBuffer.sdManager.otaUpdateInformation.filename);
moduleState[EXTERNAL_MODULE].startBind(&reusableBuffer.sdManager.otaUpdateInformation, onUpdateStateChanged);
}
#endif
#if defined(LUA)
@ -219,10 +221,10 @@ void onSdManagerMenu(const char * result)
void onUpdateReceiverSelection(const char * result)
{
if (result != STR_EXIT) {
reusableBuffer.sdManager.otaInformation.selectedReceiverIndex = (result - reusableBuffer.sdManager.otaInformation.candidateReceiversNames[0]) / sizeof(reusableBuffer.sdManager.otaInformation.candidateReceiversNames[0]);
reusableBuffer.sdManager.otaInformation.step = BIND_INFO_REQUEST;
reusableBuffer.sdManager.otaUpdateInformation.selectedReceiverIndex = (result - reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[0]) / sizeof(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[0]);
reusableBuffer.sdManager.otaUpdateInformation.step = BIND_INFO_REQUEST;
#if defined(SIMU)
reusableBuffer.sdManager.otaInformation.receiverInformation.modelID = 0x01;
reusableBuffer.sdManager.otaUpdateInformation.receiverInformation.modelID = 0x01;
onUpdateStateChanged();
#endif
}
@ -483,11 +485,11 @@ void menuRadioSdManager(event_t _event)
}
if (moduleState[EXTERNAL_MODULE].mode == MODULE_MODE_BIND) {
if (reusableBuffer.sdManager.otaInformation.step == BIND_INIT) {
if (reusableBuffer.sdManager.otaInformation.candidateReceiversCount > 0) {
popupMenuItemsCount = min<uint8_t>(reusableBuffer.sdManager.otaInformation.candidateReceiversCount, PXX2_MAX_RECEIVERS_PER_MODULE);
if (reusableBuffer.sdManager.otaUpdateInformation.step == BIND_INIT) {
if (reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount > 0) {
popupMenuItemsCount = min<uint8_t>(reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversCount, PXX2_MAX_RECEIVERS_PER_MODULE);
for (uint8_t i=0; i<popupMenuItemsCount; i++) {
popupMenuItems[i] = reusableBuffer.sdManager.otaInformation.candidateReceiversNames[i];
popupMenuItems[i] = reusableBuffer.sdManager.otaUpdateInformation.candidateReceiversNames[i];
}
popupMenuTitle = STR_PXX2_SELECT_RX;
CLEAR_POPUP();

View file

@ -1164,7 +1164,7 @@ union ReusableBuffer
uint16_t offset;
uint16_t count;
char originalName[SD_SCREEN_FILE_LENGTH+1];
BindInformation otaInformation;
OtaUpdateInformation otaUpdateInformation;
char otaReceiverVersion[sizeof(TR_CURRENT_VERSION) + 12];
} sdManager;
#endif

View file

@ -27,6 +27,7 @@
#include "pulses/pxx1.h"
#include "pulses/pxx2.h"
#include "modules.h"
#include "ff.h"
#if NUM_MODULES > 1
#define IS_RANGECHECK_ENABLE() (moduleState[0].mode == MODULE_MODE_RANGECHECK || moduleState[1].mode == MODULE_MODE_RANGECHECK)
@ -77,7 +78,8 @@ enum ModuleSettingsMode
MODULE_MODE_BIND,
MODULE_MODE_SHARE,
MODULE_MODE_RANGECHECK,
MODULE_MODE_RESET
MODULE_MODE_RESET,
MODULE_MODE_OTA_UPDATE,
};
@ -104,35 +106,44 @@ PACK(struct ModuleInformation {
} receivers[PXX2_MAX_RECEIVERS_PER_MODULE];
});
struct ModuleSettings {
uint8_t state; // 0x00 = READ 0x40 = WRITE
tmr10ms_t retryTime;
uint8_t rfProtocol;
uint8_t externalAntenna;
int8_t txPower;
class ModuleSettings {
public:
uint8_t state; // 0x00 = READ 0x40 = WRITE
tmr10ms_t retryTime;
uint8_t rfProtocol;
uint8_t externalAntenna;
int8_t txPower;
};
struct ReceiverSettings {
uint8_t state; // 0x00 = READ 0x40 = WRITE
tmr10ms_t timeout;
uint8_t receiverId;
uint8_t dirty;
uint8_t telemetryDisabled;
uint8_t pwmRate;
uint8_t outputsCount;
uint8_t outputsMapping[24];
class ReceiverSettings {
public:
uint8_t state; // 0x00 = READ 0x40 = WRITE
tmr10ms_t timeout;
uint8_t receiverId;
uint8_t dirty;
uint8_t telemetryDisabled;
uint8_t pwmRate;
uint8_t outputsCount;
uint8_t outputsMapping[24];
};
struct BindInformation {
uint8_t step;
uint32_t timeout;
char candidateReceiversNames[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME + 1];
uint8_t candidateReceiversCount;
uint8_t selectedReceiverIndex;
uint8_t rxUid;
uint8_t lbtMode;
uint8_t flexMode;
PXX2HardwareInformation receiverInformation;
class BindInformation {
public:
uint8_t step;
uint32_t timeout;
char candidateReceiversNames[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME + 1];
uint8_t candidateReceiversCount;
uint8_t selectedReceiverIndex;
uint8_t rxUid;
uint8_t lbtMode;
uint8_t flexMode;
PXX2HardwareInformation receiverInformation;
};
class OtaUpdateInformation: public BindInformation {
public:
char filename[_MAX_LFN+1];
uint32_t address;
};
typedef void (* ModuleCallback)();
@ -156,6 +167,7 @@ PACK(struct ModuleState {
ModuleInformation * moduleInformation;
ModuleSettings * moduleSettings;
BindInformation * bindInformation;
OtaUpdateInformation * otaUpdateInformation;
};
ModuleCallback callback;

View file

@ -287,8 +287,40 @@ void Pxx2Pulses::setupShareMode(uint8_t module)
Pxx2Transport::addByte(reusableBuffer.moduleSetup.pxx2.shareReceiverIndex);
}
void Pxx2Pulses::sendOtaUpdate(uint8_t module, const char * rxName, uint32_t address, const char * data)
{
initFrame();
addFrameType(PXX2_TYPE_C_OTA, PXX2_TYPE_ID_OTA);
if (rxName) {
Pxx2Transport::addByte(0x00);
for (uint8_t i=0; i<PXX2_LEN_RX_NAME; i++) {
Pxx2Transport::addByte(rxName[i]);
}
}
else if (data) {
Pxx2Transport::addByte(0x01);
Pxx2Transport::addWord(address);
for (uint8_t i=0; i<32; i++) {
Pxx2Transport::addByte(data[i]);
}
}
else {
Pxx2Transport::addByte(0x02);
}
endFrame();
if (module == EXTERNAL_MODULE)
extmoduleSendNextFrame();
}
void Pxx2Pulses::setupFrame(uint8_t module)
{
if (moduleState[module].mode == MODULE_MODE_OTA_UPDATE)
return;
initFrame();
switch (moduleState[module].mode) {
@ -336,3 +368,95 @@ void Pxx2Pulses::setupFrame(uint8_t module)
endFrame();
}
bool Pxx2OtaUpdate::waitStep(uint8_t step, uint8_t timeout)
{
OtaUpdateInformation * destination = moduleState[module].otaUpdateInformation;
uint8_t elapsed = 0;
watchdogSuspend(100);
while (step != destination->step) {
if (elapsed++ > timeout) {
return false;
}
RTOS_WAIT_MS(1);
telemetryWakeup();
}
return true;
}
const char * Pxx2OtaUpdate::doFlashFirmware(const char * filename)
{
FIL file;
uint8_t buffer[32];
UINT count = 0;
OtaUpdateInformation * destination = moduleState[module].otaUpdateInformation;
destination->step = OTA_UPDATE_START;
extmodulePulsesData.pxx2.sendOtaUpdate(module, rxName, 0, nullptr);
if (!waitStep(OTA_UPDATE_START_ACK, 10)) {
return "OTA start failed";
}
if (f_open(&file, filename, FA_READ) != FR_OK) {
return "Opening file failed";
}
uint32_t size = f_size(&file);
uint32_t done = 0;
while (1) {
done += count;
drawProgressScreen(getBasename(filename), "OTA update...", done, size);
if (f_read(&file, buffer, sizeof(buffer), &count) != FR_OK) {
f_close(&file);
return "Reading file failed";
}
destination->step = OTA_UPDATE_TRANSFER;
extmodulePulsesData.pxx2.sendOtaUpdate(module, nullptr, done, (char *)buffer);
if (!waitStep(OTA_UPDATE_TRANSFER_ACK, 10)) {
return "OTA transfer failed";
}
if (count < sizeof(buffer)) {
f_close(&file);
break;
}
}
destination->step = OTA_UPDATE_EOF;
extmodulePulsesData.pxx2.sendOtaUpdate(module, nullptr, done, nullptr);
if (!waitStep(OTA_UPDATE_END, 10)) {
return "OTA end failed";
}
return nullptr;
}
void Pxx2OtaUpdate::flashFirmware(const char * filename)
{
pausePulses();
watchdogSuspend(100);
RTOS_WAIT_MS(100);
moduleState[module].mode = MODULE_MODE_OTA_UPDATE;
const char * result = doFlashFirmware(filename);
moduleState[module].mode = MODULE_MODE_NORMAL;
AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1 );
BACKLIGHT_ENABLE();
if (result) {
POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR);
SET_WARNING_INFO(result, strlen(result), 0);
}
else {
POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS);
}
watchdogSuspend(100);
RTOS_WAIT_MS(100);
resumePulses();
}

View file

@ -41,6 +41,7 @@
#define PXX2_TYPE_ID_SPECTRUM 0x02
#define PXX2_TYPE_C_OTA 0xFE
#define PXX2_TYPE_ID_OTA 0x02
#define PXX2_CHANNELS_FLAG0_FAILSAFE (1 << 6)
#define PXX2_CHANNELS_FLAG0_RANGECHECK (1 << 7)
@ -130,6 +131,15 @@ enum PXX2BindSteps {
BIND_OK
};
enum PXX2OtaUpdateSteps {
OTA_UPDATE_START = BIND_OK + 1,
OTA_UPDATE_START_ACK,
OTA_UPDATE_TRANSFER,
OTA_UPDATE_TRANSFER_ACK,
OTA_UPDATE_EOF,
OTA_UPDATE_END
};
enum PXX2ReceiverStatus {
PXX2_HARDWARE_INFO,
PXX2_SETTINGS_READ,
@ -178,6 +188,8 @@ class Pxx2Transport: public DataBuffer<uint8_t, 64>, public Pxx2CrcMixin {
};
class Pxx2Pulses: public Pxx2Transport {
friend class Pxx2OtaUpdate;
public:
void setupFrame(uint8_t module);
@ -204,6 +216,8 @@ class Pxx2Pulses: public Pxx2Transport {
void setupPowerMeter(uint8_t module);
void sendOtaUpdate(uint8_t module, const char * rxName, uint32_t address, const char * data);
void addHead()
{
// send 7E, do not CRC
@ -265,4 +279,22 @@ class Pxx2Pulses: public Pxx2Transport {
}
};
class Pxx2OtaUpdate {
public:
Pxx2OtaUpdate(uint8_t module, const char * rxName):
module(module),
rxName(rxName)
{
}
void flashFirmware(const char * filename);
protected:
uint8_t module;
const char * rxName;
const char * doFlashFirmware(const char * filename);
bool waitStep(uint8_t step, uint8_t timeout);
};
#endif

View file

@ -239,6 +239,32 @@ void processPowerMeterFrame(uint8_t module, uint8_t * frame)
}
}
void processOtaUpdateFrame(uint8_t module, uint8_t * frame)
{
if (moduleState[module].mode != MODULE_MODE_OTA_UPDATE) {
return;
}
OtaUpdateInformation * destination = moduleState[module].otaUpdateInformation;
if (destination->step == OTA_UPDATE_START) {
if (frame[3] == 0x00 && memcmp(&destination->candidateReceiversNames[destination->selectedReceiverIndex], &frame[4], PXX2_LEN_RX_NAME) == 0) {
destination->step = OTA_UPDATE_START_ACK;
}
}
else if (destination->step == OTA_UPDATE_TRANSFER) {
uint32_t address = *((uint32_t *)&frame[4]);
if (frame[3] == 0x01 && destination->address == address) {
destination->step = OTA_UPDATE_TRANSFER_ACK;
}
}
else if (destination->step == OTA_UPDATE_EOF) {
if (frame[3] == 0x02) {
destination->step = OTA_UPDATE_END;
}
}
}
void processModuleFrame(uint8_t module, uint8_t *frame)
{
switch (frame[2]) {
@ -296,6 +322,10 @@ void processPXX2Frame(uint8_t module, uint8_t *frame)
processToolsFrame(module, frame);
break;
case PXX2_TYPE_C_OTA:
processOtaUpdateFrame(module, frame);
break;
default:
break;
}