DFU : add timeout detection : abort dfu procedure after 10s without any data from the host.

This commit is contained in:
JF 2020-06-01 16:30:24 +02:00
parent b41a856b9d
commit 07f74cee63
7 changed files with 45 additions and 33 deletions

View file

@ -16,11 +16,16 @@ int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle,
return dfuService->OnServiceData(conn_handle, attr_handle, ctxt); return dfuService->OnServiceData(conn_handle, attr_handle, ctxt);
} }
void NotificationTimerCallback( TimerHandle_t xTimer ) { void NotificationTimerCallback(TimerHandle_t xTimer) {
auto dfuService = static_cast<DfuService *>(pvTimerGetTimerID( xTimer )); auto dfuService = static_cast<DfuService *>(pvTimerGetTimerID(xTimer));
dfuService->OnNotificationTimer(); dfuService->OnNotificationTimer();
} }
void TimeoutTimerCallback(TimerHandle_t xTimer) {
auto dfuService = static_cast<DfuService *>(pvTimerGetTimerID(xTimer));
dfuService->OnTimeout();
}
DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController, DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
Pinetime::Drivers::SpiNorFlash &spiNorFlash) : Pinetime::Drivers::SpiNorFlash &spiNorFlash) :
systemTask{systemTask}, systemTask{systemTask},
@ -66,6 +71,7 @@ DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Contr
}, },
} { } {
notificationTimer = xTimerCreate ("notificationTimer", 1000, pdFALSE, this, NotificationTimerCallback); notificationTimer = xTimerCreate ("notificationTimer", 1000, pdFALSE, this, NotificationTimerCallback);
timeoutTimer = xTimerCreate ("notificationTimer", 10000, pdFALSE, this, TimeoutTimerCallback);
} }
void DfuService::Init() { void DfuService::Init() {
@ -74,6 +80,10 @@ void DfuService::Init() {
} }
int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context) { int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context) {
if(bleController.IsFirmwareUpdating()){
xTimerStart(timeoutTimer, 0);
}
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &packetCharacteristicUuid, nullptr, ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &packetCharacteristicUuid, nullptr,
&packetCharacteristicHandle); &packetCharacteristicHandle);
@ -150,11 +160,6 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
nbPacketReceived++; nbPacketReceived++;
auto offset = ((nbPacketReceived - 1) % nbPacketsToNotify) * 20; auto offset = ((nbPacketReceived - 1) % nbPacketsToNotify) * 20;
std::memcpy(tempBuffer + offset, om->om_data, om->om_len); std::memcpy(tempBuffer + offset, om->om_data, om->om_len);
if (firstCrc) {
tempCrc = ComputeCrc(om->om_data, om->om_len, NULL);
firstCrc = false;
} else
tempCrc = ComputeCrc(om->om_data, om->om_len, &tempCrc);
if (nbPacketReceived > 0 && (nbPacketReceived % nbPacketsToNotify) == 0) { if (nbPacketReceived > 0 && (nbPacketReceived % nbPacketsToNotify) == 0) {
#if 1 #if 1
@ -190,7 +195,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
uint8_t data[3]{static_cast<uint8_t>(Opcodes::Response), uint8_t data[3]{static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage), static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage),
static_cast<uint8_t>(ErrorCodes::NoError)}; static_cast<uint8_t>(ErrorCodes::NoError)};
NRF_LOG_INFO("[DFU] -> Send packet notification : all bytes received! CRC = %u -- %d", tempCrc, connectionHandle); NRF_LOG_INFO("[DFU] -> Send packet notification : all bytes received!");
SendNotification(connectionHandle, data, 3); SendNotification(connectionHandle, data, 3);
state = States::Validate; state = States::Validate;
} }
@ -266,7 +271,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
return 0; return 0;
case Opcodes::ValidateFirmware: { case Opcodes::ValidateFirmware: {
if (state != States::Validate) { if (state != States::Validate) {
NRF_LOG_INFO("[DFU] -> Validate firmware image requested, but we are not in Data state"); NRF_LOG_INFO("[DFU] -> Validate firmware image requested, but we are not in Data state %d", state);
return 0; return 0;
} }
@ -301,6 +306,8 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
NRF_LOG_INFO("[DFU] -> Activate image and reset!"); NRF_LOG_INFO("[DFU] -> Activate image and reset!");
bleController.StopFirmwareUpdate(); bleController.StopFirmwareUpdate();
systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished); systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished);
Reset();
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
return 0; return 0;
default: default:
return 0; return 0;
@ -375,3 +382,24 @@ void DfuService::OnNotificationTimer() {
notificationSize = 0; notificationSize = 0;
} }
} }
void DfuService::OnTimeout() {
Reset();
}
void DfuService::Reset() {
state = States::Idle;
nbPacketsToNotify = 0;
nbPacketReceived = 0;
bytesReceived = 0;
softdeviceSize = 0;
bootloaderSize = 0;
applicationSize = 0;
expectedCrc = 0;
notificatonConnectionHandle = 0;
notificationSize = 0;
xTimerStop(notificationTimer, 0);
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
bleController.StopFirmwareUpdate();
systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished);
}

View file

@ -26,6 +26,9 @@ namespace Pinetime {
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context); int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
void OnNotificationTimer(); void OnNotificationTimer();
void OnTimeout();
void Reset();
private: private:
Pinetime::System::SystemTask &systemTask; Pinetime::System::SystemTask &systemTask;
@ -125,11 +128,9 @@ namespace Pinetime {
uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc); uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc);
bool firstCrc = true;
uint16_t tempCrc = 0;
void WriteMagicNumber(); void WriteMagicNumber();
TimerHandle_t notificationTimer; TimerHandle_t notificationTimer;
TimerHandle_t timeoutTimer;
uint16_t notificatonConnectionHandle = 0; uint16_t notificatonConnectionHandle = 0;
size_t notificationSize = 0; size_t notificationSize = 0;

View file

@ -163,12 +163,8 @@ void DisplayApp::Refresh() {
lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Down); lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Down);
currentScreen.reset(nullptr); currentScreen.reset(nullptr);
currentScreen.reset(new Screens::FirmwareUpdate(this, bleController)); currentScreen.reset(new Screens::FirmwareUpdate(this, bleController));
onClockApp = false;
break;
case Messages::BleFirmwareUpdateFinished:
lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::Down);
currentScreen.reset(nullptr);
currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController));
break; break;
} }
} }

View file

@ -26,15 +26,6 @@ FirmwareUpdate::FirmwareUpdate(Pinetime::Applications::DisplayApp *app, Pinetime
lv_label_set_text(percentLabel, ""); lv_label_set_text(percentLabel, "");
lv_obj_set_auto_realign(percentLabel, true); lv_obj_set_auto_realign(percentLabel, true);
lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60); lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60);
button = lv_btn_create(lv_scr_act(), NULL);
//lv_obj_set_event_cb(button, event_handler);
lv_obj_align(button, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
lv_obj_set_hidden(button, true);
labelBtn = lv_label_create(button, NULL);
lv_label_set_text(labelBtn, "Back");
lv_obj_set_hidden(labelBtn, true);
} }
FirmwareUpdate::~FirmwareUpdate() { FirmwareUpdate::~FirmwareUpdate() {
@ -88,7 +79,4 @@ void FirmwareUpdate::UpdateValidated() {
void FirmwareUpdate::UpdateError() { void FirmwareUpdate::UpdateError() {
lv_label_set_recolor(percentLabel, true); lv_label_set_recolor(percentLabel, true);
lv_label_set_text(percentLabel, "#ff0000 Error!#"); lv_label_set_text(percentLabel, "#ff0000 Error!#");
lv_obj_set_hidden(labelBtn, false);
lv_obj_set_hidden(button, false);
} }

View file

@ -31,8 +31,6 @@ namespace Pinetime {
lv_obj_t* bar1; lv_obj_t* bar1;
lv_obj_t* percentLabel; lv_obj_t* percentLabel;
lv_obj_t* titleLabel; lv_obj_t* titleLabel;
lv_obj_t* labelBtn;
lv_obj_t* button;
mutable char percentStr[10]; mutable char percentStr[10];
bool running = true; bool running = true;
States state; States state;

View file

@ -96,7 +96,7 @@
#define configUSE_TIMERS 1 #define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 0 ) #define configTIMER_TASK_PRIORITY ( 0 )
#define configTIMER_QUEUE_LENGTH 32 #define configTIMER_QUEUE_LENGTH 32
#define configTIMER_TASK_STACK_DEPTH ( 120 ) #define configTIMER_TASK_STACK_DEPTH ( 240 )
/* Tickless Idle configuration. */ /* Tickless Idle configuration. */
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2

View file

@ -118,6 +118,7 @@ void SystemTask::Work() {
break; break;
case Messages::BleFirmwareUpdateFinished: case Messages::BleFirmwareUpdateFinished:
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::BleFirmwareUpdateFinished); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::BleFirmwareUpdateFinished);
if(bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated)
NVIC_SystemReset(); NVIC_SystemReset();
break; break;
default: break; default: break;