Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FOTA support and enable MCUboot logs #14

Merged
merged 4 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
26 changes: 26 additions & 0 deletions child_image/mcuboot.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,29 @@
# Increase the monotonic firmware version before building a firmware update
CONFIG_FW_INFO=y
CONFIG_FW_INFO_FIRMWARE_VERSION=1

# Note: BOOT_SERIAL and UART_CONSOLE cannot be installed on the same uart
# It looks like there is an unused UART_1 on the thingy where we could
# potentially wire up CONFIG_MCUBOOT_SERIAL=y CONFIG_BOOT_SERIAL_UART=y
# in the future

CONFIG_MCUBOOT_SERIAL=n
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_MCUBOOT_LOG_LEVEL_DBG=y

# Note: The image is nearly full causing some kind of edge case to be hit when swap upgrade
# move strategy is used:
#
# I: Boot source: none
# I: Image index: 0, Swap type: test
# I: Starting swap using move algorithm.
# W: Not enough free space to run swap upgrade
# W: required 430080 bytes but only 425984 are available
#
# For more info about mcuboot upgrade strategies see:
# https://interrupt.memfault.com/blog/mcuboot-overview#swap-mode
#
# For now let's flip on MCUBOOT_OVERWRITE_ONLY mode which has less wonky
# flash requirements (and imo is better for long term flash health)
CONFIG_BOOT_UPGRADE_ONLY=y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my kingdom for a single kconfig flag 🥹

4 changes: 4 additions & 0 deletions prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,7 @@ CONFIG_LOG_DEFAULT_LEVEL=3
# instead of logs being separately viewed in a file via
# RTT logger
CONFIG_SHELL_LOG_BACKEND=y

# Let's manage the memfault_fota_download_callback() from
# the asset tracker application rather than using the Memfault default
CONFIG_MEMFAULT_FOTA_DOWNLOAD_CALLBACK_CUSTOM=y
79 changes: 79 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include "events/util_module_event.h"
#include "events/modem_module_event.h"

#include "memfault/components.h"
#include "memfault/nrfconnect_port/fota.h"

#include <zephyr/logging/log.h>
#include <zephyr/logging/log_ctrl.h>

Expand Down Expand Up @@ -490,6 +493,74 @@ static void on_sub_state_active(struct app_msg_data *msg)
}
}

/* always check for a new FOTA on first boot and then every timer period */
static bool s_run_fota_check_upon_lte_connect = true;

static void prv_memfault_fota_work_handler(struct k_work *work) {
int rv = memfault_fota_start();
if (rv < 0) {
/* we may have just not been connected, try again on next connect */
s_run_fota_check_upon_lte_connect = true;
} else if (rv == 0) {
MEMFAULT_LOG_INFO("FOTA up to date");
}
}
K_WORK_DELAYABLE_DEFINE(s_memfault_fota_work, prv_memfault_fota_work_handler);

static void prv_run_memfault_fota_check(void) {
k_work_schedule(&s_memfault_fota_work, K_SECONDS(5));
}

void memfault_fota_download_callback(const struct fota_download_evt *evt) {
switch (evt->id) {
case FOTA_DOWNLOAD_EVT_FINISHED:
MEMFAULT_LOG_INFO("OTA Complete, resetting to install update!");
memfault_platform_reboot();
break;
case FOTA_DOWNLOAD_EVT_ERROR:
/*
* FIXME: When multiple threads are send/read'ing from the modem
* at the same time, we get intermittent corruption issues. We should
* really figure out what is wrong here but for now we just keep retrying.
*
* Example error logs:
*
* [00:04:45.544,891] <wrn> location: GNSS timed out possibly due to too short GNSS time windows
* [00:04:45.557,037] <inf> app_event_manager: LOCATION_MODULE_EVT_CLOUD_LOCATION_DATA_READY
* [00:04:45.557,769] <inf> app_event_manager: DATA_EVT_DATA_READY
* [00:04:45.562,713] <inf> app_event_manager: DATA_EVT_CLOUD_LOCATION_DATA_SEND
* [00:04:45.580,718] <inf> app_event_manager: DATA_EVT_DATA_SEND_BATCH
* [00:04:45.581,604] <inf> app_event_manager: CLOUD_EVT_DATA_SEND_QOS
* [00:04:45.581,909] <inf> app_event_manager: CLOUD_EVT_CLOUD_LOCATION_UNKNOWN
* [00:04:45.582,672] <inf> app_event_manager: LOCATION_MODULE_EVT_INACTIVE
* [00:04:45.583,923] <inf> app_event_manager: CLOUD_EVT_DATA_SEND_QOS
* [00:04:46.846,618] <inf> download_client: Downloaded 346112/424124 bytes (81%)
* [00:04:47.373,565] <err> download_client: Unexpected HTTP response: 403 forbidden
* [00:04:47.373,596] <err> fota_download: Download client error
* [00:04:47.373,596] <err> fota_download: Download client error
* [00:04:47.373,596] <inf> dfu_target_mcuboot: MCUBoot image upgrade aborted.
* [00:04:47.373,657] <inf> dfu_target_mcuboot: MCUBoot image upgrade aborted.
* [00:04:47.375,183] <err> FOTA failed -- trying again ...
*/
MEMFAULT_LOG_ERROR("FOTA failed -- trying again ...");
prv_run_memfault_fota_check();
break;
default:
break;
}
}

static void prv_memfault_fota_timer_expiry_handler(struct k_timer *dummy) {
prv_run_memfault_fota_check();
}

K_TIMER_DEFINE(s_memfault_fota_timer, prv_memfault_fota_timer_expiry_handler, NULL);

static void prv_memfault_fota_timer_start(void) {
/* Check and see if new FOTA is available every 12 hours */
k_timer_start(&s_memfault_fota_timer, K_HOURS(12), K_HOURS(12));
}

/* Message handler for all states. */
static void on_all_events(struct app_msg_data *msg)
{
Expand Down Expand Up @@ -517,6 +588,13 @@ static void on_all_events(struct app_msg_data *msg)
if (IS_EVENT(msg, sensor, SENSOR_EVT_MOVEMENT_IMPACT_DETECTED)) {
SEND_EVENT(app, APP_EVT_DATA_GET_ALL);
}

if (IS_EVENT(msg, modem, MODEM_EVT_LTE_CONNECTED)) {
if (s_run_fota_check_upon_lte_connect) {
prv_run_memfault_fota_check();
s_run_fota_check_upon_lte_connect = false;
}
}
}

int main(void)
Expand Down Expand Up @@ -547,6 +625,7 @@ int main(void)
LOG_ERR("Failed starting module, error: %d", err);
SEND_ERROR(app, APP_EVT_ERROR, err);
}
prv_memfault_fota_timer_start();

while (true) {
module_get_next_msg(&self, &msg);
Expand Down
Loading