Furi: cleanup crash use (#3175)

* Furi: optional message in furi_crash and furi_halt
* Consistent furi_crash use
* UnitTests: crash instead of assert
* furi: check: fixed macro for default arg
* unit_tests: fixed crashes everywhere
* lib: infrared: fixed PVS warnings
* furi: eliminated __FURI_ASSERT_MESSAGE_FLAG
* Furi: update check.h docs
* Furi: add check.h usage note
* Docs: grammar

---------

Co-authored-by: hedger <hedger@nanode.su>
This commit is contained in:
あく 2023-10-31 19:40:32 +09:00 committed by GitHub
parent c8180747db
commit 9af81ce8d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 159 additions and 107 deletions

View File

@ -28,7 +28,7 @@ void bt_test_alloc() {
} }
void bt_test_free() { void bt_test_free() {
furi_assert(bt_test); furi_check(bt_test);
free(bt_test->nvm_ram_buff_ref); free(bt_test->nvm_ram_buff_ref);
free(bt_test->nvm_ram_buff_dut); free(bt_test->nvm_ram_buff_dut);
bt_keys_storage_free(bt_test->bt_keys_storage); bt_keys_storage_free(bt_test->bt_keys_storage);
@ -89,7 +89,7 @@ static void bt_test_keys_remove_test_file() {
} }
MU_TEST(bt_test_keys_storage_serial_profile) { MU_TEST(bt_test_keys_storage_serial_profile) {
furi_assert(bt_test); furi_check(bt_test);
bt_test_keys_remove_test_file(); bt_test_keys_remove_test_file();
bt_test_keys_storage_profile(); bt_test_keys_storage_profile();

View File

@ -27,7 +27,7 @@ static void infrared_test_alloc() {
} }
static void infrared_test_free() { static void infrared_test_free() {
furi_assert(test); furi_check(test);
infrared_free_decoder(test->decoder_handler); infrared_free_decoder(test->decoder_handler);
infrared_free_encoder(test->encoder_handler); infrared_free_encoder(test->encoder_handler);
flipper_format_free(test->ff); flipper_format_free(test->ff);

View File

@ -34,7 +34,7 @@ static void nfc_test_alloc() {
} }
static void nfc_test_free() { static void nfc_test_free() {
furi_assert(nfc_test); furi_check(nfc_test);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);
free(nfc_test); free(nfc_test);

View File

@ -122,7 +122,7 @@ Nfc* nfc_alloc() {
} }
void nfc_free(Nfc* instance) { void nfc_free(Nfc* instance) {
furi_assert(instance); furi_check(instance);
free(instance); free(instance);
} }
@ -165,9 +165,9 @@ NfcError nfc_iso14443a_listener_set_col_res_data(
uint8_t uid_len, uint8_t uid_len,
uint8_t* atqa, uint8_t* atqa,
uint8_t sak) { uint8_t sak) {
furi_assert(instance); furi_check(instance);
furi_assert(uid); furi_check(uid);
furi_assert(atqa); furi_check(atqa);
nfc_prepare_col_res_data(instance, uid, uid_len, atqa, sak); nfc_prepare_col_res_data(instance, uid, uid_len, atqa, sak);
@ -176,7 +176,7 @@ NfcError nfc_iso14443a_listener_set_col_res_data(
static int32_t nfc_worker_poller(void* context) { static int32_t nfc_worker_poller(void* context) {
Nfc* instance = context; Nfc* instance = context;
furi_assert(instance->callback); furi_check(instance->callback);
instance->state = NfcStateReady; instance->state = NfcStateReady;
NfcCommand command = NfcCommandContinue; NfcCommand command = NfcCommandContinue;
@ -196,7 +196,7 @@ static int32_t nfc_worker_poller(void* context) {
} }
static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, uint16_t rx_bits) { static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, uint16_t rx_bits) {
furi_assert(instance->col_res_status != Iso14443_3aColResStatusDone); furi_check(instance->col_res_status != Iso14443_3aColResStatusDone);
BitBuffer* tx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE); BitBuffer* tx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
bool processed = false; bool processed = false;
@ -255,7 +255,7 @@ static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, ui
static int32_t nfc_worker_listener(void* context) { static int32_t nfc_worker_listener(void* context) {
Nfc* instance = context; Nfc* instance = context;
furi_assert(instance->callback); furi_check(instance->callback);
NfcMessage message = {}; NfcMessage message = {};
@ -295,17 +295,17 @@ static int32_t nfc_worker_listener(void* context) {
} }
void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) { void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) {
furi_assert(instance); furi_check(instance);
furi_assert(instance->worker_thread == NULL); furi_check(instance->worker_thread == NULL);
if(instance->mode == NfcModeListener) { if(instance->mode == NfcModeListener) {
furi_assert(listener_queue == NULL); furi_check(listener_queue == NULL);
// Check that poller didn't start // Check that poller didn't start
furi_assert(poller_queue == NULL); furi_check(poller_queue == NULL);
} else { } else {
furi_assert(poller_queue == NULL); furi_check(poller_queue == NULL);
// Check that poller is started after listener // Check that poller is started after listener
furi_assert(listener_queue); furi_check(listener_queue);
} }
instance->callback = callback; instance->callback = callback;
@ -334,8 +334,8 @@ void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) {
} }
void nfc_stop(Nfc* instance) { void nfc_stop(Nfc* instance) {
furi_assert(instance); furi_check(instance);
furi_assert(instance->worker_thread); furi_check(instance->worker_thread);
if(instance->mode == NfcModeListener) { if(instance->mode == NfcModeListener) {
NfcMessage message = {.type = NfcMessageTypeAbort}; NfcMessage message = {.type = NfcMessageTypeAbort};
@ -361,10 +361,10 @@ void nfc_stop(Nfc* instance) {
// Called from worker thread // Called from worker thread
NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) { NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) {
furi_assert(instance); furi_check(instance);
furi_assert(poller_queue); furi_check(poller_queue);
furi_assert(listener_queue); furi_check(listener_queue);
furi_assert(tx_buffer); furi_check(tx_buffer);
NfcMessage message = {}; NfcMessage message = {};
message.type = NfcMessageTypeTx; message.type = NfcMessageTypeTx;
@ -382,11 +382,11 @@ NfcError nfc_iso14443a_listener_tx_custom_parity(Nfc* instance, const BitBuffer*
NfcError NfcError
nfc_poller_trx(Nfc* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer, uint32_t fwt) { nfc_poller_trx(Nfc* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer, uint32_t fwt) {
furi_assert(instance); furi_check(instance);
furi_assert(tx_buffer); furi_check(tx_buffer);
furi_assert(rx_buffer); furi_check(rx_buffer);
furi_assert(poller_queue); furi_check(poller_queue);
furi_assert(listener_queue); furi_check(listener_queue);
UNUSED(fwt); UNUSED(fwt);
NfcError error = NfcErrorNone; NfcError error = NfcErrorNone;
@ -396,7 +396,7 @@ NfcError
message.data.data_bits = bit_buffer_get_size(tx_buffer); message.data.data_bits = bit_buffer_get_size(tx_buffer);
bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer)); bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer));
// Tx // Tx
furi_assert(furi_message_queue_put(listener_queue, &message, FuriWaitForever) == FuriStatusOk); furi_check(furi_message_queue_put(listener_queue, &message, FuriWaitForever) == FuriStatusOk);
// Rx // Rx
FuriStatus status = furi_message_queue_get(poller_queue, &message, 50); FuriStatus status = furi_message_queue_get(poller_queue, &message, 50);

View File

@ -48,7 +48,7 @@ bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent
} else if(edit_mode == InfraredEditModeDelete) { } else if(edit_mode == InfraredEditModeDelete) {
scene_manager_next_scene(scene_manager, InfraredSceneEditDelete); scene_manager_next_scene(scene_manager, InfraredSceneEditDelete);
} else { } else {
furi_assert(0); furi_crash();
} }
consumed = true; consumed = true;
} }

View File

@ -60,7 +60,7 @@ void infrared_scene_edit_delete_on_enter(void* context) {
infrared_remote_get_name(remote), infrared_remote_get_name(remote),
infrared_remote_get_signal_count(remote)); infrared_remote_get_signal_count(remote));
} else { } else {
furi_assert(0); furi_crash();
} }
dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter); dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter);
@ -101,7 +101,7 @@ bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event)
success = infrared_remote_remove(remote); success = infrared_remote_remove(remote);
app_state->current_button_index = InfraredButtonIndexNone; app_state->current_button_index = InfraredButtonIndexNone;
} else { } else {
furi_crash(NULL); furi_crash();
} }
if(success) { if(success) {

View File

@ -33,7 +33,7 @@ bool infrared_scene_edit_delete_done_on_event(void* context, SceneManagerEvent e
view_dispatcher_stop(infrared->view_dispatcher); view_dispatcher_stop(infrared->view_dispatcher);
} }
} else { } else {
furi_assert(0); furi_crash();
} }
consumed = true; consumed = true;
} }

