[FL-2733] multitarget support for fbt (#2209)

* First part of multitarget porting
* Delete firmware/targets/f7/Inc directory
* Delete firmware/targets/f7/Src directory
* gpio: cli fixes; about: using version from HAL
* sdk: path fixes
* gui: include fixes
* applications: more include fixes
* gpio: ported to new apis
* hal: introduced furi_hal_target_hw.h; libs: added one_wire
* hal: f18 target
* github: also build f18 by default
* typo fix
* fbt: removed extra checks on app list
* api: explicitly bundling select mlib headers with sdk
* hal: f18: changed INPUT_DEBOUNCE_TICKS to match f7
* cleaned up commented out code
* docs: added info on hw targets
* docs: targets: formatting fixes
* f18: fixed link error
* f18: fixed API version to match f7
* docs: hardware: minor wording fixes
* faploader: added fw target check
* docs: typo fixes
* github: not building komi target by default
* fbt: support for `targets` field for built-in apps
* github: reworked build flow to exclude app_set; fbt: removed komi-specific appset; added additional target buildset check
* github: fixed build; nfc: fixed pvs warnings
* attempt to fix target id
* f7, f18: removed certain HAL function from public API
* apps: debug: enabled bt_debug_app for f18
* Targets: backport input pins configuration routine from F7 to F18

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
hedger
2023-02-07 19:33:05 +03:00
committed by GitHub
parent 1eda913367
commit 224d0aefe4
152 changed files with 4140 additions and 495 deletions

View File

@@ -0,0 +1,41 @@
#include <furi.h>
#include <furi_hal.h>
#include <flipper.h>
#include <alt_boot.h>
#include <u8g2_glue.h>
#include <assets_icons.h>
void flipper_boot_dfu_show_splash() {
// Initialize
furi_hal_compress_icon_init();
u8g2_t* fb = malloc(sizeof(u8g2_t));
memset(fb, 0, sizeof(u8g2_t));
u8g2_Setup_st756x_flipper(fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
u8g2_InitDisplay(fb);
u8g2_SetDrawColor(fb, 0x01);
uint8_t* splash_data = NULL;
furi_hal_compress_icon_decode(icon_get_data(&I_DFU_128x50), &splash_data);
u8g2_DrawXBM(fb, 0, 64 - 50, 128, 50, splash_data);
u8g2_SetFont(fb, u8g2_font_helvB08_tr);
u8g2_DrawStr(fb, 2, 8, "Update & Recovery Mode");
u8g2_DrawStr(fb, 2, 21, "DFU Started");
u8g2_SetPowerSave(fb, 0);
u8g2_SendBuffer(fb);
}
void flipper_boot_dfu_exec() {
// Show DFU splashscreen
flipper_boot_dfu_show_splash();
// Errata 2.2.9, Flash OPTVERR flag is always set after system reset
WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR);
// Cleanup before jumping to DFU
furi_hal_deinit_early();
// Remap memory to system bootloader
LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SYSTEMFLASH);
// Jump
furi_hal_switch(0x0);
}

View File

@@ -0,0 +1,74 @@
#include <furi.h>
#include <furi_hal.h>
#include <flipper.h>
#include <alt_boot.h>
#include <semphr.h>
#include <update_util/update_operation.h>
#define TAG "Main"
int32_t init_task(void* context) {
UNUSED(context);
// Flipper FURI HAL
furi_hal_init();
// Init flipper
flipper_init();
return 0;
}
int main() {
// Initialize FURI layer
furi_init();
// Flipper critical FURI HAL
furi_hal_init_early();
FuriThread* main_thread = furi_thread_alloc_ex("Init", 4096, init_task, NULL);
#ifdef FURI_RAM_EXEC
furi_thread_start(main_thread);
#else
furi_hal_light_sequence("RGB");
// Delay is for button sampling
furi_delay_ms(100);
FuriHalRtcBootMode boot_mode = furi_hal_rtc_get_boot_mode();
if(boot_mode == FuriHalRtcBootModeDfu || !furi_hal_gpio_read(&gpio_button_left)) {
furi_hal_light_sequence("rgb WB");
furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal);
flipper_boot_dfu_exec();
furi_hal_power_reset();
} else if(boot_mode == FuriHalRtcBootModeUpdate) {
furi_hal_light_sequence("rgb BR");
flipper_boot_update_exec();
// if things go nice, we shouldn't reach this point.
// But if we do, abandon to avoid bootloops
furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal);
furi_hal_power_reset();
} else if(!furi_hal_gpio_read(&gpio_button_up)) {
furi_hal_light_sequence("rgb WR");
flipper_boot_recovery_exec();
furi_hal_power_reset();
} else {
furi_hal_light_sequence("rgb G");
furi_thread_start(main_thread);
}
#endif
// Run Kernel
furi_run();
furi_crash("Kernel is Dead");
}
void Error_Handler(void) {
furi_crash("ErrorHandler");
}
void abort() {
furi_crash("AbortHandler");
}

View File

