Skip to content

Commit 3a0e91e

Browse files
sigvartmhcarlescufi
authored andcommitted
net: lib: Erase pending may cause the modem DFU operation to stall
Doing a modem DFU may cause the modem's erase operation to hang on `DFU_ERASE_PENDING` this is due to the modem being too busy to do the actual erase. Either reboot the device or turn of the LTE link until the erase operation is complete to mitigate this issue. Signed-off-by: Sigvart Hovland <[email protected]>
1 parent c3fe1be commit 3a0e91e

File tree

14 files changed

+146
-34
lines changed

14 files changed

+146
-34
lines changed

applications/asset_tracker/src/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,9 @@ void cloud_event_handler(const struct cloud_backend *const backend,
902902
break;
903903
case CLOUD_EVT_FOTA_DONE:
904904
LOG_INF("CLOUD_EVT_FOTA_DONE");
905+
#if defined(CONFIG_LTE_LINK_CONTROL)
906+
lte_lc_power_off();
907+
#endif
905908
sys_reboot(SYS_REBOOT_COLD);
906909
break;
907910
default:

include/dfu/dfu_target.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@ extern "C" {
2323
#define DFU_TARGET_IMAGE_TYPE_MCUBOOT 1
2424
#define DFU_TARGET_IMAGE_TYPE_MODEM_DELTA 2
2525

26+
enum dfu_target_evt_id {
27+
DFU_TARGET_EVT_TIMEOUT,
28+
DFU_TARGET_EVT_ERASE_DONE
29+
};
30+
31+
typedef void (*dfu_target_callback_t)(enum dfu_target_evt_id evt_id);
32+
2633
/** @brief Functions which needs to be supported by all DFU targets.
2734
*/
2835
struct dfu_target {
29-
int (*init)(size_t file_size);
36+
int (*init)(size_t file_size, dfu_target_callback_t cb);
3037
int (*offset_get)(size_t *offset);
3138
int (*write)(const void *const buf, size_t len);
3239
int (*done)(bool successful);
@@ -58,12 +65,14 @@ int dfu_target_img_type(const void *const buf, size_t len);
5865
*
5966
* @param[in] img_type Image type identifier.
6067
* @param[in] file_size Size of the current file being downloaded.
68+
* @param[in] cb Callback function in case the DFU operation requires additional
69+
* proceedures to be called.
6170
*
6271
* @return 0 for a supported image type or a negative error
6372
* code identicating reason of failure.
6473
*
6574
**/
66-
int dfu_target_init(int img_type, size_t file_size);
75+
int dfu_target_init(int img_type, size_t file_size, dfu_target_callback_t cb);
6776

6877
/**
6978
* @brief Get offset of the firmware upgrade

include/net/aws_fota.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ enum aws_fota_evt_id {
2525
/** AWS FOTA complete and status reported to job document */
2626
AWS_FOTA_EVT_DONE,
2727
/** AWS FOTA error */
28-
AWS_FOTA_EVT_ERROR
28+
AWS_FOTA_EVT_ERROR,
29+
/** AWS FOTA Erase pending*/
30+
AWS_FOTA_EVT_ERASE_PENDING,
31+
/** AWS FOTA Erase done*/
32+
AWS_FOTA_EVT_ERASE_DONE
2933
};
3034

3135
typedef void (*aws_fota_callback_t)(enum aws_fota_evt_id evt_id);

include/net/fota_download.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ enum fota_download_evt_id {
3434
FOTA_DOWNLOAD_EVT_PROGRESS,
3535
/** FOTA download finished. */
3636
FOTA_DOWNLOAD_EVT_FINISHED,
37+
/** FOTA download erase pending. */
38+
FOTA_DOWNLOAD_EVT_ERASE_PENDING,
39+
/** FOTA download erase done. */
40+
FOTA_DOWNLOAD_EVT_ERASE_DONE,
3741
/** FOTA download error. */
3842
FOTA_DOWNLOAD_EVT_ERROR,
3943
};

samples/nrf9160/aws_fota/src/main.c

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include <dfu/mcuboot.h>
1818
#include <power/reboot.h>
1919

20+
BUILD_ASSERT_MSG(!IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT),
21+
"This sample does not support auto init and connect");
22+
2023
#if defined(CONFIG_USE_NRF_CLOUD)
2124
#define NRF_CLOUD_SECURITY_TAG 16842753
2225
#endif
@@ -434,36 +437,44 @@ static int fds_init(struct mqtt_client *c)
434437
return 0;
435438
}
436439

