Przeglądaj źródła

[FL-164] Add bootloader version (#417)

* Add bootloader versioning
* Move some logic to api-hal-version
* Backport to f4
* Dolphin: update version screen layout, make it more readable

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Albert Kharisov 4 lat temu
rodzic
commit
aa20a78b0e

+ 23 - 6
applications/cli/cli.c

@@ -1,5 +1,7 @@
 #include "cli_i.h"
 #include "cli_commands.h"
+#include <version.h>
+#include <api-hal-version.h>
 
 Cli* cli_alloc() {
     Cli* cli = furi_alloc(sizeof(Cli));
@@ -48,16 +50,31 @@ size_t cli_read(Cli* cli, uint8_t* buffer, size_t size) {
     return api_hal_vcp_rx(buffer, size);
 }
 
-void cli_print_version() {
-    printf("Build date:" BUILD_DATE ". "
-           "Git Commit:" GIT_COMMIT ". "
-           "Git Branch:" GIT_BRANCH ". "
-           "Commit Number:" GIT_BRANCH_NUM ".");
+void cli_print_version(const Version* version) {
+    if(version) {
+        printf("\tVersion:\t%s\r\n", version_get_version(version));
+        printf("\tBuild date:\t%s\r\n", version_get_builddate(version));
+        printf(
+            "\tGit Commit:\t%s (%s)\r\n",
+            version_get_githash(version),
+            version_get_gitbranchnum(version));
+        printf("\tGit Branch:\t%s\r\n", version_get_gitbranch(version));
+    } else {
+        printf("\tNo build info\r\n");
+    }
 }
 
 void cli_motd() {
+    const Version* version;
     printf("Flipper cli.\r\n");
-    cli_print_version();
+
+    version = (const Version*)api_hal_version_get_boot_version();
+    printf("Bootloader\r\n");
+    cli_print_version(version);
+
+    version = (const Version*)api_hal_version_get_fw_version();
+    printf("Firmware\r\n");
+    cli_print_version(version);
 }
 
 void cli_nl() {

+ 31 - 1
applications/dolphin/dolphin.c

@@ -191,6 +191,33 @@ bool dolphin_view_lockmenu_input(InputEvent* event, void* context) {
     return true;
 }
 
+bool dolphin_view_idle_down_input(InputEvent* event, void* context) {
+    furi_assert(event);
+    furi_assert(context);
+    Dolphin* dolphin = context;
+
+    if(event->type != InputTypeShort) return false;
+
+    if((event->key == InputKeyLeft) || (event->key == InputKeyRight)) {
+        with_view_model(
+            dolphin->idle_view_down, (DolphinViewIdleDownModel * model) {
+                model->show_fw_or_boot = !model->show_fw_or_boot;
+                return true;
+            });
+    }
+
+    if(event->key == InputKeyBack) {
+        with_view_model(
+            dolphin->idle_view_down, (DolphinViewIdleDownModel * model) {
+                model->show_fw_or_boot = 0;
+                return true;
+            });
+        view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain);
+    }
+
+    return false;
+}
+
 Dolphin* dolphin_alloc() {
     Dolphin* dolphin = furi_alloc(sizeof(Dolphin));
     // Message queue
@@ -255,11 +282,14 @@ Dolphin* dolphin_alloc() {
 
     // Down Idle View
     dolphin->idle_view_down = view_alloc();
+    view_set_context(dolphin->idle_view_down, dolphin);
+    view_allocate_model(
+        dolphin->idle_view_down, ViewModelTypeLockFree, sizeof(DolphinViewIdleDownModel));
     view_set_draw_callback(dolphin->idle_view_down, dolphin_view_idle_down_draw);
+    view_set_input_callback(dolphin->idle_view_down, dolphin_view_idle_down_input);
     view_set_previous_callback(dolphin->idle_view_down, dolphin_view_idle_back);
     view_dispatcher_add_view(
         dolphin->idle_view_dispatcher, DolphinViewIdleDown, dolphin->idle_view_down);
-
     // HW Mismatch
     dolphin->view_hw_mismatch = view_alloc();
     view_set_draw_callback(dolphin->view_hw_mismatch, dolphin_view_hw_mismatch_draw);

+ 33 - 10
applications/dolphin/dolphin_views.c

@@ -3,6 +3,8 @@
 #include <gui/gui.h>
 #include <gui/elements.h>
 #include <api-hal.h>
+#include <version.h>
+#include <api-hal-version.h>
 
 static char* Lockmenu_Items[3] = {"Lock", "Set PIN", "DUMB mode"};
 
@@ -92,25 +94,46 @@ void dolphin_view_lockmenu_draw(Canvas* canvas, void* model) {
 }
 
 void dolphin_view_idle_down_draw(Canvas* canvas, void* model) {
-    canvas_clear(canvas);
+    DolphinViewIdleDownModel* m = model;
+    const Version* ver;
+    char buffer[64];
+
     canvas_set_color(canvas, ColorBlack);
     canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str(canvas, 2, 15, "Version info:");
+    canvas_draw_str(canvas, 2, 13, m->show_fw_or_boot ? "Boot Version info:" : "FW Version info:");
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str(canvas, 5, 25, TARGET " " BUILD_DATE);
-    canvas_draw_str(canvas, 5, 35, GIT_BRANCH);
-    canvas_draw_str(canvas, 5, 45, GIT_BRANCH_NUM " " GIT_COMMIT);
 
-    char buffer[64];
+    // Hardware version
     snprintf(
         buffer,
-        64,
-        "HW: %d.F%dB%dC%d",
+        sizeof(buffer),
+        "HW: %d.F%dB%dC%d %s",
         api_hal_version_get_hw_version(),
         api_hal_version_get_hw_target(),
         api_hal_version_get_hw_body(),
-        api_hal_version_get_hw_connect());
-    canvas_draw_str(canvas, 5, 55, buffer);
+        api_hal_version_get_hw_connect(),
+        api_hal_version_get_name_ptr());
+    canvas_draw_str(canvas, 5, 23, buffer);
+
+    ver = m->show_fw_or_boot ? api_hal_version_get_boot_version() :
+                               api_hal_version_get_fw_version();
+
+    if(!ver) {
+        canvas_draw_str(canvas, 5, 33, "No info");
+        return;
+    }
+
+    snprintf(
+        buffer, sizeof(buffer), "%s [%s]", version_get_version(ver), version_get_builddate(ver));
+    canvas_draw_str(canvas, 5, 33, buffer);
+
+    snprintf(
+        buffer, sizeof(buffer), "%s [%s]", version_get_githash(ver), version_get_gitbranchnum(ver));
+    canvas_draw_str(canvas, 5, 43, buffer);
+
+    snprintf(
+        buffer, sizeof(buffer), "[%s] %s", version_get_target(ver), version_get_gitbranch(ver));
+    canvas_draw_str(canvas, 5, 53, buffer);
 }
 
 void dolphin_view_hw_mismatch_draw(Canvas* canvas, void* model) {

+ 4 - 0
applications/dolphin/dolphin_views.h

@@ -28,6 +28,10 @@ typedef struct {
     uint32_t butthurt;
 } DolphinViewIdleUpModel;
 
+typedef struct {
+    bool show_fw_or_boot;
+} DolphinViewIdleDownModel;
+
 typedef struct {
     uint8_t idx;
 } DolphinViewMenuModel;

+ 1 - 1
bootloader/targets/f4/stm32wb55xx_flash_cm4.ld

@@ -55,7 +55,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
 /* Specify the memory areas */
 MEMORY
 {
-FLASH (rx)                 : ORIGIN = 0x08000000, LENGTH = 512K
+FLASH (rx)                 : ORIGIN = 0x08000000, LENGTH = 32K
 RAM1 (xrw)                 : ORIGIN = 0x20000004, LENGTH = 0x2FFFC
 RAM_SHARED (xrw)           : ORIGIN = 0x20030000, LENGTH = 10K
 }

+ 7 - 0
bootloader/targets/f4/target.c

@@ -9,6 +9,8 @@
 #include <stm32wbxx_ll_gpio.h>
 #include <stm32wbxx_hal_flash.h>
 
+#include <version.h>
+
 // Boot request enum
 #define BOOT_REQUEST_NONE 0x00000000
 #define BOOT_REQUEST_DFU 0xDF00B000
@@ -128,6 +130,10 @@ void rtc_init() {
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
 }
 
+void version_save(void) {
+    LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR1, (uint32_t)version_get());
+}
+
 void lcd_backlight_on() {
     LL_GPIO_SetOutputPin(BOOT_LCD_BL_PORT, BOOT_LCD_BL_PIN);
 }
@@ -142,6 +148,7 @@ void target_init() {
     clock_init();
     gpio_init();
     rtc_init();
+    version_save();
     usb_wire_reset();
 
     // Errata 2.2.9, Flash OPTVERR flag is always set after system reset

+ 4 - 0
bootloader/targets/f4/target.mk

@@ -24,6 +24,10 @@ CFLAGS			+= -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc
 
 LDFLAGS			+= -T$(TARGET_DIR)/stm32wb55xx_flash_cm4.ld
 
+# Version generation
+CFLAGS			+= -I../lib/version
+C_SOURCES		+= ../lib/version/version.c
+
 ASM_SOURCES		+= $(wildcard $(TARGET_DIR)/*.s)
 C_SOURCES		+= $(wildcard $(TARGET_DIR)/*.c)
 CPP_SOURCES		+= $(wildcard $(TARGET_DIR)/*.cpp)

+ 1 - 1
bootloader/targets/f5/stm32wb55xx_flash_cm4.ld

@@ -55,7 +55,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
 /* Specify the memory areas */
 MEMORY
 {
-FLASH (rx)                 : ORIGIN = 0x08000000, LENGTH = 512K
+FLASH (rx)                 : ORIGIN = 0x08000000, LENGTH = 32K
 RAM1 (xrw)                 : ORIGIN = 0x20000004, LENGTH = 0x2FFFC
 RAM_SHARED (xrw)           : ORIGIN = 0x20030000, LENGTH = 10K
 }

+ 6 - 0
bootloader/targets/f5/target.c

@@ -9,6 +9,7 @@
 #include <stm32wbxx_ll_gpio.h>
 #include <stm32wbxx_hal_flash.h>
 
+#include <version.h>
 #include <api-hal.h>
 
 // Boot request enum
@@ -110,6 +111,10 @@ void rtc_init() {
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
 }
 
+void version_save(void) {
+    LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR1, (uint32_t)version_get());
+}
+
 void usb_wire_reset() {
     LL_GPIO_ResetOutputPin(BOOT_USB_PORT, BOOT_USB_PIN);
     LL_mDelay(10);
@@ -122,6 +127,7 @@ void target_init() {
     api_hal_init();
     target_led_control("RGB");
     rtc_init();
+    version_save();
     usb_wire_reset();
 
     // Errata 2.2.9, Flash OPTVERR flag is always set after system reset

+ 3 - 0
bootloader/targets/f5/target.mk

@@ -37,6 +37,9 @@ C_SOURCES		+= $(DRIVERS_DIR)/lp5562.c
 CFLAGS			+= -I$(TARGET_DIR)/api-hal
 C_SOURCES		+= $(wildcard $(TARGET_DIR)/api-hal/*.c)
 
+# Version generation
+CFLAGS			+= -I../lib/version
+C_SOURCES		+= ../lib/version/version.c
 
 ASM_SOURCES		+= $(wildcard $(TARGET_DIR)/*.s)
 C_SOURCES		+= $(wildcard $(TARGET_DIR)/*.c)

+ 26 - 5
core/flipper.c

@@ -1,12 +1,33 @@
 #include "flipper.h"
 #include <applications.h>
 #include <furi.h>
+#include <version.h>
+#include <api-hal-version.h>
+
+static void flipper_print_version(const Version* version) {
+    if(version) {
+        printf("\tVersion:\t%s\r\n", version_get_version(version));
+        printf("\tBuild date:\t%s\r\n", version_get_builddate(version));
+        printf(
+            "\tGit Commit:\t%s (%s)\r\n",
+            version_get_githash(version),
+            version_get_gitbranchnum(version));
+        printf("\tGit Branch:\t%s\r\n", version_get_gitbranch(version));
+    } else {
+        printf("\tNo build info\r\n");
+    }
+}
 
 void flipper_init() {
-    printf("[flipper] Build date:" BUILD_DATE ". "
-           "Git Commit:" GIT_COMMIT ". "
-           "Git Branch:" GIT_BRANCH ". "
-           "Commit Number:" GIT_BRANCH_NUM "\r\n");
+    const Version* version;
+
+    version = (const Version*)api_hal_version_get_boot_version();
+    printf("Bootloader\r\n");
+    flipper_print_version(version);
+
+    version = (const Version*)api_hal_version_get_fw_version();
+    printf("Firmware\r\n");
+    flipper_print_version(version);
 
     printf("[flipper] starting services\r\n");
 
@@ -23,4 +44,4 @@ void flipper_init() {
     }
 
     printf("[flipper] services startup complete\r\n");
-}
+}

+ 1 - 0
firmware/targets/api-hal-include/api-hal-boot.h

@@ -1,4 +1,5 @@
 #pragma once
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {

+ 15 - 0
firmware/targets/api-hal-include/api-hal-version.h

@@ -3,6 +3,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
+#include <version.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -29,6 +30,20 @@ const uint32_t api_hal_version_get_hw_timestamp();
 /** Get pointer to target name */
 const char * api_hal_version_get_name_ptr();
 
+/**
+ * Get address of version structure of bootloader, stored in chip flash.
+ *
+ * @return Address of boot version structure.
+ */
+const struct Version* api_hal_version_get_boot_version(void);
+
+/**
+ * Get address of version structure of firmware.
+ *
+ * @return Address of firmware version structure.
+ */
+const struct Version* api_hal_version_get_fw_version(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 2 - 1
firmware/targets/f4/api-hal/api-hal-boot.c

@@ -10,4 +10,5 @@ void api_hal_boot_set_mode(ApiHalBootMode mode) {
     } else if (mode == ApiHalBootModeDFU) {
         LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU);
     }
-}
+}
+

+ 15 - 0
firmware/targets/f4/api-hal/api-hal-version.c

@@ -1,5 +1,6 @@
 #include <api-hal-version.h>
 #include <stm32wbxx.h>
+#include <stm32wbxx_ll_rtc.h>
 
 typedef struct {
     uint8_t version;
@@ -38,3 +39,17 @@ const char * api_hal_version_get_name_ptr() {
     char * name = ((ApiHalVersionOTP*)OTP_AREA_BASE)->name;
     return *name == 0xFFU ? NULL : name; 
 }
+
+const struct Version* api_hal_version_get_fw_version(void) {
+    return version_get();
+}
+
+const struct Version* api_hal_version_get_boot_version(void) {
+#ifdef NO_BOOTLOADER
+    return 0;
+#else
+    /* Backup register which points to structure in flash memory */
+    return (const struct Version*) LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR1);
+#endif
+}
+

+ 2 - 1
firmware/targets/f5/api-hal/api-hal-boot.c

@@ -10,4 +10,5 @@ void api_hal_boot_set_mode(ApiHalBootMode mode) {
     } else if (mode == ApiHalBootModeDFU) {
         LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU);
     }
-}
+}
+

+ 15 - 0
firmware/targets/f5/api-hal/api-hal-version.c

@@ -1,5 +1,6 @@
 #include <api-hal-version.h>
 #include <stm32wbxx.h>
+#include <stm32wbxx_ll_rtc.h>
 
 typedef struct {
     uint8_t version;
@@ -38,3 +39,17 @@ const char * api_hal_version_get_name_ptr() {
     char * name = ((ApiHalVersionOTP*)OTP_AREA_BASE)->name;
     return *name == 0xFFU ? NULL : name; 
 }
+
+const struct Version* api_hal_version_get_fw_version(void) {
+    return version_get();
+}
+
+const struct Version* api_hal_version_get_boot_version(void) {
+#ifdef NO_BOOTLOADER
+    return 0;
+#else
+    /* Backup register which points to structure in flash memory */
+    return (const struct Version*) LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR1);
+#endif
+}
+

+ 5 - 0
lib/lib.mk

@@ -82,3 +82,8 @@ CFLAGS			+= -I$(LIB_DIR)/common-api
 # drivers
 CFLAGS			+= -I$(LIB_DIR)/drivers
 C_SOURCES		+= $(wildcard $(LIB_DIR)/drivers/*.c)
+
+#version
+CFLAGS			+= -I$(LIB_DIR)/version
+C_SOURCES		+= $(LIB_DIR)/version/version.c
+

+ 50 - 0
lib/version/version.c

@@ -0,0 +1,50 @@
+#include "version.h"
+
+struct Version {
+    const char*  git_hash;
+    const char*  git_branch;
+    const char*  git_branch_num;
+    const char*  build_date;
+    const char*  version;
+    const char*  target;
+};
+
+/* version of current running firmware (bootloader/flipper) */
+static const Version version = {
+    .git_hash       = GIT_COMMIT,
+    .git_branch     = GIT_BRANCH,
+    .git_branch_num = GIT_BRANCH_NUM,
+    .build_date     = BUILD_DATE,
+    .version        = VERSION,
+    .target         = TARGET,
+};
+
+
+const Version* version_get(void) {
+    return &version;
+}
+
+const char* version_get_githash(const Version* v) {
+    return v ? v->git_hash : version.git_hash;
+}
+
+const char* version_get_gitbranch(const Version* v) {
+    return v ? v->git_branch : version.git_branch;
+}
+
+const char* version_get_gitbranchnum(const Version* v) {
+    return v ? v->git_branch_num : version.git_branch_num;
+}
+
+const char* version_get_builddate(const Version* v) {
+    return v ? v->build_date : version.build_date;
+}
+
+const char* version_get_version(const Version* v) {
+    return v ? v->version : version.version;
+}
+
+const char* version_get_target(const Version* v) {
+    return v ? v->target : version.target;
+}
+

+ 73 - 0
lib/version/version.h

@@ -0,0 +1,73 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Version Version;
+
+/**
+ * Gets current running firmware version handle.
+ * You can store it somewhere. But if you want to retrieve data,
+ * you have to use 'version_*_get()' set of functions.
+ * Also, 'version_*_get()' imply to use this
+ * handle if no handle (NULL_PTR) provided.
+ *
+ * @return Handle to version data.
+ */
+const Version* version_get(void);
+
+/**
+ * Gets git hash of build commit.
+ *
+ * @param   v - ptr to version handle. If zero - gets current running fw info.
+ * @return  git hash
+ */
+const char* version_get_githash(const Version* v);
+
+/**
+ * Gets git branch of build commit.
+ *
+ * @param   v - ptr to version handle. If zero - gets current running fw info.
+ * @return  git branch
+ */
+const char* version_get_gitbranch(const Version* v);
+
+/**
+ * Gets git number of build commit.
+ *
+ * @param   v - ptr to version handle. If zero - gets current running fw info.
+ * @return  number of commit
+ */
+const char* version_get_gitbranchnum(const Version* v);
+
+/**
+ * Gets build date.
+ *
+ * @param   v - ptr to version handle. If zero - gets current running fw info.
+ * @return  build date
+ */
+const char* version_get_builddate(const Version* v);
+
+/**
+ * Gets build version.
+ * Build version is last tag in git history.
+ *
+ * @param   v - ptr to version handle. If zero - gets current running fw info.
+ * @return  build date
+ */
+const char* version_get_version(const Version* v);
+
+/**
+ * Gets firmware target.
+ * Build version is last tag for build commit.
+ *
+ * @param   v - ptr to version handle. If zero - gets current running fw info.
+ * @return  build date
+ */
+const char* version_get_target(const Version* v);
+
+#ifdef __cplusplus
+}
+#endif
+

+ 3 - 1
make/git.mk

@@ -2,6 +2,8 @@ GIT_COMMIT		= $(shell git describe --always  --exclude '*' || echo 'unknown')
 GIT_BRANCH		= $(shell git rev-parse --abbrev-ref HEAD || echo 'unknown')
 GIT_BRANCH_NUM	= $(shell git rev-list --count $(GIT_BRANCH) || echo 'nan')
 BUILD_DATE		= $(shell date '+%d-%m-%Y' || echo 'unknown')
+VERSION			= $(shell git describe --tags --abbrev=0 || echo 'unknown')
 
 CFLAGS			+= -DGIT_COMMIT="\"$(GIT_COMMIT)\"" -DGIT_BRANCH="\"$(GIT_BRANCH)\"" -DGIT_BRANCH_NUM="\"$(GIT_BRANCH_NUM)\""
-CFLAGS			+= -DBUILD_DATE="\"$(BUILD_DATE)\"" -DTARGET="\"$(TARGET)\""
+CFLAGS			+= -DBUILD_DATE="\"$(BUILD_DATE)\"" -DTARGET="\"$(TARGET)\"" -DVERSION="\"$(VERSION)\""
+