Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ CONFIG_NRF_CLOUD_FOTA_POLL=y
CONFIG_NRF_CLOUD_FOTA_POLL_LOG_LEVEL_DBG=y
CONFIG_NRF_CLOUD_FOTA_FULL_MODEM_UPDATE=y
CONFIG_NRF_CLOUD_FOTA_DOWNLOAD_FRAGMENT_SIZE=1700
CONFIG_NRF_CLOUD_COAP_DOWNLOADS=y
CONFIG_FOTA_DOWNLOAD=y
CONFIG_FOTA_DOWNLOAD_PROGRESS_EVT=y
CONFIG_FOTA_DL_TIMEOUT_MIN=30
Expand Down
23 changes: 21 additions & 2 deletions app/src/modules/app/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static void trigger_work_fn(struct k_work *work);
static K_WORK_DELAYABLE_DEFINE(trigger_work, trigger_work_fn);

/* Forward declarations of state handlers */
static void running_entry(void *o);
static void running_run(void *o);

static void periodic_triggering_entry(void *o);
Expand Down Expand Up @@ -125,11 +126,11 @@ static struct app_state_object app_state;
/* Construct state table */
static const struct smf_state states[] = {
[STATE_RUNNING] = SMF_CREATE_STATE(
NULL,
running_entry,
running_run,
NULL,
NULL,
&states[STATE_IDLE]
NULL
),
[STATE_PERIODIC_TRIGGERING] = SMF_CREATE_STATE(
periodic_triggering_entry,
Expand Down Expand Up @@ -267,13 +268,31 @@ static void trigger_work_fn(struct k_work *work)

triggers_send();

LOG_DBG("Next trigger in %lld seconds", app_state.interval_sec);

k_work_reschedule(&trigger_work, K_SECONDS(app_state.interval_sec));
}

/* Zephyr State Machine framework handlers */

/* STATE_RUNNING */

static void running_entry(void *o)
{
const struct app_state_object *state_object = (const struct app_state_object *)o;

LOG_DBG("%s", __func__);

if (state_object->status == CLOUD_CONNECTED_READY_TO_SEND ||
state_object->status == CLOUD_PAYLOAD_JSON ||
state_object->status == CLOUD_POLL_SHADOW) {
STATE_SET(app_state, STATE_PERIODIC_TRIGGERING);
return;
}

STATE_SET(app_state, STATE_IDLE);
}

static void running_run(void *o)
{
const struct app_state_object *state_object = (const struct app_state_object *)o;
Expand Down
63 changes: 45 additions & 18 deletions app/src/modules/fota/fota.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ static void state_waiting_for_image_apply_run(void *o);

static void state_reboot_needed_entry(void *o);

static void state_canceled_entry(void *o);
static void state_canceling_entry(void *o);
static void state_canceling_run(void *o);

static struct fota_state fota_state = {
.fota_ctx.reboot_fn = fota_reboot,
Expand Down Expand Up @@ -148,8 +149,8 @@ static const struct smf_state states[] = {
&states[STATE_RUNNING],
NULL),
[STATE_CANCELED] =
SMF_CREATE_STATE(state_canceled_entry,
NULL,
SMF_CREATE_STATE(state_canceling_entry,
state_canceling_run,
NULL,
&states[STATE_RUNNING],
NULL),
Expand Down Expand Up @@ -189,6 +190,11 @@ static void fota_status(enum nrf_cloud_fota_status status, const char *const sta

evt = FOTA_DOWNLOAD_FAILED;
break;
case NRF_CLOUD_FOTA_CANCELED:
LOG_WRN("Firmware download canceled");

evt = FOTA_CANCELED;
break;
case NRF_CLOUD_FOTA_TIMED_OUT:
LOG_WRN("Firmware download timed out");

Expand All @@ -214,14 +220,14 @@ static void fota_status(enum nrf_cloud_fota_status status, const char *const sta

err = zbus_chan_pub(&FOTA_CHAN, &evt, K_SECONDS(1));
if (err) {
LOG_DBG("zbus_chan_pub, error: %d", err);
LOG_ERR("zbus_chan_pub, error: %d", err);
SEND_FATAL_ERROR();
}
}

static void task_wdt_callback(int channel_id, void *user_data)
{
LOG_DBG("Watchdog expired, Channel: %d, Thread: %s",
LOG_ERR("Watchdog expired, Channel: %d, Thread: %s",
channel_id, k_thread_name_get((k_tid_t)user_data));

SEND_FATAL_ERROR_WATCHDOG_TIMEOUT();
Expand All @@ -239,16 +245,16 @@ static void state_running_entry(void *o)
/* Initialize the FOTA context */
err = nrf_cloud_fota_poll_init(&state_object->fota_ctx);
if (err) {
LOG_DBG("nrf_cloud_fota_poll_init failed: %d", err);
LOG_ERR("nrf_cloud_fota_poll_init failed: %d", err);
SEND_FATAL_ERROR();
}

/* Process pending FOTA job, the FOTA type is returned */
err = nrf_cloud_fota_poll_process_pending(&state_object->fota_ctx);
if (err < 0) {
LOG_DBG("nrf_cloud_fota_poll_process_pending failed: %d", err);
LOG_ERR("nrf_cloud_fota_poll_process_pending failed: %d", err);
} else if (err != NRF_CLOUD_FOTA_TYPE__INVALID) {
LOG_DBG("Processed pending FOTA job type: %d", err);
LOG_ERR("Processed pending FOTA job type: %d", err);
}
}

Expand Down Expand Up @@ -306,7 +312,7 @@ static void state_polling_for_update_entry(void *o)

err = zbus_chan_pub(&FOTA_CHAN, &evt, K_SECONDS(1));
if (err) {
LOG_DBG("zbus_chan_pub, error: %d", err);
LOG_ERR("zbus_chan_pub, error: %d", err);
SEND_FATAL_ERROR();
}
break;
Expand All @@ -317,7 +323,7 @@ static void state_polling_for_update_entry(void *o)
LOG_DBG("Job available, FOTA processing started");
break;
default:
LOG_DBG("nrf_cloud_fota_poll_process, error: %d", err);
LOG_ERR("nrf_cloud_fota_poll_process, error: %d", err);
SEND_FATAL_ERROR();
break;
}
Expand All @@ -337,6 +343,11 @@ static void state_polling_for_update_run(void *o)
case FOTA_NO_AVAILABLE_UPDATE:
STATE_SET(fota_state, STATE_WAITING_FOR_POLL_REQUEST);
break;
case FOTA_CANCEL:
LOG_DBG("No ongoing FOTA update, nothing to cancel");

STATE_EVENT_HANDLED(fota_state);
break;
default:
/* Don't care */
break;
Expand Down Expand Up @@ -395,7 +406,7 @@ static void state_waiting_for_image_apply_run(void *o)
int err = nrf_cloud_fota_poll_update_apply(&state_object->fota_ctx);

if (err) {
LOG_DBG("nrf_cloud_fota_poll_update_apply, error: %d", err);
LOG_ERR("nrf_cloud_fota_poll_update_apply, error: %d", err);
SEND_FATAL_ERROR();
}

Expand All @@ -417,16 +428,32 @@ static void state_reboot_needed_entry(void *o)
LOG_DBG("Waiting for the application to reboot in order to apply the update");
}

static void state_canceled_entry(void *o)
static void state_canceling_entry(void *o)
{
ARG_UNUSED(o);

LOG_DBG("%s", __func__);
LOG_WRN("Canceling download");
LOG_DBG("Canceling download");

(void)fota_download_cancel();
int err = fota_download_cancel();

STATE_SET(fota_state, STATE_WAITING_FOR_POLL_REQUEST);
if (err) {
LOG_ERR("fota_download_cancel, error: %d", err);
SEND_FATAL_ERROR();
}
}

static void state_canceling_run(void *o)
{
const struct fota_state *state_object = (const struct fota_state *)o;

if (&FOTA_CHAN == state_object->chan) {
const enum fota_msg_type msg = MSG_TO_FOTA_TYPE(state_object->msg_buf);

if (msg == FOTA_CANCELED) {
STATE_SET(fota_state, STATE_WAITING_FOR_POLL_REQUEST);
}
}
}

/* End of state handlers */
Expand All @@ -449,7 +476,7 @@ static void fota_task(void)
while (true) {
err = task_wdt_feed(task_wdt_id);
if (err) {
LOG_DBG("task_wdt_feed, error: %d", err);
LOG_ERR("task_wdt_feed, error: %d", err);
SEND_FATAL_ERROR();
return;
}
Expand All @@ -458,14 +485,14 @@ static void fota_task(void)
if (err == -ENOMSG) {
continue;
} else if (err) {
LOG_DBG("zbus_sub_wait_msg, error: %d", err);
LOG_ERR("zbus_sub_wait_msg, error: %d", err);
SEND_FATAL_ERROR();
return;
}

err = STATE_RUN(fota_state);
if (err) {
LOG_DBG("handle_message, error: %d", err);
LOG_ERR("handle_message, error: %d", err);
SEND_FATAL_ERROR();
return;
}
Expand Down
Loading