Skip to content

Commit 89d39b8

Browse files
committed
Implements background modem update checks, Cellular.updateStatus(), Cellular.enableUpdates()
1 parent 672130c commit 89d39b8

File tree

14 files changed

+385
-252
lines changed

14 files changed

+385
-252
lines changed

hal/inc/cellular_hal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,16 @@ int cellular_start_ncp_firmware_update(bool update = false, void* reserved = NUL
272272
*/
273273
int cellular_get_ublox_firmware_version(uint32_t* version, void* reserved = NULL);
274274

275+
/**
276+
* Get modem firmware update status result
277+
*/
278+
int cellular_update_status(void* reserved = NULL);
279+
280+
/**
281+
* Enable modem firmware updates (blocking call, requires a pending update)
282+
*/
283+
int cellular_enable_updates(void* reserved = NULL);
284+
275285
#ifdef __cplusplus
276286
}
277287
#endif

hal/inc/hal_dynalib_cellular.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ DYNALIB_FN(BASE_CELL_IDX + 3, hal_cellular, cellular_powered, bool(void*))
9595
#endif // !HAL_PLATFORM_NCP
9696

9797
DYNALIB_FN(BASE_CELL_IDX1 + 0, hal_cellular, cellular_urcs, cellular_result_t(bool, void*))
98+
DYNALIB_FN(BASE_CELL_IDX1 + 1, hal_cellular, cellular_update_status, int(void*))
99+
DYNALIB_FN(BASE_CELL_IDX1 + 2, hal_cellular, cellular_enable_updates, int(void*))
98100

99101
DYNALIB_END(hal_cellular)
100102

hal/network/ncp/cellular/cellular_hal.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#include "cellular_enums_hal.h"
3636
#include "cellular_ncp_dev_mapping.h"
3737

38+
#include "ncp_fw_update.h"
39+
3840
#include <limits>
3941

