zephyr: allow recovery over usb cdc-acm with logs enabled
Modified serial_adapter so log are allowed when using USB
CDC ACM serial port emulation.
Added dedicated thread for log processing of the highest application
priority. This allows to transmit all logs without adding k_sleep
anywhere else int the code.
Introduced boot log thread is simpler than the default log threat
which decreases flash footprint by a few dozen bytes.
Added configuration for nrf52840_pca10056 which shows how
to enable looging along with USB - among other, thread log
processing is required.
build command (form zephyr-project root directory)
west build -d build/mcuboot/nrf52840_pca10056 -b nrf52840_pca10056
./bootloader/mcuboot/boot/zephyr/
-- -DDTC_OVERLAY_FILE=./boards/nrf52840_pca10056_big.overlay
-DOVERLAY_CONFIG=./usb_cdc_acm_log_recovery.conf
Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig
index d8f72a3..96bcd89 100644
--- a/boot/zephyr/Kconfig
+++ b/boot/zephyr/Kconfig
@@ -359,6 +359,14 @@
config LOG_IMMEDIATE
default n if MULTITHREADING
+ default y
+
+config LOG_PROCESS_THREAD
+ default n # mcuboot has its own log processing thread
+
+# override USB device name
+config USB_DEVICE_PRODUCT
+ default "MCUBOOT"
config UPDATEABLE_IMAGE_NUMBER
int "Number of updateable images"
diff --git a/boot/zephyr/boards/nrf52840_pca10056_big.overlay b/boot/zephyr/boards/nrf52840_pca10056_big.overlay
new file mode 100644
index 0000000..094a7a4
--- /dev/null
+++ b/boot/zephyr/boards/nrf52840_pca10056_big.overlay
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/delete-node/ &boot_partition;
+/delete-node/ &slot0_partition;
+/delete-node/ &slot1_partition;
+
+&flash0 {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_partition: partition@0 {
+ label = "mcuboot";
+ reg = <0x000000000 0x00010000>;
+ };
+ slot0_partition: partition@10000 {
+ label = "image-0";
+ reg = <0x000010000 0x000074000>;
+ };
+ slot1_partition: partition@75000 {
+ label = "image-1";
+ reg = <0x00084000 0x000074000>;
+ };
+ };
+};
diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c
index e2e609f..2fd80ee 100644
--- a/boot/zephyr/main.c
+++ b/boot/zephyr/main.c
@@ -44,6 +44,28 @@
#include <usb/class/usb_dfu.h>
#endif
+#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_IMMEDIATE)
+#ifdef CONFIG_LOG_PROCESS_THREAD
+#warning "The log internal thread for log processing can't transfer the log"\
+ "well for MCUBoot."
+#else
+#include <logging/log_ctrl.h>
+
+#define BOOT_LOG_STACK_SIZE 768
+#define BOOT_LOG_PROCESSING_INTERVAL 30 /* [ms] */
+
+/* log are processing in custom routine */
+K_THREAD_STACK_DEFINE(boot_log_stack, BOOT_LOG_STACK_SIZE);
+struct k_thread boot_log_thread;
+
+/* log processing need to be initalized by the application */
+#define ZEPHYR_BOOT_LOG_START() zephyr_boot_log_start()
+#endif /* CONFIG_LOG_PROCESS_THREAD */
+#else
+/* synchronous log mode doesn't need to be initalized by the application */
+#define ZEPHYR_BOOT_LOG_START() do { } while (false)
+#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_IMMEDIATE) */
+
#ifdef CONFIG_SOC_FAMILY_NRF
#include <hal/nrf_power.h>
@@ -175,6 +197,45 @@
}
#endif
+#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_IMMEDIATE) &&\
+ !defined(CONFIG_LOG_PROCESS_THREAD)
+/* The log internal thread for log processing can't transfer log well as has too
+ * low priority.
+ * Dedicated thread for log processing below uses highest application
+ * priority. This allows to transmit all logs without adding k_sleep/k_yield
+ * anywhere else int the code.
+ */
+
+/* most simple log processing theread */
+void boot_log_thread_func(void *dummy1, void *dummy2, void *dummy3)
+{
+ (void)dummy1;
+ (void)dummy2;
+ (void)dummy3;
+
+ log_init();
+
+ while (1) {
+ if (log_process(false) == false) {
+ k_sleep(BOOT_LOG_PROCESSING_INTERVAL);
+ }
+ }
+}
+
+void zephyr_boot_log_start(void)
+{
+ /* start logging thread */
+ k_thread_create(&boot_log_thread, boot_log_stack,
+ K_THREAD_STACK_SIZEOF(boot_log_stack),
+ boot_log_thread_func, NULL, NULL, NULL,
+ K_HIGHEST_APPLICATION_THREAD_PRIO, 0,
+ BOOT_LOG_PROCESSING_INTERVAL);
+
+ k_thread_name_set(&boot_log_thread, "logging");
+}
+#endif/* defined(CONFIG_LOG) && !defined(CONFIG_LOG_IMMEDIATE) &&\
+ !defined(CONFIG_LOG_PROCESS_THREAD) */
+
void main(void)
{
struct boot_rsp rsp;
@@ -184,6 +245,8 @@
os_heap_init();
+ ZEPHYR_BOOT_LOG_START();
+
#if (!defined(CONFIG_XTENSA) && defined(DT_FLASH_DEV_NAME))
if (!flash_device_get_binding(DT_FLASH_DEV_NAME)) {
BOOT_LOG_ERR("Flash device %s not found", DT_FLASH_DEV_NAME);
diff --git a/boot/zephyr/sample.yaml b/boot/zephyr/sample.yaml
index d486aac..62518c1 100644
--- a/boot/zephyr/sample.yaml
+++ b/boot/zephyr/sample.yaml
@@ -13,3 +13,8 @@
sample.bootloader.mcuboot.usb_cdc_acm_recovery:
tags: bootloader_mcuboot
platform_whitelist: nrf52840_pca10059
+ sample.bootloader.mcuboot.usb_cdc_acm_recovery_log:
+ extra_args: OVERLAY_CONFIG=./usb_cdc_acm_log_recovery.conf
+ DTC_OVERLAY=./boards/nrf52840_pca10056_big.overlay
+ platform_whitelist: nrf52840_pca10056
+ tags: bootloader_mcuboot
diff --git a/boot/zephyr/serial_adapter.c b/boot/zephyr/serial_adapter.c
index e5ebfdb..63dca02 100644
--- a/boot/zephyr/serial_adapter.c
+++ b/boot/zephyr/serial_adapter.c
@@ -22,7 +22,7 @@
#include "bootutil/bootutil_log.h"
#include <usb/usb_device.h>
-#ifdef CONFIG_UART_CONSOLE
+#if defined(CONFIG_BOOT_SERIAL_UART) && defined(CONFIG_UART_CONSOLE)
#error Zephyr UART console must been disabled if serial_adapter module is used.
#endif
diff --git a/boot/zephyr/usb_cdc_acm_log_recovery.conf b/boot/zephyr/usb_cdc_acm_log_recovery.conf
new file mode 100644
index 0000000..ae412fe
--- /dev/null
+++ b/boot/zephyr/usb_cdc_acm_log_recovery.conf
@@ -0,0 +1,16 @@
+CONFIG_LOG=y
+
+# The build won't fit on the partition allocated for it without size
+# optimizations.
+CONFIG_SIZE_OPTIMIZATIONS=y
+
+# Serial
+CONFIG_SERIAL=y
+CONFIG_UART_LINE_CTRL=y
+
+# MCUBoot serial
+CONFIG_MCUBOOT_SERIAL=y
+CONFIG_BOOT_SERIAL_CDC_ACM=y
+
+CONFIG_LOG_BACKEND_UART=y
+CONFIG_LOG_BACKEND_RTT=n