Skip to content

Commit 0a0f28f

Browse files
authored
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
1 parent 57b3397 commit 0a0f28f

5 files changed

Lines changed: 52 additions & 17 deletions

File tree

src/components/ble/DfuService.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,14 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
266266
static_cast<uint8_t>(ErrorCodes::NoError)};
267267
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
268268
} else {
269-
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
270269
NRF_LOG_INFO("Image Error : bad CRC");
271270

272271
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
273272
static_cast<uint8_t>(Opcodes::ValidateFirmware),
274273
static_cast<uint8_t>(ErrorCodes::CrcError)};
275274
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
275+
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
276+
Reset();
276277
}
277278

278279
return 0;
@@ -283,17 +284,16 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
283284
return 0;
284285
}
285286
NRF_LOG_INFO("[DFU] -> Activate image and reset!");
286-
bleController.StopFirmwareUpdate();
287-
systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
288-
Reset();
289287
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
288+
Reset();
290289
return 0;
291290
default:
292291
return 0;
293292
}
294293
}
295294

296295
void DfuService::OnTimeout() {
296+
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
297297
Reset();
298298
}
299299

@@ -307,7 +307,6 @@ void DfuService::Reset() {
307307
applicationSize = 0;
308308
expectedCrc = 0;
309309
notificationManager.Reset();
310-
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
311310
bleController.StopFirmwareUpdate();
312311
systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
313312
}

src/displayapp/DisplayApp.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,13 @@ void DisplayApp::Refresh() {
177177
}
178178
break;
179179
case Messages::TouchEvent: {
180-
if (state != States::Running)
180+
if (state != States::Running) {
181181
break;
182+
}
182183
auto gesture = OnTouchEvent();
184+
if (gesture == TouchEvents::None) {
185+
break;
186+
}
183187
if (!currentScreen->OnTouchEvent(gesture)) {
184188
if (currentApp == Apps::Clock) {
185189
switch (gesture) {
@@ -286,6 +290,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
286290
break;
287291
case Apps::FirmwareUpdate:
288292
currentScreen = std::make_unique<Screens::FirmwareUpdate>(this, bleController);
293+
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
289294
break;
290295

291296
case Apps::Notifications:

src/displayapp/screens/FirmwareUpdate.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ FirmwareUpdate::FirmwareUpdate(Pinetime::Applications::DisplayApp* app, Pinetime
2727
lv_bar_set_value(bar1, 0, LV_ANIM_OFF);
2828

2929
percentLabel = lv_label_create(lv_scr_act(), nullptr);
30-
lv_label_set_text(percentLabel, "");
30+
lv_label_set_text(percentLabel, "Waiting...");
3131
lv_obj_set_auto_realign(percentLabel, true);
3232
lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60);
33+
startTime = xTaskGetTickCount();
3334
}
3435

3536
FirmwareUpdate::~FirmwareUpdate() {
@@ -40,34 +41,49 @@ bool FirmwareUpdate::Refresh() {
4041
switch (bleController.State()) {
4142
default:
4243
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Idle:
44+
// This condition makes sure that the app is exited if somehow it got
45+
// launched without a firmware update. This should never happen.
46+
if (state != States::Error) {
47+
if (xTaskGetTickCount() - startTime > (60 * 1024)) {
48+
UpdateError();
49+
state = States::Error;
50+
}
51+
} else if (xTaskGetTickCount() - startTime > (5 * 1024)) {
52+
running = false;
53+
}
54+
break;
4355
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Running:
4456
if (state != States::Running)
4557
state = States::Running;
46-
return DisplayProgression();
58+
DisplayProgression();
59+
break;
4760
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated:
4861
if (state != States::Validated) {
4962
UpdateValidated();
5063
state = States::Validated;
5164
}
52-
return running;
65+
break;
5366
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Error:
5467
if (state != States::Error) {
5568
UpdateError();
5669
state = States::Error;
5770
}
58-
return running;
71+
if (xTaskGetTickCount() - startTime > (5 * 1024)) {
72+
running = false;
73+
}
74+
break;
5975
}
76+
return running;
6077
}
6178

62-
bool FirmwareUpdate::DisplayProgression() const {
79+
void FirmwareUpdate::DisplayProgression() const {
6380
float current = bleController.FirmwareUpdateCurrentBytes() / 1024.0f;
6481
float total = bleController.FirmwareUpdateTotalBytes() / 1024.0f;
6582
int16_t pc = (current / total) * 100.0f;
6683
sprintf(percentStr, "%d %%", pc);
6784
lv_label_set_text(percentLabel, percentStr);
6885

6986
lv_bar_set_value(bar1, pc, LV_ANIM_OFF);
70-
return running;
7187
}
7288

7389
void FirmwareUpdate::UpdateValidated() {
@@ -78,4 +94,9 @@ void FirmwareUpdate::UpdateValidated() {
7894
void FirmwareUpdate::UpdateError() {
7995
lv_label_set_recolor(percentLabel, true);
8096
lv_label_set_text(percentLabel, "#ff0000 Error!#");
97+
startTime = xTaskGetTickCount();
98+
}
99+
100+
bool FirmwareUpdate::OnButtonPushed() {
101+
return true;
81102
}

src/displayapp/screens/FirmwareUpdate.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Screen.h"
44
#include <lvgl/src/lv_core/lv_obj.h>
5+
#include "FreeRTOS.h"
56

67
namespace Pinetime {
78
namespace Controllers {
@@ -25,13 +26,17 @@ namespace Pinetime {
2526
lv_obj_t* titleLabel;
2627
mutable char percentStr[10];
2728

28-
States state;
29+
States state = States::Idle;
2930

30-
bool DisplayProgression() const;
31+
void DisplayProgression() const;
32+
33+
bool OnButtonPushed() override;
3134

3235
void UpdateValidated();
3336

3437
void UpdateError();
38+
39+
TickType_t startTime;
3540
};
3641
}
3742
}

src/systemtask/SystemTask.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,11 @@ void SystemTask::Work() {
198198
Messages message = static_cast<Messages>(msg);
199199
switch (message) {
200200
case Messages::EnableSleeping:
201-
doNotGoToSleep = false;
201+
// Make sure that exiting an app doesn't enable sleeping,
202+
// if the exiting was caused by a firmware update
203+
if (!bleController.IsFirmwareUpdating()) {
204+
doNotGoToSleep = false;
205+
}
202206
break;
203207
case Messages::DisableSleeping:
204208
doNotGoToSleep = true;
@@ -275,10 +279,11 @@ void SystemTask::Work() {
275279
displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
276280
break;
277281
case Messages::BleFirmwareUpdateFinished:
282+
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) {
283+
NVIC_SystemReset();
284+
}
278285
doNotGoToSleep = false;
279286
xTimerStart(idleTimer, 0);
280-
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated)
281-
NVIC_SystemReset();
282287
break;
283288
case Messages::OnTouchEvent:
284289
ReloadIdleTimer();

0 commit comments

Comments
 (0)