437-
/**@brief Configures modem to provide LTE link.
438-
*
439-
* Blocks until link is successfully established.
440-
*/
441-
static void modem_configure(void)
440+
/**@brief Configures AT Command interface to the modem link. */
441+
static void at_configure(void)
442442
{
443-
#if defined(CONFIG_LTE_LINK_CONTROL)
444-
BUILD_ASSERT_MSG(!IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT),
445-
"This sample does not support auto init and connect");
446443
int err;
447444

448445
err = at_notif_init();
449446
__ASSERT(err == 0, "AT Notify could not be initialized.");
450447
err = at_cmd_init();
451448
__ASSERT(err == 0, "AT CMD could not be established.");
452-
printk("LTE Link Connecting ...\n");
453-
err = lte_lc_init_and_connect();
454-
__ASSERT(err == 0, "LTE link could not be established.");
455-
printk("LTE Link Connected!\n");
456-
#endif
457449
}
458450

459451
static void aws_fota_cb_handler(enum aws_fota_evt_id evt)
460452
{
453+
int err;
454+
461455
switch (evt) {
462456
case AWS_FOTA_EVT_DONE:
463457
printk("AWS_FOTA_EVT_DONE, rebooting to apply update.\n");
464458
do_reboot = true;
465459
break;
466460

461+
case AWS_FOTA_EVT_ERASE_PENDING:
462+
printk("AWS_FOTA_EVT_ERASE_PENDING, reboot or disconnect the "
463+
"LTE link\n");
464+
err = lte_lc_offline();
465+
if (err) {
466+
printk("Error turning off the LTE link\n");
467+
}
468+
break;
469+
470+
case AWS_FOTA_EVT_ERASE_DONE:
471+
printk("AWS_FOTA_EVT_ERASE_DONE, reconnecting the LTE link\n");
472+
err = lte_lc_connect();
473+
if (err) {
474+
printk("Error reconnecting the LTE link\n");
475+
}
476+
break;
477+
467478
case AWS_FOTA_EVT_ERROR:
468479
printk("AWS_FOTA_EVT_ERROR\n");
469480
break;
@@ -505,10 +516,14 @@ void main(void)
505516
}
506517
printk("Initialized bsdlib\n");
507518

519+
at_configure();
508520
#if defined(CONFIG_PROVISION_CERTIFICATES)
509521
provision_certificates();
510522
#endif /* CONFIG_PROVISION_CERTIFICATES */
511-
modem_configure();
523+
printk("LTE Link Connecting ...\n");
524+
err = lte_lc_init_and_connect();
525+
__ASSERT(err == 0, "LTE link could not be established.");
526+
printk("LTE Link Connected!\n");
512527

513528
client_init(&client, CONFIG_MQTT_BROKER_HOSTNAME);
514529

subsys/dfu/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ config DFU_TARGET_MODEM
3838
help
3939
Enable support for updates to the modem firmware.
4040

41+
if (DFU_TARGET_MODEM)
42+
43+
config DFU_TARGET_MODEM_TIMEOUT
44+
int "Erase pending timeout"
45+
default 60
46+
help
47+
Set the timeout in seconds for how long the code will wait when
48+
reading DFU_ERASE_PENDING from the modem. If the timeout is reached
49+
an DFU_TARGET_EVT_TIMEOUT is issued and a disconnect of the LTE link
50+
is recommended so that the modem has time to service the
51+
DFU_ERASE_PENDING request. It's also possible to reboot the device to
52+
achive the same desired behavior.
53+
54+
55+
endif # DFU_TARGET_MODEM
56+
4157
module=DFU_TARGET
4258
module-dep=LOG
4359
module-str=Device Firmware Upgrade

subsys/dfu/include/dfu_target_mcuboot.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@ bool dfu_target_mcuboot_identify(const void *const buf);
5252
* @brief Initialize dfu target, perform steps necessary to receive firmware.
5353
*
5454
* @param[in] file_size Size of the current file being downloaded.
55+
* @param[in] cb Callback for signaling events(unused).
5556
*
5657
* @retval 0 If successful, negative errno otherwise.
5758
*/
58-
int dfu_target_mcuboot_init(size_t file_size);
59+
int dfu_target_mcuboot_init(size_t file_size, dfu_target_callback_t cb);
5960

6061
/**
6162
* @brief Get offset of firmware

subsys/dfu/include/dfu_target_modem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ bool dfu_target_modem_identify(const void *const buf);
3131
* @brief Initialize dfu target, perform steps necessary to receive firmware.
3232
*
3333
* @param[in] file_size Size of the current file being downloaded.
34+
* @param[in] callback Callback function for signaling if the modem is not able
35+
* to service the erase request.
3436
*
3537
* @retval 0 If successful, negative errno otherwise.
3638
*/
37-
int dfu_target_modem_init(size_t file_size);
39+
int dfu_target_modem_init(size_t file_size, dfu_target_callback_t callback);
3840

3941
/**
4042
* @brief Get offset of firmware

subsys/dfu/src/dfu_target.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int dfu_target_img_type(const void *const buf, size_t len)
5454
return -ENOTSUP;
5555
}
5656

57-
int dfu_target_init(int img_type, size_t file_size)
57+
int dfu_target_init(int img_type, size_t file_size, dfu_target_callback_t cb)
5858
{
5959
const struct dfu_target *new_target = NULL;
6060

@@ -83,7 +83,7 @@ int dfu_target_init(int img_type, size_t file_size)
8383

8484
current_target = new_target;
8585

86-
return current_target->init(file_size);
86+
return current_target->init(file_size, cb);
8787
}
8888

8989
int dfu_target_offset_get(size_t *offset)
@@ -124,4 +124,3 @@ int dfu_target_done(bool successful)
124124

125125
return 0;
126126
}
127-

subsys/dfu/src/dfu_target_mcuboot.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <pm_config.h>
2222
#include <logging/log.h>
2323
#include <dfu/mcuboot.h>
24+
#include <dfu/dfu_target.h>
2425
#include <dfu/flash_img.h>
2526
#include <settings/settings.h>
2627

@@ -31,7 +32,8 @@ LOG_MODULE_REGISTER(dfu_target_mcuboot, CONFIG_DFU_TARGET_LOG_LEVEL);
3132

3233
static struct flash_img_context flash_img;
3334

34-
int dfu_ctx_mcuboot_set_b1_file(const char *file, bool s0_active, const char **update)
35+
int dfu_ctx_mcuboot_set_b1_file(const char *file, bool s0_active,
36+
const char **update)
3537
{
3638
if (file == NULL || update == NULL) {
3739
return -EINVAL;
@@ -112,8 +114,9 @@ bool dfu_target_mcuboot_identify(const void *const buf)
112114
return *((const u32_t *)buf) == MCUBOOT_HEADER_MAGIC;
113115
}
114116

115-
int dfu_target_mcuboot_init(size_t file_size)
117+
int dfu_target_mcuboot_init(size_t file_size, dfu_target_callback_t cb)
116118
{
119+
ARG_UNUSED(cb);
117120
int err = flash_img_init(&flash_img);
118121

119122
if (err != 0) {
@@ -122,7 +125,8 @@ int dfu_target_mcuboot_init(size_t file_size)
122125
}
123126

124127
if (file_size > PM_MCUBOOT_SECONDARY_SIZE) {
125-
LOG_ERR("Requested file too big to fit in flash");
128+
LOG_ERR("Requested file too big to fit in flash %d > %d",
129+
file_size, PM_MCUBOOT_SECONDARY_SIZE);
126130
return -EFBIG;
127131
}
128132

0 commit comments

Comments
 (0)