mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-26 06:20:21 +00:00
Furi,FuriHal: various improvements (#2819)
* Lib: adjust default contrast for ERC displays * Furi: various improvements in check module * Format Sources * FurHal: ble early hardfault detection --------- Co-authored-by: hedger <hedger@users.noreply.github.com>
This commit is contained in:
parent
5d40193308
commit
6d9de25494
6 changed files with 218 additions and 33 deletions
10
applications/debug/crash_test/application.fam
Normal file
10
applications/debug/crash_test/application.fam
Normal file
|
@ -0,0 +1,10 @@
|
|||
App(
|
||||
appid="crash_test",
|
||||
name="Crash Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="crash_test_app",
|
||||
cdefines=["APP_CRASH_TEST"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Debug",
|
||||
)
|
128
applications/debug/crash_test/crash_test.c
Normal file
128
applications/debug/crash_test/crash_test.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
#define TAG "CrashTest"
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
} CrashTest;
|
||||
|
||||
typedef enum {
|
||||
CrashTestViewSubmenu,
|
||||
} CrashTestView;
|
||||
|
||||
typedef enum {
|
||||
CrashTestSubmenuCheck,
|
||||
CrashTestSubmenuCheckMessage,
|
||||
CrashTestSubmenuAssert,
|
||||
CrashTestSubmenuAssertMessage,
|
||||
CrashTestSubmenuCrash,
|
||||
CrashTestSubmenuHalt,
|
||||
} CrashTestSubmenu;
|
||||
|
||||
static void crash_test_submenu_callback(void* context, uint32_t index) {
|
||||
CrashTest* instance = (CrashTest*)context;
|
||||
UNUSED(instance);
|
||||
|
||||
switch(index) {
|
||||
case CrashTestSubmenuCheck:
|
||||
furi_check(false);
|
||||
break;
|
||||
case CrashTestSubmenuCheckMessage:
|
||||
furi_check(false, "Crash test: furi_check with message");
|
||||
break;
|
||||
case CrashTestSubmenuAssert:
|
||||
furi_assert(false);
|
||||
break;
|
||||
case CrashTestSubmenuAssertMessage:
|
||||
furi_assert(false, "Crash test: furi_assert with message");
|
||||
break;
|
||||
case CrashTestSubmenuCrash:
|
||||
furi_crash("Crash test: furi_crash");
|
||||
break;
|
||||
case CrashTestSubmenuHalt:
|
||||
furi_halt("Crash test: furi_halt");
|
||||
break;
|
||||
default:
|
||||
furi_crash("Programming error");
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t crash_test_exit_callback(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
CrashTest* crash_test_alloc() {
|
||||
CrashTest* instance = malloc(sizeof(CrashTest));
|
||||
|
||||
View* view = NULL;
|
||||
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
instance->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(instance->view_dispatcher);
|
||||
view_dispatcher_attach_to_gui(
|
||||
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Menu
|
||||
instance->submenu = submenu_alloc();
|
||||
view = submenu_get_view(instance->submenu);
|
||||
view_set_previous_callback(view, crash_test_exit_callback);
|
||||
view_dispatcher_add_view(instance->view_dispatcher, CrashTestViewSubmenu, view);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Check", CrashTestSubmenuCheck, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu,
|
||||
"Check with message",
|
||||
CrashTestSubmenuCheckMessage,
|
||||
crash_test_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Assert", CrashTestSubmenuAssert, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu,
|
||||
"Assert with message",
|
||||
CrashTestSubmenuAssertMessage,
|
||||
crash_test_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Crash", CrashTestSubmenuCrash, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Halt", CrashTestSubmenuHalt, crash_test_submenu_callback, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void crash_test_free(CrashTest* instance) {
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||
submenu_free(instance->submenu);
|
||||
|
||||
view_dispatcher_free(instance->view_dispatcher);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
int32_t crash_test_run(CrashTest* instance) {
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||
view_dispatcher_run(instance->view_dispatcher);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t crash_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
CrashTest* instance = crash_test_alloc();
|
||||
|
||||
int32_t ret = crash_test_run(instance);
|
||||
|
||||
crash_test_free(instance);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -21,8 +21,17 @@
|
|||
|
||||
#define FURI_HAL_BT_HARDFAULT_INFO_MAGIC 0x1170FD0F
|
||||
|
||||
FuriMutex* furi_hal_bt_core2_mtx = NULL;
|
||||
static FuriHalBtStack furi_hal_bt_stack = FuriHalBtStackUnknown;
|
||||
typedef struct {
|
||||
FuriMutex* core2_mtx;
|
||||
FuriTimer* hardfault_check_timer;
|
||||
FuriHalBtStack stack;
|
||||
} FuriHalBt;
|
||||
|
||||
static FuriHalBt furi_hal_bt = {
|
||||
.core2_mtx = NULL,
|
||||
.hardfault_check_timer = NULL,
|
||||
.stack = FuriHalBtStackUnknown,
|
||||
};
|
||||
|
||||
typedef void (*FuriHalBtProfileStart)(void);
|
||||
typedef void (*FuriHalBtProfileStop)(void);
|
||||
|
@ -79,6 +88,13 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = {
|
|||
};
|
||||
FuriHalBtProfileConfig* current_profile = NULL;
|
||||
|
||||
static void furi_hal_bt_hardfault_check(void* context) {
|
||||
UNUSED(context);
|
||||
if(furi_hal_bt_get_hardfault_info()) {
|
||||
furi_crash("ST(R) Copro(R) HardFault");
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_bt_init() {
|
||||
furi_hal_bus_enable(FuriHalBusHSEM);
|
||||
furi_hal_bus_enable(FuriHalBusIPCC);
|
||||
|
@ -86,9 +102,15 @@ void furi_hal_bt_init() {
|
|||
furi_hal_bus_enable(FuriHalBusPKA);
|
||||
furi_hal_bus_enable(FuriHalBusCRC);
|
||||
|
||||
if(!furi_hal_bt_core2_mtx) {
|
||||
furi_hal_bt_core2_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
furi_assert(furi_hal_bt_core2_mtx);
|
||||
if(!furi_hal_bt.core2_mtx) {
|
||||
furi_hal_bt.core2_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
furi_assert(furi_hal_bt.core2_mtx);
|
||||
}
|
||||
|
||||
if(!furi_hal_bt.hardfault_check_timer) {
|
||||
furi_hal_bt.hardfault_check_timer =
|
||||
furi_timer_alloc(furi_hal_bt_hardfault_check, FuriTimerTypePeriodic, NULL);
|
||||
furi_timer_start(furi_hal_bt.hardfault_check_timer, 5000);
|
||||
}
|
||||
|
||||
// Explicitly tell that we are in charge of CLK48 domain
|
||||
|
@ -99,13 +121,13 @@ void furi_hal_bt_init() {
|
|||
}
|
||||
|
||||
void furi_hal_bt_lock_core2() {
|
||||
furi_assert(furi_hal_bt_core2_mtx);
|
||||
furi_check(furi_mutex_acquire(furi_hal_bt_core2_mtx, FuriWaitForever) == FuriStatusOk);
|
||||
furi_assert(furi_hal_bt.core2_mtx);
|
||||
furi_check(furi_mutex_acquire(furi_hal_bt.core2_mtx, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void furi_hal_bt_unlock_core2() {
|
||||
furi_assert(furi_hal_bt_core2_mtx);
|
||||
furi_check(furi_mutex_release(furi_hal_bt_core2_mtx) == FuriStatusOk);
|
||||
furi_assert(furi_hal_bt.core2_mtx);
|
||||
furi_check(furi_mutex_release(furi_hal_bt.core2_mtx) == FuriStatusOk);
|
||||
}
|
||||
|
||||
static bool furi_hal_bt_radio_stack_is_supported(const BleGlueC2Info* info) {
|
||||
|
@ -113,26 +135,26 @@ static bool furi_hal_bt_radio_stack_is_supported(const BleGlueC2Info* info) {
|
|||
if(info->StackType == INFO_STACK_TYPE_BLE_LIGHT) {
|
||||
if(info->VersionMajor >= FURI_HAL_BT_STACK_VERSION_MAJOR &&
|
||||
info->VersionMinor >= FURI_HAL_BT_STACK_VERSION_MINOR) {
|
||||
furi_hal_bt_stack = FuriHalBtStackLight;
|
||||
furi_hal_bt.stack = FuriHalBtStackLight;
|
||||
supported = true;
|
||||
}
|
||||
} else if(info->StackType == INFO_STACK_TYPE_BLE_FULL) {
|
||||
if(info->VersionMajor >= FURI_HAL_BT_STACK_VERSION_MAJOR &&
|
||||
info->VersionMinor >= FURI_HAL_BT_STACK_VERSION_MINOR) {
|
||||
furi_hal_bt_stack = FuriHalBtStackFull;
|
||||
furi_hal_bt.stack = FuriHalBtStackFull;
|
||||
supported = true;
|
||||
}
|
||||
} else {
|
||||
furi_hal_bt_stack = FuriHalBtStackUnknown;
|
||||
furi_hal_bt.stack = FuriHalBtStackUnknown;
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
bool furi_hal_bt_start_radio_stack() {
|
||||
bool res = false;
|
||||
furi_assert(furi_hal_bt_core2_mtx);
|
||||
furi_assert(furi_hal_bt.core2_mtx);
|
||||
|
||||
furi_mutex_acquire(furi_hal_bt_core2_mtx, FuriWaitForever);
|
||||
furi_mutex_acquire(furi_hal_bt.core2_mtx, FuriWaitForever);
|
||||
|
||||
// Explicitly tell that we are in charge of CLK48 domain
|
||||
furi_check(LL_HSEM_1StepLock(HSEM, CFG_HW_CLK48_CONFIG_SEMID) == 0);
|
||||
|
@ -166,17 +188,17 @@ bool furi_hal_bt_start_radio_stack() {
|
|||
}
|
||||
res = true;
|
||||
} while(false);
|
||||
furi_mutex_release(furi_hal_bt_core2_mtx);
|
||||
furi_mutex_release(furi_hal_bt.core2_mtx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
FuriHalBtStack furi_hal_bt_get_radio_stack() {
|
||||
return furi_hal_bt_stack;
|
||||
return furi_hal_bt.stack;
|
||||
}
|
||||
|
||||
bool furi_hal_bt_is_ble_gatt_gap_supported() {
|
||||
if(furi_hal_bt_stack == FuriHalBtStackLight || furi_hal_bt_stack == FuriHalBtStackFull) {
|
||||
if(furi_hal_bt.stack == FuriHalBtStackLight || furi_hal_bt.stack == FuriHalBtStackFull) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -184,7 +206,7 @@ bool furi_hal_bt_is_ble_gatt_gap_supported() {
|
|||
}
|
||||
|
||||
bool furi_hal_bt_is_testing_supported() {
|
||||
if(furi_hal_bt_stack == FuriHalBtStackFull) {
|
||||
if(furi_hal_bt.stack == FuriHalBtStackFull) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -166,7 +166,11 @@ FURI_NORETURN void __furi_crash() {
|
|||
RESTORE_REGISTERS_AND_HALT_MCU(true);
|
||||
#ifndef FURI_DEBUG
|
||||
} else {
|
||||
furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message);
|
||||
uint32_t ptr = (uint32_t)__furi_check_message;
|
||||
if(ptr < FLASH_BASE || ptr > (FLASH_BASE + FLASH_SIZE)) {
|
||||
ptr = (uint32_t) "Check serial logs";
|
||||
}
|
||||
furi_hal_rtc_set_fault_data(ptr);
|
||||
furi_hal_console_puts("\r\nRebooting system.\r\n");
|
||||
furi_hal_console_puts("\033[0m\r\n");
|
||||
furi_hal_power_reset();
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <m-core.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#define FURI_NORETURN [[noreturn]]
|
||||
|
@ -48,28 +50,47 @@ FURI_NORETURN void __furi_halt();
|
|||
} while(0)
|
||||
|
||||
/** Check condition and crash if check failed */
|
||||
#define furi_check(__e) \
|
||||
do { \
|
||||
if(!(__e)) { \
|
||||
furi_crash(__FURI_CHECK_MESSAGE_FLAG); \
|
||||
} \
|
||||
#define __furi_check(__e, __m) \
|
||||
do { \
|
||||
if(!(__e)) { \
|
||||
furi_crash(__m); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/** Check condition and crash if failed
|
||||
*
|
||||
* @param condition to check
|
||||
* @param optional message
|
||||
*/
|
||||
#define furi_check(...) \
|
||||
M_APPLY(__furi_check, M_DEFAULT_ARGS(2, (__FURI_CHECK_MESSAGE_FLAG), __VA_ARGS__))
|
||||
|
||||
/** Only in debug build: Assert condition and crash if assert failed */
|
||||
#ifdef FURI_DEBUG
|
||||
#define furi_assert(__e) \
|
||||
do { \
|
||||
if(!(__e)) { \
|
||||
furi_crash(__FURI_ASSERT_MESSAGE_FLAG); \
|
||||
} \
|
||||
#define __furi_assert(__e, __m) \
|
||||
do { \
|
||||
if(!(__e)) { \
|
||||
furi_crash(__m); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define furi_assert(__e) \
|
||||
do { \
|
||||
((void)(__e)); \
|
||||
#define __furi_assert(__e, __m) \
|
||||
do { \
|
||||
((void)(__e)); \
|
||||
((void)(__m)); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/** Assert condition and crash if failed
|
||||
*
|
||||
* @warning only will do check if firmware compiled in debug mode
|
||||
*
|
||||
* @param condition to check
|
||||
* @param optional message
|
||||
*/
|
||||
#define furi_assert(...) \
|
||||
M_APPLY(__furi_assert, M_DEFAULT_ARGS(2, (__FURI_ASSERT_MESSAGE_FLAG), __VA_ARGS__))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define CONTRAST_ERC 32
|
||||
#define CONTRAST_ERC 31
|
||||
#define CONTRAST_MGG 31
|
||||
|
||||
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
|
|
Loading…
Reference in a new issue