[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>
This commit is contained in:
Albert Kharisov 2021-04-19 19:30:25 +03:00 committed by GitHub
parent 202673aed1
commit aa20a78b0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 320 additions and 27 deletions

View file

@ -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() {

View file

@ -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);

View file

@ -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) {

View file

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

View file

@ -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
}

View file

@ -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

View file

@ -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)

View file

@ -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
}

View file

@ -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

View file

@ -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)

View file

@ -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");
}
}

View file

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

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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
}

View file

@ -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);
}
}
}

View file

@ -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
}

View file

@ -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
lib/version/version.c Normal file
View file

@ -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
lib/version/version.h Normal file
View file

@ -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

View file

@ -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)\""