View File

@ -42,7 +42,7 @@ void infrared_scene_edit_rename_on_enter(void* context) {
furi_string_free(folder_path); furi_string_free(folder_path);
} else { } else {
furi_crash(NULL); furi_crash();
} }
text_input_set_result_callback( text_input_set_result_callback(
@ -81,7 +81,7 @@ bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event)
} else if(edit_target == InfraredEditTargetRemote) { } else if(edit_target == InfraredEditTargetRemote) {
success = infrared_rename_current_remote(infrared, infrared->text_store[0]); success = infrared_rename_current_remote(infrared, infrared->text_store[0]);
} else { } else {
furi_crash(NULL); furi_crash();
} }
if(success) { if(success) {

View File

@ -456,7 +456,7 @@ void animation_manager_unload_and_stall_animation(AnimationManager* animation_ma
} }
furi_timer_stop(animation_manager->idle_animation_timer); furi_timer_stop(animation_manager->idle_animation_timer);
} else { } else {
furi_assert(0); furi_crash();
} }
FURI_LOG_I( FURI_LOG_I(
@ -528,7 +528,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m
} }
} else { } else {
/* Unknown state is an error. But not in release version.*/ /* Unknown state is an error. But not in release version.*/
furi_assert(0); furi_crash();
} }
/* if can't restore previous animation - select new */ /* if can't restore previous animation - select new */
@ -564,7 +564,7 @@ static void animation_manager_switch_to_one_shot_view(AnimationManager* animatio
} else if(stats.level == 2) { } else if(stats.level == 2) {
one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup2_128x64); one_shot_view_start_animation(animation_manager->one_shot_view, &A_Levelup2_128x64);
} else { } else {
furi_assert(0); furi_crash();
} }
} }

View File

@ -78,7 +78,7 @@ static bool desktop_view_pin_input_input(InputEvent* event, void* context) {
} }
break; break;
default: default:
furi_assert(0); furi_crash();
break; break;
} }
} }
@ -129,7 +129,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu
canvas_draw_icon_ex(canvas, x + 2, y + 3, &I_Pin_arrow_up_7x9, IconRotation90); canvas_draw_icon_ex(canvas, x + 2, y + 3, &I_Pin_arrow_up_7x9, IconRotation90);
break; break;
default: default:
furi_assert(0); furi_crash();
break; break;
} }
} }

View File

@ -135,7 +135,7 @@ void canvas_set_font(Canvas* canvas, Font font) {
} else if(font == FontBigNumbers) { } else if(font == FontBigNumbers) {
u8g2_SetFont(&canvas->fb, u8g2_font_profont22_tn); u8g2_SetFont(&canvas->fb, u8g2_font_profont22_tn);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -175,7 +175,7 @@ void canvas_draw_str_aligned(
x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2); x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2);
break; break;
default: default:
furi_crash(NULL); furi_crash();
break; break;
} }
@ -189,7 +189,7 @@ void canvas_draw_str_aligned(
y += (u8g2_GetAscent(&canvas->fb) / 2); y += (u8g2_GetAscent(&canvas->fb) / 2);
break; break;
default: default:
furi_crash(NULL); furi_crash();
break; break;
} }
@ -530,7 +530,7 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) {
rotate_cb = U8G2_R1; rotate_cb = U8G2_R1;
break; break;
default: default:
furi_assert(0); furi_crash();
} }
if(need_swap) FURI_SWAP(canvas->width, canvas->height); if(need_swap) FURI_SWAP(canvas->width, canvas->height);

View File

@ -232,7 +232,7 @@ static size_t
} else if(horizontal == AlignRight) { } else if(horizontal == AlignRight) {
px_left = x; px_left = x;
} else { } else {
furi_assert(0); furi_crash();
} }
if(len_px > px_left) { if(len_px > px_left) {

View File

@ -79,7 +79,7 @@ static uint8_t byte_input_get_row_size(uint8_t row_index) {
row_size = COUNT_OF(keyboard_keys_row_2); row_size = COUNT_OF(keyboard_keys_row_2);
break; break;
default: default:
furi_crash(NULL); furi_crash();
} }
return row_size; return row_size;
@ -102,7 +102,7 @@ static const ByteInputKey* byte_input_get_row(uint8_t row_index) {
row = keyboard_keys_row_2; row = keyboard_keys_row_2;
break; break;
default: default:
furi_crash(NULL); furi_crash();
} }
return row; return row;

View File

@ -98,7 +98,7 @@ void popup_start_timer(void* context) {
if(timer_period == 0) timer_period = 1; if(timer_period == 0) timer_period = 1;
if(furi_timer_start(popup->timer, timer_period) != FuriStatusOk) { if(furi_timer_start(popup->timer, timer_period) != FuriStatusOk) {
furi_assert(0); furi_crash();
}; };
} }
} }

View File