@@ -0,0 +1,54 @@
#include <furi.h>
#include <furi_hal.h>
#include <flipper.h>
#include <alt_boot.h>
#include <u8g2_glue.h>
#include <assets_icons.h>
#define COUNTER_VALUE (100U)
static void flipper_boot_recovery_draw_splash(u8g2_t* fb, size_t progress) {
u8g2_ClearBuffer(fb);
u8g2_SetDrawColor(fb, 0x01);
u8g2_SetFont(fb, u8g2_font_helvB08_tr);
u8g2_DrawStr(fb, 2, 8, "PIN and Factory Reset");
u8g2_SetFont(fb, u8g2_font_haxrcorp4089_tr);
u8g2_DrawStr(fb, 2, 21, "Hold Right to confirm");
u8g2_DrawStr(fb, 2, 31, "Press Down to cancel");
if(progress < COUNTER_VALUE) {
size_t width = progress / (COUNTER_VALUE / 100);
u8g2_DrawBox(fb, 14 + (50 - width / 2), 54, width, 3);
}
u8g2_SetPowerSave(fb, 0);
u8g2_SendBuffer(fb);
}
void flipper_boot_recovery_exec() {
u8g2_t* fb = malloc(sizeof(u8g2_t));
u8g2_Setup_st756x_flipper(fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
u8g2_InitDisplay(fb);
size_t counter = COUNTER_VALUE;
while(counter) {
if(!furi_hal_gpio_read(&gpio_button_down)) {
break;
}
if(!furi_hal_gpio_read(&gpio_button_right)) {
counter--;
} else {
counter = COUNTER_VALUE;
}
flipper_boot_recovery_draw_splash(fb, counter);
}
if(!counter) {
furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset);
furi_hal_rtc_set_pin_fails(0);
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
}
}

View File

@@ -0,0 +1,97 @@
#include "stm32wbxx.h"
/*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */
/* #define VECT_TAB_SRAM */
#ifndef VECT_TAB_OFFSET
#define VECT_TAB_OFFSET \
0x0 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
#endif
#define VECT_TAB_BASE_ADDRESS \
SRAM1_BASE /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
/* The SystemCoreClock variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 4000000UL; /*CPU1: M4 on MSI clock after startup (4MHz)*/
const uint32_t AHBPrescTable[16UL] =
{1UL, 3UL, 5UL, 1UL, 1UL, 6UL, 10UL, 32UL, 2UL, 4UL, 8UL, 16UL, 64UL, 128UL, 256UL, 512UL};
const uint32_t APBPrescTable[8UL] = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
const uint32_t MSIRangeTable[16UL] = {
100000UL,
200000UL,
400000UL,
800000UL,
1000000UL,
2000000UL,
4000000UL,
8000000UL,
16000000UL,
24000000UL,
32000000UL,
48000000UL,
0UL,
0UL,
0UL,
0UL}; /* 0UL values are incorrect cases */
/**
* @brief Setup the microcontroller system.
* @param None
* @retval None
*/
void SystemInit(void) {
/* Configure the Vector Table location add offset address ------------------*/
#if defined(VECT_TAB_SRAM) && defined(VECT_TAB_BASE_ADDRESS)
/* program in SRAMx */
SCB->VTOR = VECT_TAB_BASE_ADDRESS |
VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAMx for CPU1 */
#else /* program in FLASH */
SCB->VTOR = VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
/* FPU settings ------------------------------------------------------------*/
#if(__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |=
((3UL << (10UL * 2UL)) | (3UL << (11UL * 2UL))); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set MSION bit */
RCC->CR |= RCC_CR_MSION;
/* Reset CFGR register */
RCC->CFGR = 0x00070000U;
/* Reset PLLSAI1ON, PLLON, HSECSSON, HSEON, HSION, and MSIPLLON bits */
RCC->CR &= (uint32_t)0xFAF6FEFBU;
/*!< Reset LSI1 and LSI2 bits */
RCC->CSR &= (uint32_t)0xFFFFFFFAU;
/*!< Reset HSI48ON bit */
RCC->CRRCR &= (uint32_t)0xFFFFFFFEU;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x22041000U;
#if defined(STM32WB55xx) || defined(STM32WB5Mxx)
/* Reset PLLSAI1CFGR register */
RCC->PLLSAI1CFGR = 0x22041000U;
#endif
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Disable all interrupts */
RCC->CIER = 0x00000000;
}

View File