4042
namespace {
@@ -618,4 +620,18 @@ int cellular_get_ublox_firmware_version(uint32_t* version, void* reserved) {
618620
return SYSTEM_ERROR_NONE;
619621
}
620622

623+
int cellular_update_status(void* reserved) {
624+
#if HAL_PLATFORM_NCP_FW_UPDATE
625+
return services::NcpFwUpdate::instance()->updateStatus();
626+
#else
627+
return false;
628+
#endif
629+
}
621630

631+
int cellular_enable_updates(void* reserved) {
632+
#if HAL_PLATFORM_NCP_FW_UPDATE
633+
return services::NcpFwUpdate::instance()->enableUpdates();
634+
#else
635+
return SYSTEM_ERROR_NOT_SUPPORTED;
636+
#endif
637+
}

hal/network/ncp_client/sara/sara_ncp_client.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ LOG_SOURCE_CATEGORY("ncp.client");
4646
#include <lwip/memp.h>
4747
#include "enumclass.h"
4848

49+
#include "ncp_fw_update.h"
50+
4951
#undef LOG_COMPILE_TIME_LEVEL
5052
#define LOG_COMPILE_TIME_LEVEL LOG_LEVEL_ALL
5153

@@ -1501,7 +1503,6 @@ int SaraNcpClient::getUbloxFirmwareVersion(uint32_t* version) {
15011503
char atResponse[64] = {};
15021504
auto resp = parser_.sendCommand("ATI9");
15031505
CHECK_PARSER(resp.readLine(atResponse, sizeof(atResponse)));
1504-
LOG(INFO, "atResponse:[%s]", atResponse);
15051506
if (::sscanf(atResponse, "%*[\r\nL0.0.00.00.]%d.%d%*[,A.]%d.%d", &major1, &minor1, &major2, &minor2) == 4) {
15061507
ver = major1 * 1000000 + minor1 * 10000 + major2 * 100 + minor2;
15071508
} else if (::sscanf(atResponse, "%*[\r\nL0.0.00.00.]%d.%d%8[^,]%*[,A.]%d.%d", &major1, &minor1, eng, &major2, &minor2) == 5) {
@@ -1524,11 +1525,16 @@ int SaraNcpClient::initReady(ModemState state) {
15241525
if (getUbloxFirmwareVersion(&fwVersion_) != SYSTEM_ERROR_NONE) {
15251526
fwVersion_ = 0;
15261527
}
1527-
CHECK_TRUE(fwVersion_ != 0, SYSTEM_ERROR_AT_RESPONSE_UNEXPECTED); // XXX: The modem may get into a bad state without knowing what version we are operating with
1528+
#if HAL_PLATFORM_NCP_FW_UPDATE
1529+
if (ncpId() == PLATFORM_NCP_SARA_R510) {
1530+
CHECK(services::NcpFwUpdate::instance()->checkUpdate(fwVersion_));
1531+
}
1532+
#endif
15281533

15291534
// L0.0.00.00.05.06,A.02.00 has a memory issue
15301535
R410MemoryIssuePresent_ = (ncpId() == PLATFORM_NCP_SARA_R410) ? (fwVersion_ == UBLOX_NCP_R4_APP_FW_VERSION_MEMORY_LEAK_ISSUE) : false;
1531-
R410OldFirmwarePresent_ = (ncpId() == PLATFORM_NCP_SARA_R410) ? (fwVersion_ < UBLOX_NCP_R4_APP_FW_VERSION_LATEST_02B_01) : false;
1536+
R410OldFirmwarePresent_ = (ncpId() == PLATFORM_NCP_SARA_R410) ? (fwVersion_ >= UBLOX_NCP_R4_APP_FW_VERSION_MEMORY_LEAK_ISSUE &&
1537+
fwVersion_ < UBLOX_NCP_R4_APP_FW_VERSION_LATEST_02B_01) : false;
15321538
// Select either internal or external SIM card slot depending on the configuration
15331539
CHECK(selectSimCard(state));
15341540
// Make sure flow control is enabled as well

hal/src/electron/cellular_hal.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,4 +458,12 @@ int cellular_start_ncp_firmware_update(bool update, void* reserved) {
458458
return SYSTEM_ERROR_NOT_SUPPORTED;
459459
}
460460

461+
int cellular_update_status(void* reserved) {
462+
return SYSTEM_ERROR_NOT_SUPPORTED;
463+
}
464+
465+
int cellular_enable_updates(void* reserved) {
466+
return SYSTEM_ERROR_NOT_SUPPORTED;
467+
}
468+
461469
#endif // !defined(HAL_CELLULAR_EXCLUDE)

hal/src/stm32f2xx/core_hal_stm32f2xx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,10 +1220,10 @@ int HAL_Feature_Set(HAL_Feature feature, bool enabled)
12201220
return Write_Feature_Flag(FEATURE_FLAG_LED_OVERRIDDEN, !enabled, NULL);
12211221
}
12221222
#if HAL_PLATFORM_INTERNAL_LOW_SPEED_CLOCK
1223-
case FEATURE_DISABLE_EXTERNAL_LOW_SPEED_CLOCK: {
1223+
case FEATURE_DISABLE_EXTERNAL_LOW_SPEED_CLOCK: {
12241224
uint32_t value = enabled ? DCT_EXT_LOW_SPEED_CLOCK_DISABLE_SET : DCT_EXT_LOW_SPEED_CLOCK_DISABLE_CLEAR;
12251225
return dct_write_app_data(&value, DCT_EXT_LOW_SPEED_CLOCK_DISABLE_OFFSET, sizeof(value));
1226-
}
1226+
}
12271227
#endif // HAL_PLATFORM_INTERNAL_LOW_SPEED_CLOCK
12281228
}
12291229
return -1;

services/inc/ncp_fw_update.h

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -61,51 +61,58 @@ namespace particle {
6161
namespace services {
6262

6363
const system_tick_t NCP_FW_MODEM_POWER_ON_TIMEOUT = 60000;
64+
const system_tick_t NCP_FW_MODEM_INSTALL_ATOK_INTERVAL = 10000;
6465
const system_tick_t NCP_FW_MODEM_INSTALL_START_TIMEOUT = 5 * 60000;
6566
const system_tick_t NCP_FW_MODEM_INSTALL_FINISH_TIMEOUT = 30 * 60000;
6667
const system_tick_t NCP_FW_MODEM_CLOUD_CONNECT_TIMEOUT = 5 * 60000;
67-
const uint32_t NCP_FW_UBLOX_R510_ENG_VERSION = 100000000;
68+
const system_tick_t NCP_FW_MODEM_CLOUD_DISCONNECT_TIMEOUT = 1 * 60000;
69+
const system_tick_t NCP_FW_MODEM_CELLULAR_CONNECT_TIMEOUT = 10 * 60000;
70+
const int NCP_FW_UBLOX_DEFAULT_CID = 1;
6871
const int NCP_FW_UUFWINSTALL_COMPLETE = 128;
6972

7073
enum NcpFwUpdateState {
7174
FW_UPDATE_IDLE_STATE = 0,
7275
FW_UPDATE_QUALIFY_FLAGS_STATE = 1,
73-
FW_UPDATE_QUALIFY_MODEM_ON_STATE = 2,
74-
FW_UPDATE_QUALIFY_RETRY_STATE = 3,
75-
FW_UPDATE_SETUP_CLOUD_CONNECT_STATE = 4,
76-
FW_UPDATE_SETUP_CLOUD_CONNECTING_STATE = 5,
77-
FW_UPDATE_SETUP_CLOUD_CONNECTED_STATE = 6,
78-
FW_UPDATE_DOWNLOAD_CLOUD_DISCONNECT_STATE = 7,
79-
FW_UPDATE_DOWNLOAD_CELL_DISCONNECTING_STATE = 8,
80-
FW_UPDATE_DOWNLOAD_CELL_CONNECTING_STATE = 9,
81-
FW_UPDATE_DOWNLOAD_HTTPS_SETUP_STATE = 10,
82-
FW_UPDATE_DOWNLOAD_READY_STATE = 11,
83-
FW_UPDATE_INSTALL_CELL_DISCONNECTING_STATE = 12,
84-
FW_UPDATE_INSTALL_CELL_DISCONNECTED_STATE = 13,
85-
FW_UPDATE_INSTALL_STATE_STARTING = 14,
86-
FW_UPDATE_INSTALL_STATE_WAITING = 15,
87-
FW_UPDATE_FINISHED_POWER_OFF_STATE = 16,
88-
FW_UPDATE_FINISHED_POWERING_OFF_STATE = 17,
89-
FW_UPDATE_FINISHED_CLOUD_CONNECTING_STATE = 18,
90-
FW_UPDATE_FINISHED_CLOUD_CONNECTED_STATE = 19,
91-
FW_UPDATE_FINISHED_IDLE_STATE = 20,
76+
FW_UPDATE_SETUP_CLOUD_CONNECT_STATE = 2,
77+
FW_UPDATE_SETUP_CLOUD_CONNECTING_STATE = 3,
78+
FW_UPDATE_SETUP_CLOUD_CONNECTED_STATE = 4,
79+
FW_UPDATE_DOWNLOAD_CLOUD_DISCONNECT_STATE = 5,
80+
FW_UPDATE_DOWNLOAD_CELL_DISCONNECTING_STATE = 6,
81+
FW_UPDATE_DOWNLOAD_CELL_CONNECTING_STATE = 7,
82+
FW_UPDATE_DOWNLOAD_HTTPS_SETUP_STATE = 8,
83+
FW_UPDATE_DOWNLOAD_READY_STATE = 9,
84+
FW_UPDATE_INSTALL_CELL_DISCONNECTING_STATE = 10,
85+
FW_UPDATE_INSTALL_STATE_STARTING = 11,
86+
FW_UPDATE_INSTALL_STATE_WAITING = 12,
87+
FW_UPDATE_FINISHED_POWER_OFF_STATE = 13,
88+
FW_UPDATE_FINISHED_POWERING_OFF_STATE = 14,
89+
FW_UPDATE_FINISHED_CLOUD_CONNECTING_STATE = 15,
90+
FW_UPDATE_FINISHED_CLOUD_CONNECTED_STATE = 16,
91+
FW_UPDATE_FINISHED_IDLE_STATE = 17,
9292
};
9393

9494
enum NcpFwUpdateStatus {
95-
FW_UPDATE_IDLE_STATUS = 0,
96-
FW_UPDATE_DOWNLOADING_STATUS = 1,
97-
FW_UPDATE_UPDATING_STATUS = 2,
98-
FW_UPDATE_SUCCESS_STATUS = 3,
99-
FW_UPDATE_NONE_STATUS = -1, // for diagnostics
100-
FW_UPDATE_FAILED_STATUS = -2,
101-
FW_UPDATE_FAILED_DOWNLOAD_RETRY_MAX_STATUS = -3,
102-
FW_UPDATE_FAILED_START_INSTALL_TIMEOUT_STATUS = -4,
103-
FW_UPDATE_FAILED_INSTALL_AT_ERROR_STATUS = -5,
104-
FW_UPDATE_FAILED_SAME_VERSION_STATUS = -6,
105-
FW_UPDATE_FAILED_INSTALL_TIMEOUT_STATUS = -7,
106-
FW_UPDATE_FAILED_POWER_OFF_TIMEOUT_STATUS = -8,
107-
FW_UPDATE_FAILED_CLOUD_CONNECT_TIMEOUT_STATUS = -9,
108-
FW_UPDATE_FAILED_PUBLISH_RESULT_STATUS = -10,
95+
FW_UPDATE_IDLE_STATUS = 0,
96+
FW_UPDATE_DOWNLOADING_STATUS = 1,
97+
FW_UPDATE_UPDATING_STATUS = 2,
98+
FW_UPDATE_SUCCESS_STATUS = 3,
99+
FW_UPDATE_NONE_STATUS = -1, // for diagnostics
100+
FW_UPDATE_FAILED_STATUS = -2,
101+
FW_UPDATE_FAILED_QUALIFY_FLAGS_STATUS = -3,
102+
FW_UPDATE_FAILED_CLOUD_CONNECT_ON_ENTRY_TIMEOUT_STATUS = -4,
103+
FW_UPDATE_FAILED_PUBLISH_START_STATUS = -5,
104+
FW_UPDATE_FAILED_SETUP_CELLULAR_DISCONNECT_TIMEOUT_STATUS = -6,
105+
FW_UPDATE_FAILED_CELLULAR_CONNECT_TIMEOUT_STATUS = -7,
106+
FW_UPDATE_FAILED_HTTPS_SETUP_STATUS = -8,
107+
FW_UPDATE_FAILED_DOWNLOAD_RETRY_MAX_STATUS = -9,
108+
FW_UPDATE_FAILED_INSTALL_CELLULAR_DISCONNECT_TIMEOUT_STATUS = -10,
109+
FW_UPDATE_FAILED_START_INSTALL_TIMEOUT_STATUS = -11,
110+
FW_UPDATE_FAILED_INSTALL_AT_ERROR_STATUS = -12,
111+
FW_UPDATE_FAILED_SAME_VERSION_STATUS = -13,
112+
FW_UPDATE_FAILED_INSTALL_TIMEOUT_STATUS = -14,
113+
FW_UPDATE_FAILED_POWER_OFF_TIMEOUT_STATUS = -15,
114+
FW_UPDATE_FAILED_CLOUD_CONNECT_ON_EXIT_TIMEOUT_STATUS = -16,
115+
FW_UPDATE_FAILED_PUBLISH_RESULT_STATUS = -17,
109116
};
110117

111118
struct HTTPSresponse {
@@ -126,12 +133,13 @@ struct NcpFwUpdateData {
126133
int firmwareVersion; // 0;
127134
int startingFirmwareVersion; // 0;
128135
int updateVersion; // 0;
136+
uint8_t updateAvailable; // SYSTEM_NCP_FW_UPDATE_STATUS_UNKNOWN;
129137
uint8_t isUserConfig; // 0;
130138
NcpFwUpdateConfig userConfigData; // 0;
131139
uint32_t footer; // NCP_FW_DATA_FOOTER;
132140
};
133141

134-
/**
142+
/**
135143
* struct NcpFwUpdateConfig {
136144
* const uint32_t start_version;
137145
* const uint32_t end_version;
@@ -155,28 +163,31 @@ class NcpFwUpdate {
155163
*/
156164
static NcpFwUpdate* instance();
157165

158-
NcpFwUpdate();
159-
~NcpFwUpdate();
160-
161-
int checkUpdate(const NcpFwUpdateConfig* userConfigData);
162166
void init(NcpFwUpdateCallbacks* callbacks);
163167
int process();
164168
int getStatusDiagnostics();
169+
int setConfig(const NcpFwUpdateConfig* userConfigData = nullptr);
170+
int checkUpdate(uint32_t version = 0);
171+
int enableUpdates();
172+
int updateStatus();
165173

166174
private:
175+
NcpFwUpdate();
176+
~NcpFwUpdate();
167177

168178
NcpFwUpdateState ncpFwUpdateState_;
169179
NcpFwUpdateStatus ncpFwUpdateStatus_;
170180
NcpFwUpdateStatus ncpFwUpdateStatusDiagnostics_;
171181
int foatReady_;
172-
system_tick_t startInstallTimer_;
182+
system_tick_t startTimer_;
173183
system_tick_t atOkCheckTimer_;
174184
int lastRespCode_;
175185
int atResp_;
176186
int atResponsive_;
177187
int startingFirmwareVersion_;
178188
int firmwareVersion_;
179189
int updateVersion_;
190+
int updateAvailable_;
180191
bool isUserConfig_;
181192
system_tick_t cooldownTimer_;
182193
system_tick_t cooldownTimeout_;
@@ -198,6 +209,7 @@ class NcpFwUpdate {
198209
static int cbUPSND_(int type, const char* buf, int len, int* data);
199210
static int cbCOPS_(int type, const char* buf, int len, int* data);
200211
static int httpRespCallback_(AtResponseReader* reader, const char* prefix, void* data);
212+
static int cgevCallback_(AtResponseReader* reader, const char* prefix, void* data);
201213
uint32_t getAppFirmwareVersion_();
202214
int setupHTTPSProperties_();
203215
void cooldown_(system_tick_t timer);

services/inc/ncp_fw_update_dynalib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extern "C" {
3333
#endif
3434

3535
#if !defined(PARTICLE_USER_MODULE) || defined(PARTICLE_USE_UNSTABLE_API)
36-
int ncp_fw_udpate_check(const NcpFwUpdateConfig* data, void* reserved);
36+
int ncp_fw_udpate_config(const NcpFwUpdateConfig* data, void* reserved);
3737
#endif // !defined(PARTICLE_USER_MODULE) || defined(PARTICLE_USE_UNSTABLE_API)
3838

3939
#ifdef __cplusplus

services/inc/services_dynalib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ DYNALIB_FN(BASE_IDX + 0, services, set_system_error_message, void(const char*, .
115115
DYNALIB_FN(BASE_IDX + 1, services, clear_system_error_message, void())
116116
DYNALIB_FN(BASE_IDX + 2, services, get_system_error_message, const char*(int))
117117
DYNALIB_FN(BASE_IDX + 3, services, jsmn_parse, int(jsmn_parser*, const char*, size_t, jsmntok_t*, unsigned int, void*))
118-
DYNALIB_FN(BASE_IDX + 4, services, ncp_fw_udpate_check, int(const NcpFwUpdateConfig*, void*))
118+
DYNALIB_FN(BASE_IDX + 4, services, ncp_fw_udpate_config, int(const NcpFwUpdateConfig*, void*))
119119

120120
DYNALIB_END(services)
121121

services/inc/system_defs.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,28 @@ typedef enum system_flag_t {
159159

160160
} system_flag_t;
161161

162+
/**
163+
* NCP Firmware Update Available Status for Cellular Wiring API Cellular.updateStatus()
164+
*/
165+
typedef enum {
166+
/**
167+
* The system will check locally for firmware updates when the modem is initialized.
168+
*/
169+
SYSTEM_NCP_FW_UPDATE_STATUS_UNKNOWN = 0,
170+
/**
171+
* No firmware update available.
172+
*/
173+
SYSTEM_NCP_FW_UPDATE_STATUS_NOT_AVAILABLE = 1,
174+
/**
175+
* A firmware update is available.
176+
*/
177+
SYSTEM_NCP_FW_UPDATE_STATUS_PENDING = 2,
178+
/**
179+
* A firmware update is in progress.
180+
*/
181+
SYSTEM_NCP_FW_UPDATE_STATUS_IN_PROGRESS = 3
182+
} NcpFwUpdateAvailableStatus;
183+
162184
#ifdef __cplusplus
163185

164186
#include "enumflags.h"

0 commit comments

Comments
 (0)