@ -101,7 +101,7 @@ static uint8_t get_row_size(uint8_t row_index) {
row_size = COUNT_OF(keyboard_keys_row_3); row_size = COUNT_OF(keyboard_keys_row_3);
break; break;
default: default:
furi_crash(NULL); furi_crash();
} }
return row_size; return row_size;
@ -121,7 +121,7 @@ static const TextInputKey* get_row(uint8_t row_index) {
row = keyboard_keys_row_3; row = keyboard_keys_row_3;
break; break;
default: default:
furi_crash(NULL); furi_crash();
} }
return row; return row;

View File

@ -82,7 +82,7 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) {
model->data = malloc(size); model->data = malloc(size);
view->model = model; view->model = model;
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -99,7 +99,7 @@ void view_free_model(View* view) {
free(model); free(model);
view->model = NULL; view->model = NULL;
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }

View File

@ -207,7 +207,7 @@ void view_dispatcher_attach_to_gui(
} else if(type == ViewDispatcherTypeFullscreen) { } else if(type == ViewDispatcherTypeFullscreen) {
gui_add_view_port(gui, view_dispatcher->view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_dispatcher->view_port, GuiLayerFullscreen);
} else { } else {
furi_check(NULL); furi_crash();
} }
view_dispatcher->gui = gui; view_dispatcher->gui = gui;
} }

View File

@ -62,7 +62,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context)
} else if(status == LoaderStatusOk) { } else if(status == LoaderStatusOk) {
result = PB_CommandStatus_OK; result = PB_CommandStatus_OK;
} else { } else {
furi_crash(NULL); furi_crash();
} }
} else { } else {
result = PB_CommandStatus_ERROR_INVALID_PARAMETERS; result = PB_CommandStatus_ERROR_INVALID_PARAMETERS;

View File

@ -68,7 +68,7 @@ bool desktop_settings_scene_pin_auth_on_event(void* context, SceneManagerEvent e
} else if(state == SCENE_STATE_PIN_AUTH_DISABLE) { } else if(state == SCENE_STATE_PIN_AUTH_DISABLE) {
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinDisable); scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinDisable);
} else { } else {
furi_assert(0); furi_crash();
} }
consumed = true; consumed = true;
break; break;

View File

@ -39,7 +39,7 @@ void desktop_settings_scene_pin_error_on_enter(void* context) {
} else if(state == SCENE_STATE_PIN_ERROR_WRONG) { } else if(state == SCENE_STATE_PIN_ERROR_WRONG) {
desktop_view_pin_input_set_label_primary(app->pin_input_view, 35, 8, "Wrong PIN!"); desktop_view_pin_input_set_label_primary(app->pin_input_view, 35, 8, "Wrong PIN!");
} else { } else {
furi_assert(0); furi_crash();
} }
desktop_view_pin_input_set_label_secondary(app->pin_input_view, 0, 8, NULL); desktop_view_pin_input_set_label_secondary(app->pin_input_view, 0, 8, NULL);
desktop_view_pin_input_set_label_button(app->pin_input_view, "Retry"); desktop_view_pin_input_set_label_button(app->pin_input_view, "Retry");

View File

@ -32,7 +32,7 @@ bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManager
consumed = true; consumed = true;
break; break;
default: default:
furi_crash(NULL); furi_crash();
} }
} }
return consumed; return consumed;

View File

@ -52,7 +52,7 @@ bool desktop_settings_scene_pin_setup_howto2_on_event(void* context, SceneManage
break; break;
} }
default: default:
furi_crash(NULL); furi_crash();
} }
} }
return consumed; return consumed;

View File

@ -264,7 +264,7 @@ void hid_hal_keyboard_press(Hid* instance, uint16_t event) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_kb_press(event); furi_hal_hid_kb_press(event);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -275,7 +275,7 @@ void hid_hal_keyboard_release(Hid* instance, uint16_t event) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_kb_release(event); furi_hal_hid_kb_release(event);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -286,7 +286,7 @@ void hid_hal_keyboard_release_all(Hid* instance) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_kb_release_all(); furi_hal_hid_kb_release_all();
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -297,7 +297,7 @@ void hid_hal_consumer_key_press(Hid* instance, uint16_t event) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_consumer_key_press(event); furi_hal_hid_consumer_key_press(event);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -308,7 +308,7 @@ void hid_hal_consumer_key_release(Hid* instance, uint16_t event) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_consumer_key_release(event); furi_hal_hid_consumer_key_release(event);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -319,7 +319,7 @@ void hid_hal_consumer_key_release_all(Hid* instance) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_kb_release_all(); furi_hal_hid_kb_release_all();
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -330,7 +330,7 @@ void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_mouse_move(dx, dy); furi_hal_hid_mouse_move(dx, dy);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -341,7 +341,7 @@ void hid_hal_mouse_scroll(Hid* instance, int8_t delta) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_mouse_scroll(delta); furi_hal_hid_mouse_scroll(delta);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -352,7 +352,7 @@ void hid_hal_mouse_press(Hid* instance, uint16_t event) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_mouse_press(event); furi_hal_hid_mouse_press(event);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -363,7 +363,7 @@ void hid_hal_mouse_release(Hid* instance, uint16_t event) {
} else if(instance->transport == HidTransportUsb) { } else if(instance->transport == HidTransportUsb) {
furi_hal_hid_mouse_release(event); furi_hal_hid_mouse_release(event);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
@ -375,7 +375,7 @@ void hid_hal_mouse_release_all(Hid* instance) {
furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT); furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT);
furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT); furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }

View File

@ -0,0 +1,40 @@
# Run time checks and forced system crash
The best way to protect system integrity is to reduce amount cases that we must handle and crash the system as early as possible.
For that purpose we have bunch of helpers located in Furi Core check.h.
## Couple notes before start
- Definition of Crash - log event, save crash information in RTC and reboot the system.
- Definition of Halt - log event, stall the system.
- Debug and production builds behaves differently: debug build will never reset system in order to preserve state for debugging.
- If you have debugger connected we will stop before reboot automatically.
- All helpers accept optional MESSAGE_CSTR: it can be in RAM or Flash memory, but only messages from Flash will be shown after system reboot.
- MESSAGE_CSTR can be NULL, but macros magic already doing it for you, so just don't.
## `furi_assert(CONDITION)` or `furi_assert(CONDITION, MESSAGE_CSTR)`
Assert condition in development environment and crash the system if CONDITION is false.
- Should be used at development stage in apps and services
- Keep in mind that release never contains this check
- Keep in mind that libraries never contains this check by default, use `LIB_DEBUG=1` if you need it
- Avoid putting function calls into CONDITION, since it may be omitted in some builds
## `furi_check(CONDITION)` or `furi_check(CONDITION, MESSAGE_CSTR)`
Always assert condition and crash the system if CONDITION is false.
- Use it if you always need to check conditions
## `furi_crash()` or `furi_crash(MESSAGE_CSTR)`
Crash the system.
- Use it to crash the system. For example: if abnormal condition detected.
## `furi_halt()` or `furi_halt(MESSAGE_CSTR)`
Halt the system.
- We use it internally to shutdown flipper if poweroff is not possible.

View File

@ -128,7 +128,7 @@ static void __furi_print_name(bool isr) {
} }
} }
FURI_NORETURN void __furi_crash() { FURI_NORETURN void __furi_crash_implementation() {
__disable_irq(); __disable_irq();
GET_MESSAGE_AND_STORE_REGISTERS(); GET_MESSAGE_AND_STORE_REGISTERS();
@ -179,7 +179,7 @@ FURI_NORETURN void __furi_crash() {
__builtin_unreachable(); __builtin_unreachable();
} }
FURI_NORETURN void __furi_halt() { FURI_NORETURN void __furi_halt_implementation() {
__disable_irq(); __disable_irq();
GET_MESSAGE_AND_STORE_REGISTERS(); GET_MESSAGE_AND_STORE_REGISTERS();

View File

@ -28,39 +28,51 @@ extern "C" {
#define __FURI_CHECK_MESSAGE_FLAG (0x02) #define __FURI_CHECK_MESSAGE_FLAG (0x02)
/** Crash system */ /** Crash system */
FURI_NORETURN void __furi_crash(); FURI_NORETURN void __furi_crash_implementation();
/** Halt system */ /** Halt system */
FURI_NORETURN void __furi_halt(); FURI_NORETURN void __furi_halt_implementation();
/** Crash system with message. Show message after reboot. */ /** Crash system with message. Show message after reboot. */
#define furi_crash(message) \ #define __furi_crash(message) \
do { \ do { \
register const void* r12 asm("r12") = (void*)message; \ register const void* r12 asm("r12") = (void*)message; \
asm volatile("sukima%=:" : : "r"(r12)); \ asm volatile("sukima%=:" : : "r"(r12)); \
__furi_crash(); \ __furi_crash_implementation(); \
} while(0) } while(0)
/** Crash system
*
* @param optional message (const char*)
*/
#define furi_crash(...) M_APPLY(__furi_crash, M_IF_EMPTY(__VA_ARGS__)((NULL), (__VA_ARGS__)))
/** Halt system with message. */ /** Halt system with message. */
#define furi_halt(message) \ #define __furi_halt(message) \
do { \ do { \
register const void* r12 asm("r12") = (void*)message; \ register const void* r12 asm("r12") = (void*)message; \
asm volatile("sukima%=:" : : "r"(r12)); \ asm volatile("sukima%=:" : : "r"(r12)); \
__furi_halt(); \ __furi_halt_implementation(); \
} while(0) } while(0)
/** Halt system
*
* @param optional message (const char*)
*/
#define furi_halt(...) M_APPLY(__furi_halt, M_IF_EMPTY(__VA_ARGS__)((NULL), (__VA_ARGS__)))
/** Check condition and crash if check failed */ /** Check condition and crash if check failed */
#define __furi_check(__e, __m) \ #define __furi_check(__e, __m) \
do { \ do { \
if(!(__e)) { \ if(!(__e)) { \
furi_crash(__m); \ __furi_crash(__m); \
} \ } \
} while(0) } while(0)
/** Check condition and crash if failed /** Check condition and crash if failed
* *
* @param condition to check * @param condition to check
* @param optional message * @param optional message (const char*)
*/ */
#define furi_check(...) \ #define furi_check(...) \
M_APPLY(__furi_check, M_DEFAULT_ARGS(2, (__FURI_CHECK_MESSAGE_FLAG), __VA_ARGS__)) M_APPLY(__furi_check, M_DEFAULT_ARGS(2, (__FURI_CHECK_MESSAGE_FLAG), __VA_ARGS__))
@ -70,7 +82,7 @@ FURI_NORETURN void __furi_halt();
#define __furi_assert(__e, __m) \ #define __furi_assert(__e, __m) \
do { \ do { \
if(!(__e)) { \ if(!(__e)) { \
furi_crash(__m); \ __furi_crash(__m); \
} \ } \
} while(0) } while(0)
#else #else
@ -86,7 +98,7 @@ FURI_NORETURN void __furi_halt();
* @warning only will do check if firmware compiled in debug mode * @warning only will do check if firmware compiled in debug mode
* *
* @param condition to check * @param condition to check
* @param optional message * @param optional message (const char*)
*/ */
#define furi_assert(...) \ #define furi_assert(...) \
M_APPLY(__furi_assert, M_DEFAULT_ARGS(2, (__FURI_ASSERT_MESSAGE_FLAG), __VA_ARGS__)) M_APPLY(__furi_assert, M_DEFAULT_ARGS(2, (__FURI_ASSERT_MESSAGE_FLAG), __VA_ARGS__))

View File

@ -48,7 +48,7 @@ static void ibutton_protocols_get_group_by_id(
local_id -= ibutton_protocol_groups[i]->protocol_count; local_id -= ibutton_protocol_groups[i]->protocol_count;
} }
} }
furi_crash(NULL); furi_crash();
} }
iButtonProtocols* ibutton_protocols_alloc() { iButtonProtocols* ibutton_protocols_alloc() {

View File

@ -48,7 +48,7 @@ void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* messag
*data2 = (message->command & 0xFFC0) >> 6; *data2 = (message->command & 0xFFC0) >> 6;
encoder->bits_to_encode = 42; encoder->bits_to_encode = 42;
} else { } else {
furi_assert(0); furi_crash();
} }
} }

View File

@ -23,7 +23,7 @@ void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* messa
*data |= (message->address & 0x1FFF) << 7; *data |= (message->address & 0x1FFF) << 7;
encoder->bits_to_encode = 20; encoder->bits_to_encode = 20;
} else { } else {
furi_assert(0); furi_crash();
} }
} }

View File

@ -88,7 +88,7 @@ FuriHalInfraredTxGetDataState
state = FuriHalInfraredTxGetDataStateDone; state = FuriHalInfraredTxGetDataStateDone;
} }
} else { } else {
furi_crash(NULL); furi_crash();
} }
return state; return state;

View File

@ -367,10 +367,11 @@ static FuriHalInfraredTxGetDataState
*duration = timing.duration; *duration = timing.duration;
state = timing.state; state = timing.state;
} else { } else {
furi_assert(0); // Why bother if we crash anyway?..
*level = 0; *level = 0;
*duration = 100; *duration = 100;
state = FuriHalInfraredTxGetDataStateDone; state = FuriHalInfraredTxGetDataStateDone;
furi_crash();
} }
uint32_t flags_set = furi_thread_flags_set( uint32_t flags_set = furi_thread_flags_set(
@ -414,7 +415,7 @@ static bool infrared_get_new_signal(InfraredWorker* instance) {
} else if(response == InfraredWorkerGetSignalResponseStop) { } else if(response == InfraredWorkerGetSignalResponseStop) {
new_signal_obtained = false; new_signal_obtained = false;
} else { } else {
furi_assert(0); furi_crash();
} }
return new_signal_obtained; return new_signal_obtained;
@ -443,9 +444,8 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
} }
if(status == InfraredStatusError) { if(status == InfraredStatusError) {
furi_assert(0);
new_data_available = false; new_data_available = false;
break; furi_crash();
} else if(status == InfraredStatusOk) { } else if(status == InfraredStatusOk) {
timing.state = FuriHalInfraredTxGetDataStateOk; timing.state = FuriHalInfraredTxGetDataStateOk;
} else if(status == InfraredStatusDone) { } else if(status == InfraredStatusDone) {
@ -456,7 +456,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
timing.state = FuriHalInfraredTxGetDataStateLastDone; timing.state = FuriHalInfraredTxGetDataStateLastDone;
} }
} else { } else {
furi_assert(0); furi_crash();
} }
uint32_t written_size = uint32_t written_size =
furi_stream_buffer_send(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0); furi_stream_buffer_send(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0);
@ -548,7 +548,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) {
break; break;
default: default:
furi_assert(0); furi_crash();
break; break;
} }
} }

View File

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,40.1,, Version,+,41.0,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,, Header,+,applications/services/cli/cli_vcp.h,,
@ -302,10 +302,10 @@ Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*"
Function,+,__errno,int*, Function,+,__errno,int*,
Function,-,__fpclassifyd,int,double Function,-,__fpclassifyd,int,double
Function,-,__fpclassifyf,int,float Function,-,__fpclassifyf,int,float
Function,+,__furi_crash,void, Function,+,__furi_crash_implementation,void,
Function,+,__furi_critical_enter,__FuriCriticalInfo, Function,+,__furi_critical_enter,__FuriCriticalInfo,
Function,+,__furi_critical_exit,void,__FuriCriticalInfo Function,+,__furi_critical_exit,void,__FuriCriticalInfo
Function,+,__furi_halt,void, Function,+,__furi_halt_implementation,void,
Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*" Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*"
Function,-,__getline,ssize_t,"char**, size_t*, FILE*" Function,-,__getline,ssize_t,"char**, size_t*, FILE*"
Function,-,__isinfd,int,double Function,-,__isinfd,int,double

1 entry status name type params
2 Version + 40.1 41.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
302 Function + __errno int*
303 Function - __fpclassifyd int double
304 Function - __fpclassifyf int float
305 Function + __furi_crash __furi_crash_implementation void
306 Function + __furi_critical_enter __FuriCriticalInfo
307 Function + __furi_critical_exit void __FuriCriticalInfo
308 Function + __furi_halt __furi_halt_implementation void
309 Function - __getdelim ssize_t char**, size_t*, int, FILE*
310 Function - __getline ssize_t char**, size_t*, FILE*
311 Function - __isinfd int double

View File

@ -1,5 +1,5 @@
entry,status,name,type,params entry,status,name,type,params
Version,+,40.1,, Version,+,41.0,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli.h,,
@ -370,10 +370,10 @@ Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*"
Function,+,__errno,int*, Function,+,__errno,int*,
Function,-,__fpclassifyd,int,double Function,-,__fpclassifyd,int,double
Function,-,__fpclassifyf,int,float Function,-,__fpclassifyf,int,float
Function,+,__furi_crash,void, Function,+,__furi_crash_implementation,void,
Function,+,__furi_critical_enter,__FuriCriticalInfo, Function,+,__furi_critical_enter,__FuriCriticalInfo,
Function,+,__furi_critical_exit,void,__FuriCriticalInfo Function,+,__furi_critical_exit,void,__FuriCriticalInfo
Function,+,__furi_halt,void, Function,+,__furi_halt_implementation,void,
Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*" Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*"
Function,-,__getline,ssize_t,"char**, size_t*, FILE*" Function,-,__getline,ssize_t,"char**, size_t*, FILE*"
Function,-,__isinfd,int,double Function,-,__isinfd,int,double

1 entry status name type params
2 Version + 40.1 41.0
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
370 Function + __errno int*
371 Function - __fpclassifyd int double
372 Function - __fpclassifyf int float
373 Function + __furi_crash __furi_crash_implementation void
374 Function + __furi_critical_enter __FuriCriticalInfo
375 Function + __furi_critical_exit void __FuriCriticalInfo
376 Function + __furi_halt __furi_halt_implementation void
377 Function - __getdelim ssize_t char**, size_t*, int, FILE*
378 Function - __getline ssize_t char**, size_t*, FILE*
379 Function - __isinfd int double

View File

@ -125,7 +125,7 @@ static void furi_hal_infrared_tim_rx_isr() {
if(infrared_tim_rx.capture_callback) if(infrared_tim_rx.capture_callback)
infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 1, duration); infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 1, duration);
} else { } else {
furi_assert(0); furi_crash();
} }
} }
@ -141,7 +141,7 @@ static void furi_hal_infrared_tim_rx_isr() {
if(infrared_tim_rx.capture_callback) if(infrared_tim_rx.capture_callback)
infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 0, duration); infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 0, duration);
} else { } else {
furi_assert(0); furi_crash();
} }
} }
} }
@ -254,7 +254,7 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) {
} else if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[1].data) { } else if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[1].data) {
buf_num = 1; buf_num = 1;
} else { } else {
furi_assert(0); furi_crash();
} }
return buf_num; return buf_num;
} }
@ -263,7 +263,7 @@ static void furi_hal_infrared_tx_dma_polarity_isr() {
#if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1 #if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
if(LL_DMA_IsActiveFlag_TE1(INFRARED_DMA)) { if(LL_DMA_IsActiveFlag_TE1(INFRARED_DMA)) {
LL_DMA_ClearFlag_TE1(INFRARED_DMA); LL_DMA_ClearFlag_TE1(INFRARED_DMA);
furi_crash(NULL); furi_crash();
} }
if(LL_DMA_IsActiveFlag_TC1(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH1_DEF)) { if(LL_DMA_IsActiveFlag_TC1(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH1_DEF)) {
LL_DMA_ClearFlag_TC1(INFRARED_DMA); LL_DMA_ClearFlag_TC1(INFRARED_DMA);
@ -285,7 +285,7 @@ static void furi_hal_infrared_tx_dma_isr() {
#if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2 #if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
if(LL_DMA_IsActiveFlag_TE2(INFRARED_DMA)) { if(LL_DMA_IsActiveFlag_TE2(INFRARED_DMA)) {
LL_DMA_ClearFlag_TE2(INFRARED_DMA); LL_DMA_ClearFlag_TE2(INFRARED_DMA);
furi_crash(NULL); furi_crash();
} }
if(LL_DMA_IsActiveFlag_HT2(INFRARED_DMA) && LL_DMA_IsEnabledIT_HT(INFRARED_DMA_CH2_DEF)) { if(LL_DMA_IsActiveFlag_HT2(INFRARED_DMA) && LL_DMA_IsEnabledIT_HT(INFRARED_DMA_CH2_DEF)) {
LL_DMA_ClearFlag_HT2(INFRARED_DMA); LL_DMA_ClearFlag_HT2(INFRARED_DMA);
@ -303,7 +303,7 @@ static void furi_hal_infrared_tx_dma_isr() {
} else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) { } else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) {
/* fallthrough */ /* fallthrough */
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
if(LL_DMA_IsActiveFlag_TC2(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH2_DEF)) { if(LL_DMA_IsActiveFlag_TC2(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH2_DEF)) {
@ -596,7 +596,7 @@ static void furi_hal_infrared_async_tx_free_resources(void) {
void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) { void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
if((duty_cycle > 1) || (duty_cycle <= 0) || (freq > INFRARED_MAX_FREQUENCY) || if((duty_cycle > 1) || (duty_cycle <= 0) || (freq > INFRARED_MAX_FREQUENCY) ||
(freq < INFRARED_MIN_FREQUENCY) || (infrared_tim_tx.data_callback == NULL)) { (freq < INFRARED_MIN_FREQUENCY) || (infrared_tim_tx.data_callback == NULL)) {
furi_crash(NULL); furi_crash();
} }
furi_assert(furi_hal_infrared_state == InfraredStateIdle); furi_assert(furi_hal_infrared_state == InfraredStateIdle);

View File

@ -221,7 +221,7 @@ bool furi_hal_spi_bus_trx_dma(
dma_rx_req = LL_DMAMUX_REQ_SPI2_RX; dma_rx_req = LL_DMAMUX_REQ_SPI2_RX;
dma_tx_req = LL_DMAMUX_REQ_SPI2_TX; dma_tx_req = LL_DMAMUX_REQ_SPI2_TX;
} else { } else {
furi_crash(NULL); furi_crash();
} }
if(rx_buffer == NULL) { if(rx_buffer == NULL) {

View File

@ -604,7 +604,7 @@ static void furi_hal_subghz_async_tx_timer_isr() {
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullDown, GpioSpeedLow); furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullDown, GpioSpeedLow);
LL_TIM_DisableCounter(TIM2); LL_TIM_DisableCounter(TIM2);
} else { } else {
furi_crash(NULL); furi_crash();
} }
} }
} }

View File

@ -187,7 +187,7 @@ void furi_hal_version_init() {
furi_hal_version_load_otp_v2(); furi_hal_version_load_otp_v2();
break; break;
default: default:
furi_crash(NULL); furi_crash();
} }
furi_hal_rtc_set_register(FuriHalRtcRegisterVersion, (uint32_t)version_get()); furi_hal_rtc_set_register(FuriHalRtcRegisterVersion, (uint32_t)version_get());