DFU : add timeout detection : abort dfu procedure after 10s without any data from the host.
This commit is contained in:
parent
b41a856b9d
commit
07f74cee63
7 changed files with 45 additions and 33 deletions
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue