Make firmware updating more foolproof (#469)
* Make firmware updating more foolproof and fix bugs * No need to manually handle overflow * Make startTime TickType_t * Don't process TouchEvents::None * Fix sleep getting re-enabled issue more directly
This commit is contained in:
parent
57b3397078
commit
0a0f28fff4
5 changed files with 52 additions and 17 deletions
|
@ -266,13 +266,14 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
|
|||
static_cast<uint8_t>(ErrorCodes::NoError)};
|
||||
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
||||
} else {
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
NRF_LOG_INFO("Image Error : bad CRC");
|
||||
|
||||
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
|
||||
static_cast<uint8_t>(Opcodes::ValidateFirmware),
|
||||
static_cast<uint8_t>(ErrorCodes::CrcError)};
|
||||
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
Reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -283,10 +284,8 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
|
|||
return 0;
|
||||
}
|
||||
NRF_LOG_INFO("[DFU] -> Activate image and reset!");
|
||||
bleController.StopFirmwareUpdate();
|
||||
systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
|
||||
Reset();
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
|
||||
Reset();
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -294,6 +293,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
|
|||
}
|
||||
|
||||
void DfuService::OnTimeout() {
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,6 @@ void DfuService::Reset() {
|
|||
applicationSize = 0;
|
||||
expectedCrc = 0;
|
||||
notificationManager.Reset();
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
bleController.StopFirmwareUpdate();
|
||||
systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
|
||||
}
|
||||
|
|
|
@ -177,9 +177,13 @@ void DisplayApp::Refresh() {
|
|||
}
|
||||
break;
|
||||
case Messages::TouchEvent: {
|
||||
if (state != States::Running)
|
||||
if (state != States::Running) {
|
||||
break;
|
||||
}
|
||||
auto gesture = OnTouchEvent();
|
||||
if (gesture == TouchEvents::None) {
|
||||
break;
|
||||
}
|
||||
if (!currentScreen->OnTouchEvent(gesture)) {
|
||||
if (currentApp == Apps::Clock) {
|
||||
switch (gesture) {
|
||||
|
@ -286,6 +290,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
|||
break;
|
||||
case Apps::FirmwareUpdate:
|
||||
currentScreen = std::make_unique<Screens::FirmwareUpdate>(this, bleController);
|
||||
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
|
||||
break;
|
||||
|
||||
case Apps::Notifications:
|
||||
|
|
|
@ -27,9 +27,10 @@ FirmwareUpdate::FirmwareUpdate(Pinetime::Applications::DisplayApp* app, Pinetime
|
|||
lv_bar_set_value(bar1, 0, LV_ANIM_OFF);
|
||||
|
||||
percentLabel = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text(percentLabel, "");
|
||||
lv_label_set_text(percentLabel, "Waiting...");
|
||||
lv_obj_set_auto_realign(percentLabel, true);
|
||||
lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60);
|
||||
startTime = xTaskGetTickCount();
|
||||
}
|
||||
|
||||
FirmwareUpdate::~FirmwareUpdate() {
|
||||
|
@ -40,26 +41,42 @@ bool FirmwareUpdate::Refresh() {
|
|||
switch (bleController.State()) {
|
||||
default:
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Idle:
|
||||
// This condition makes sure that the app is exited if somehow it got
|
||||
// launched without a firmware update. This should never happen.
|
||||
if (state != States::Error) {
|
||||
if (xTaskGetTickCount() - startTime > (60 * 1024)) {
|
||||
UpdateError();
|
||||
state = States::Error;
|
||||
}
|
||||
} else if (xTaskGetTickCount() - startTime > (5 * 1024)) {
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Running:
|
||||
if (state != States::Running)
|
||||
state = States::Running;
|
||||
return DisplayProgression();
|
||||
DisplayProgression();
|
||||
break;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated:
|
||||
if (state != States::Validated) {
|
||||
UpdateValidated();
|
||||
state = States::Validated;
|
||||
}
|
||||
return running;
|
||||
break;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Error:
|
||||
if (state != States::Error) {
|
||||
UpdateError();
|
||||
state = States::Error;
|
||||
}
|
||||
if (xTaskGetTickCount() - startTime > (5 * 1024)) {
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::DisplayProgression() const {
|
||||
void FirmwareUpdate::DisplayProgression() const {
|
||||
float current = bleController.FirmwareUpdateCurrentBytes() / 1024.0f;
|
||||
float total = bleController.FirmwareUpdateTotalBytes() / 1024.0f;
|
||||
int16_t pc = (current / total) * 100.0f;
|
||||
|
@ -67,7 +84,6 @@ bool FirmwareUpdate::DisplayProgression() const {
|
|||
lv_label_set_text(percentLabel, percentStr);
|
||||
|
||||
lv_bar_set_value(bar1, pc, LV_ANIM_OFF);
|
||||
return running;
|
||||
}
|
||||
|
||||
void FirmwareUpdate::UpdateValidated() {
|
||||
|
@ -78,4 +94,9 @@ void FirmwareUpdate::UpdateValidated() {
|
|||
void FirmwareUpdate::UpdateError() {
|
||||
lv_label_set_recolor(percentLabel, true);
|
||||
lv_label_set_text(percentLabel, "#ff0000 Error!#");
|
||||
startTime = xTaskGetTickCount();
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::OnButtonPushed() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "Screen.h"
|
||||
#include <lvgl/src/lv_core/lv_obj.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
|
@ -25,13 +26,17 @@ namespace Pinetime {
|
|||
lv_obj_t* titleLabel;
|
||||
mutable char percentStr[10];
|
||||
|
||||
States state;
|
||||
States state = States::Idle;
|
||||
|
||||
bool DisplayProgression() const;
|
||||
void DisplayProgression() const;
|
||||
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
void UpdateValidated();
|
||||
|
||||
void UpdateError();
|
||||
|
||||
TickType_t startTime;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,7 +198,11 @@ void SystemTask::Work() {
|
|||
Messages message = static_cast<Messages>(msg);
|
||||
switch (message) {
|
||||
case Messages::EnableSleeping:
|
||||
// Make sure that exiting an app doesn't enable sleeping,
|
||||
// if the exiting was caused by a firmware update
|
||||
if (!bleController.IsFirmwareUpdating()) {
|
||||
doNotGoToSleep = false;
|
||||
}
|
||||
break;
|
||||
case Messages::DisableSleeping:
|
||||
doNotGoToSleep = true;
|
||||
|
@ -275,10 +279,11 @@ void SystemTask::Work() {
|
|||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
|
||||
break;
|
||||
case Messages::BleFirmwareUpdateFinished:
|
||||
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) {
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
doNotGoToSleep = false;
|
||||
xTimerStart(idleTimer, 0);
|
||||
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated)
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
case Messages::OnTouchEvent:
|
||||
ReloadIdleTimer();
|
||||
|
|
Loading…
Reference in a new issue