@@ -0,0 +1,202 @@
#include <furi.h>
#include <furi_hal.h>
#include <flipper.h>
#include <alt_boot.h>
#include <fatfs.h>
#include <flipper_format/flipper_format.h>
#include <update_util/update_manifest.h>
#include <update_util/update_operation.h>
#include <toolbox/path.h>
#include <toolbox/crc32_calc.h>
#define UPDATE_POINTER_FILE_PATH "/" UPDATE_MANIFEST_POINTER_FILE_NAME
static FATFS* pfs = NULL;
#define CHECK_FRESULT(result) \
{ \
if((result) != FR_OK) { \
return false; \
} \
}
static bool flipper_update_mount_sd() {
for(int i = 0; i < BSP_SD_MaxMountRetryCount(); ++i) {
if(BSP_SD_Init((i % 2) == 0) != MSD_OK) {
/* Next attempt will be without card reset, let it settle */
furi_delay_ms(1000);
continue;
}
if(f_mount(pfs, "/", 1) == FR_OK) {
return true;
}
}
return false;
}
static bool flipper_update_init() {
furi_hal_clock_init();
furi_hal_rtc_init();
furi_hal_interrupt_init();
furi_hal_spi_config_init();
MX_FATFS_Init();
if(!hal_sd_detect()) {
return false;
}
pfs = malloc(sizeof(FATFS));
return flipper_update_mount_sd();
}
static bool flipper_update_load_stage(const FuriString* work_dir, UpdateManifest* manifest) {
FIL file;
FILINFO stat;
FuriString* loader_img_path;
loader_img_path = furi_string_alloc_set(work_dir);
path_append(loader_img_path, furi_string_get_cstr(manifest->staged_loader_file));
if((f_stat(furi_string_get_cstr(loader_img_path), &stat) != FR_OK) ||
(f_open(&file, furi_string_get_cstr(loader_img_path), FA_OPEN_EXISTING | FA_READ) !=
FR_OK)) {
furi_string_free(loader_img_path);
return false;
}
furi_string_free(loader_img_path);
void* img = malloc(stat.fsize);
uint32_t bytes_read = 0;
const uint16_t MAX_READ = 0xFFFF;
uint32_t crc = 0;
do {
uint16_t size_read = 0;
if(f_read(&file, img + bytes_read, MAX_READ, &size_read) != FR_OK) {
break;
}
crc = crc32_calc_buffer(crc, img + bytes_read, size_read);
bytes_read += size_read;
} while(bytes_read == MAX_READ);
do {
if((bytes_read != stat.fsize) || (crc != manifest->staged_loader_crc)) {
break;
}
/* Point of no return. Literally
*
* NB: we MUST disable IRQ, otherwise handlers from flash
* will change global variables (like tick count)
* that are located in .data. And we move staged loader
* to the same memory region. So, IRQ handlers will mess up
* memmove'd .text section and ruin your day.
* We don't want that to happen.
*/
__disable_irq();
memmove((void*)(SRAM1_BASE), img, stat.fsize);
LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SRAM);
furi_hal_switch((void*)SRAM1_BASE);
return true;
} while(false);
free(img);
return false;
}
static bool flipper_update_get_manifest_path(FuriString* out_path) {
FIL file;
FILINFO stat;
uint16_t size_read = 0;
char manifest_name_buf[UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN] = {0};
furi_string_reset(out_path);
CHECK_FRESULT(f_stat(UPDATE_POINTER_FILE_PATH, &stat));
CHECK_FRESULT(f_open(&file, UPDATE_POINTER_FILE_PATH, FA_OPEN_EXISTING | FA_READ));
do {
if(f_read(&file, manifest_name_buf, UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN, &size_read) !=
FR_OK) {
break;
}
if((size_read == 0) || (size_read == UPDATE_OPERATION_MAX_MANIFEST_PATH_LEN)) {
break;
}
furi_string_set(out_path, manifest_name_buf);
furi_string_right(out_path, strlen(STORAGE_EXT_PATH_PREFIX));
} while(0);
f_close(&file);
return !furi_string_empty(out_path);
}
static UpdateManifest* flipper_update_process_manifest(const FuriString* manifest_path) {
FIL file;
FILINFO stat;
CHECK_FRESULT(f_stat(furi_string_get_cstr(manifest_path), &stat));
CHECK_FRESULT(f_open(&file, furi_string_get_cstr(manifest_path), FA_OPEN_EXISTING | FA_READ));
uint8_t* manifest_data = malloc(stat.fsize);
uint32_t bytes_read = 0;
const uint16_t MAX_READ = 0xFFFF;
do {
uint16_t size_read = 0;
if(f_read(&file, manifest_data + bytes_read, MAX_READ, &size_read) != FR_OK) { //-V769
break;
}
bytes_read += size_read;
} while(bytes_read == MAX_READ);
UpdateManifest* manifest = NULL;
do {
if(bytes_read != stat.fsize) {
break;
}
manifest = update_manifest_alloc();
if(!update_manifest_init_mem(manifest, manifest_data, bytes_read)) {
update_manifest_free(manifest);
manifest = NULL;
}
} while(false);
f_close(&file);
free(manifest_data);
return manifest;
}
void flipper_boot_update_exec() {
if(!flipper_update_init()) {
return;
}
FuriString* work_dir = furi_string_alloc();
FuriString* manifest_path = furi_string_alloc();
do {
if(!flipper_update_get_manifest_path(manifest_path)) {
break;
}
UpdateManifest* manifest = flipper_update_process_manifest(manifest_path);
if(!manifest) {
break;
}
path_extract_dirname(furi_string_get_cstr(manifest_path), work_dir);
if(!flipper_update_load_stage(work_dir, manifest)) {
update_manifest_free(manifest);
}
} while(false);
furi_string_free(manifest_path);
furi_string_free(work_dir);
free(pfs);
}