Skip to content

Commit c7b7f4e

Browse files
committed
modules: Update FOTA process
Include more states in app.c to differ between different FOTA scenarios. Signed-off-by: Simen S. Røstad <simen.rostad@nordicsemi.no>
1 parent 334d8f1 commit c7b7f4e

File tree

4 files changed

+96
-29
lines changed

4 files changed

+96
-29
lines changed

app/src/modules/app/app.c

+71-5
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ static void idle_run(void *o);
6262
static void fota_entry(void *o);
6363
static void fota_run(void *o);
6464

65+
static void fota_downloading_run(void *o);
66+
67+
static void fota_network_disconnect_and_reboot_entry(void *o);
68+
static void fota_network_disconnect_and_reboot_run(void *o);
69+
6570
static void fota_network_disconnect_pending_entry(void *o);
6671
static void fota_network_disconnect_pending_run(void *o);
6772

@@ -84,6 +89,8 @@ enum state {
8489
STATE_PERIODIC_TRIGGERING,
8590
STATE_IDLE,
8691
STATE_FOTA,
92+
STATE_FOTA_DOWNLOADING,
93+
STATE_FOTA_NETWORK_DISCONNECT_AND_REBOOT,
8794
STATE_FOTA_NETWORK_DISCONNECT_PENDING,
8895
STATE_FOTA_IMAGE_APPLY_PENDING,
8996
STATE_FOTA_REBOOTING,
@@ -148,6 +155,20 @@ static const struct smf_state states[] = {
148155
fota_run,
149156
NULL,
150157
NULL,
158+
&states[STATE_FOTA_DOWNLOADING]
159+
),
160+
[STATE_FOTA_DOWNLOADING] = SMF_CREATE_STATE(
161+
NULL,
162+
fota_downloading_run,
163+
NULL,
164+
&states[STATE_FOTA],
165+
NULL
166+
),
167+
[STATE_FOTA_NETWORK_DISCONNECT_AND_REBOOT] = SMF_CREATE_STATE(
168+
fota_network_disconnect_and_reboot_entry,
169+
fota_network_disconnect_and_reboot_run,
170+
NULL,
171+
&states[STATE_FOTA],
151172
NULL
152173
),
153174
[STATE_FOTA_NETWORK_DISCONNECT_PENDING] = SMF_CREATE_STATE(
@@ -400,11 +421,25 @@ static void fota_run(void *o)
400421
case FOTA_DOWNLOAD_FAILED:
401422
STATE_SET(app_state, STATE_RUNNING);
402423
return;
403-
case FOTA_NETWORK_DISCONNECT_NEEDED:
404-
STATE_SET(app_state, STATE_FOTA_NETWORK_DISCONNECT_PENDING);
405-
return;
424+
default:
425+
/* Don't care */
426+
break;
427+
}
428+
}
429+
}
430+
431+
/* STATE_FOTA_DOWNLOADING */
432+
static void fota_downloading_run(void *o)
433+
{
434+
const struct app_state_object *state_object = (const struct app_state_object *)o;
435+
436+
if (state_object->chan == &FOTA_CHAN) {
437+
switch (state_object->fota_status) {
406438
case FOTA_REBOOT_NEEDED:
407-
STATE_SET(app_state, STATE_FOTA_REBOOTING);
439+
STATE_SET(app_state, STATE_FOTA_NETWORK_DISCONNECT_AND_REBOOT);
440+
return;
441+
case FOTA_NETWORK_DISCONNECT_AND_APPLY_NEEDED:
442+
STATE_SET(app_state, STATE_FOTA_NETWORK_DISCONNECT_PENDING);
408443
return;
409444
default:
410445
/* Don't care */
@@ -413,6 +448,37 @@ static void fota_run(void *o)
413448
}
414449
}
415450

451+
/* STATE_FOTA_NETWORK_DISCONNECT_AND_REBOOT */
452+
453+
static void fota_network_disconnect_and_reboot_entry(void *o)
454+
{
455+
ARG_UNUSED(o);
456+
457+
LOG_DBG("%s", __func__);
458+
459+
int err;
460+
struct network_msg msg = {
461+
.type = NETWORK_DISCONNECT
462+
};
463+
464+
err = zbus_chan_pub(&NETWORK_CHAN, &msg, K_SECONDS(1));
465+
if (err) {
466+
LOG_ERR("zbus_chan_pub, error: %d", err);
467+
SEND_FATAL_ERROR();
468+
}
469+
}
470+
471+
static void fota_network_disconnect_and_reboot_run(void *o)
472+
{
473+
const struct app_state_object *state_object = (const struct app_state_object *)o;
474+
475+
if (state_object->chan == &NETWORK_CHAN &&
476+
state_object->network_status == NETWORK_DISCONNECTED) {
477+
STATE_SET(app_state, STATE_FOTA_REBOOTING);
478+
return;
479+
}
480+
}
481+
416482
/* STATE_FOTA_NETWORK_DISCONNECT_PENDING */
417483

418484
static void fota_network_disconnect_pending_entry(void *o)
@@ -453,7 +519,7 @@ static void fota_image_apply_pending_entry(void *o)
453519
LOG_DBG("%s", __func__);
454520

455521
int err;
456-
enum fota_msg_type msg = FOTA_APPLY_IMAGE;
522+
enum fota_msg_type msg = FOTA_IMAGE_APPLY;
457523

458524
err = zbus_chan_pub(&FOTA_CHAN, &msg, K_SECONDS(1));
459525
if (err) {

app/src/modules/fota/fota.c

+19-18
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ static void fota_status(enum nrf_cloud_fota_status status, const char *const sta
5050
/* State machine */
5151

5252
/* Defining modules states.
53-
* STATE_RUNNING: The FOTA module is initializing and waiting for a poll request.
54-
* STATE_WAITING_FOR_POLL_REQUEST: The FOTA module is waiting for a poll request.
55-
* STATE_POLLING_FOR_UPDATE: The FOTA module is polling for an update.
56-
* STATE_DOWNLOADING_UPDATE: The FOTA module is downloading an update.
57-
* STATE_WAITING_FOR_NETWORK_DISCONNECT: The FOTA module is waiting for a network disconnect
58-
* in order to apply the update.
53+
* STATE_RUNNING: The module is initializing and waiting for a poll request.
54+
* STATE_WAITING_FOR_POLL_REQUEST: The module is waiting for a poll request.
55+
* STATE_POLLING_FOR_UPDATE: The module is polling for an update.
56+
* STATE_DOWNLOADING_UPDATE: The module is downloading an update.
57+
* STATE_WAITING_FOR_IMAGE_APPLY: The module is waiting for the event FOTA_IMAGE_APPLY to
58+
* apply the image. This requires the application to
59+
* disconnect from the network before sending the event.
5960
* STATE_REBOOT_NEEDED: The FOTA module is waiting for a reboot.
6061
* STATE_CANCELED: The FOTA module has been canceled, cleaning up.
6162
*/
@@ -64,7 +65,7 @@ enum fota_module_state {
6465
STATE_WAITING_FOR_POLL_REQUEST,
6566
STATE_POLLING_FOR_UPDATE,
6667
STATE_DOWNLOADING_UPDATE,
67-
STATE_WAITING_FOR_NETWORK_DISCONNECT,
68+
STATE_WAITING_FOR_IMAGE_APPLY,
6869
STATE_REBOOT_NEEDED,
6970
STATE_CANCELED,
7071
};
@@ -95,8 +96,8 @@ static void state_polling_for_update_entry(void *o);
9596
static void state_polling_for_update_run(void *o);
9697
static void state_downloading_update_entry(void *o);
9798
static void state_downloading_update_run(void *o);
98-
static void state_waiting_for_network_disconnect_entry(void *o);
99-
static void state_waiting_for_network_disconnect_run(void *o);
99+
static void state_waiting_for_image_apply_entry(void *o);
100+
static void state_waiting_for_image_apply_run(void *o);
100101
static void state_reboot_needed_entry(void *o);
101102
static void state_canceled_entry(void *o);
102103

@@ -130,9 +131,9 @@ static const struct smf_state states[] = {
130131
NULL,
131132
&states[STATE_RUNNING],
132133
NULL),
133-
[STATE_WAITING_FOR_NETWORK_DISCONNECT] =
134-
SMF_CREATE_STATE(state_waiting_for_network_disconnect_entry,
135-
state_waiting_for_network_disconnect_run,
134+
[STATE_WAITING_FOR_IMAGE_APPLY] =
135+
SMF_CREATE_STATE(state_waiting_for_image_apply_entry,
136+
state_waiting_for_image_apply_run,
136137
NULL,
137138
&states[STATE_RUNNING],
138139
NULL),
@@ -200,7 +201,7 @@ static void fota_status(enum nrf_cloud_fota_status status, const char *const sta
200201
case NRF_CLOUD_FOTA_FMFU_VALIDATION_NEEDED:
201202
LOG_DBG("Full Modem FOTA Update validation needed, network disconnect required");
202203

203-
evt = FOTA_NETWORK_DISCONNECT_NEEDED;
204+
evt = FOTA_NETWORK_DISCONNECT_AND_APPLY_NEEDED;
204205
break;
205206
default:
206207
LOG_DBG("Unknown FOTA status: %d", status);
@@ -354,8 +355,8 @@ static void state_downloading_update_run(void *o)
354355
const enum fota_msg_type evt = MSG_TO_FOTA_TYPE(state_object->msg_buf);
355356

356357
switch (evt) {
357-
case FOTA_NETWORK_DISCONNECT_NEEDED:
358-
STATE_SET(fota_state, STATE_WAITING_FOR_NETWORK_DISCONNECT);
358+
case FOTA_NETWORK_DISCONNECT_AND_APPLY_NEEDED:
359+
STATE_SET(fota_state, STATE_WAITING_FOR_IMAGE_APPLY);
359360
break;
360361
case FOTA_DOWNLOAD_FAILED:
361362
STATE_SET(fota_state, STATE_WAITING_FOR_POLL_REQUEST);
@@ -367,22 +368,22 @@ static void state_downloading_update_run(void *o)
367368
}
368369
}
369370

370-
static void state_waiting_for_network_disconnect_entry(void *o)
371+
static void state_waiting_for_image_apply_entry(void *o)
371372
{
372373
ARG_UNUSED(o);
373374

374375
LOG_DBG("%s", __func__);
375376
}
376377

377-
static void state_waiting_for_network_disconnect_run(void *o)
378+
static void state_waiting_for_image_apply_run(void *o)
378379
{
379380
struct fota_state *state_object = o;
380381

381382
if (&FOTA_CHAN == state_object->chan) {
382383
const enum fota_msg_type evt = MSG_TO_FOTA_TYPE(state_object->msg_buf);
383384

384385
switch (evt) {
385-
case FOTA_APPLY_IMAGE:
386+
case FOTA_IMAGE_APPLY:
386387

387388
LOG_DBG("Applying downloaded firmware image");
388389

app/src/modules/fota/fota.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ enum fota_msg_type {
3636
FOTA_REBOOT_NEEDED,
3737

3838
/* Event notified when the module needs the network to disconnect in order to apply
39-
* an update. When network has been disconnect, send the event FOTA_APPLY_IMAGE.
39+
* an update. When the network has been disconnect, send the event FOTA_IMAGE_APPLY.
4040
*/
41-
FOTA_NETWORK_DISCONNECT_NEEDED,
41+
FOTA_NETWORK_DISCONNECT_AND_APPLY_NEEDED,
4242

4343
/* Event notified when the FOTA update has been canceled. */
4444
FOTA_CANCELED,
@@ -49,7 +49,7 @@ enum fota_msg_type {
4949
FOTA_POLL_REQUEST,
5050

5151
/* Request to apply the downloaded firmware image. */
52-
FOTA_APPLY_IMAGE,
52+
FOTA_IMAGE_APPLY,
5353

5454
/* Cancel the FOTA process. */
5555
FOTA_CANCEL,

tests/module/fota/src/fota_module_test.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ void test_fota_module_should_succeed(void)
158158

159159
/* 3. Download succeeded, validation needed */
160160
invoke_nrf_cloud_fota_callback_stub_status(NRF_CLOUD_FOTA_FMFU_VALIDATION_NEEDED);
161-
event_expect(FOTA_NETWORK_DISCONNECT_NEEDED);
161+
event_expect(FOTA_NETWORK_DISCONNECT_AND_APPLY_NEEDED);
162162

163163
/* 4. Apply image */
164-
event_send(FOTA_APPLY_IMAGE);
165-
event_expect(FOTA_APPLY_IMAGE);
164+
event_send(FOTA_IMAGE_APPLY);
165+
event_expect(FOTA_IMAGE_APPLY);
166166

167167
/* 5. Reboot needed */
168168
invoke_nrf_cloud_fota_callback_stub_reboot(FOTA_REBOOT_SUCCESS);

0 commit comments

Comments
 (0)