Просмотр исходного кода

furi_check - a new way to asserting (#204)

* hal-related task_is_isr_context function
* furi_check implementation
* change application to use furi_check
* add second level of assertion
* add TODO about ISR context
* Applications: refactor furi_check and furi_assert.
* Apploader: propwer widget usage. Menu: check on furi resource request.
* refactor furi_check

Co-authored-by: Aleksandr Kutuzov <aku@plooks.com>
Co-authored-by: coreglitch <mail@s3f.ru>
DrZlo13 5 лет назад
Родитель
Сommit
8aeafd8179

+ 1 - 2
applications/app-loader/app-loader.c

@@ -51,13 +51,12 @@ static void handle_menu(void* _ctx) {
 
 void app_loader(void* p) {
     osThreadId_t self_id = osThreadGetId();
-    assert(self_id);
+    furi_check(self_id);
 
     AppLoaderState state;
     state.handler = NULL;
 
     state.widget = widget_alloc();
-    assert(state.widget);
     widget_enabled_set(state.widget, false);
     widget_draw_callback_set(state.widget, render_callback, &state);
     widget_input_callback_set(state.widget, input_callback, &state);

+ 1 - 1
applications/backlight-control/backlight-control.c

@@ -15,7 +15,7 @@ void backlight_control(void* p) {
 
     // open record
     PubSub* event_record = furi_open("input_events");
-    assert(event_record != NULL);
+    furi_check(event_record);
     subscribe_pubsub(event_record, event_cb, (void*)update);
 
     // we ready to work

+ 1 - 1
applications/cc1101-workaround/cc1101-workaround.cpp

@@ -203,7 +203,7 @@ static void input_callback(InputEvent* input_event, void* ctx) {
 
 extern "C" void cc1101_workaround(void* p) {
     osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(AppEvent), NULL);
-    assert(event_queue);
+    furi_check(event_queue);
 
     State _state;
     _state.mode = ModeRx;

+ 2 - 2
applications/examples/input_dump.c

@@ -16,11 +16,11 @@ static void event_cb(const void* value, void* ctx) {
 void application_input_dump(void* p) {
     // open record
     ValueManager* state_record = furi_open("input_state");
-    assert(state_record != NULL);
+    furi_check(state_record);
     subscribe_pubsub(&state_record->pubsub, state_cb, NULL);
 
     PubSub* event_record = furi_open("input_events");
-    assert(event_record != NULL);
+    furi_check(event_record);
     subscribe_pubsub(event_record, event_cb, NULL);
 
     for(;;) {

+ 16 - 16
applications/gui/canvas.c

@@ -3,8 +3,8 @@
 #include "icon.h"
 #include "icon_i.h"
 
-#include <assert.h>
 #include <flipper.h>
+#include <flipper_v2.h>
 
 typedef struct {
     CanvasApi api;
@@ -60,12 +60,12 @@ CanvasApi* canvas_api_init() {
 }
 
 void canvas_api_free(CanvasApi* api) {
-    assert(api);
+    furi_assert(api);
     free(api);
 }
 
 void canvas_commit(CanvasApi* api) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_SetPowerSave(&canvas->fb, 0); // wake up display
     u8g2_SendBuffer(&canvas->fb);
@@ -77,7 +77,7 @@ void canvas_frame_set(
     uint8_t offset_y,
     uint8_t width,
     uint8_t height) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     canvas->offset_x = offset_x;
     canvas->offset_y = offset_y;
@@ -86,31 +86,31 @@ void canvas_frame_set(
 }
 
 uint8_t canvas_width(CanvasApi* api) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     return canvas->width;
 }
 
 uint8_t canvas_height(CanvasApi* api) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     return canvas->height;
 }
 
 void canvas_clear(CanvasApi* api) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_ClearBuffer(&canvas->fb);
 }
 
 void canvas_color_set(CanvasApi* api, Color color) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_SetDrawColor(&canvas->fb, color);
 }
 
 void canvas_font_set(CanvasApi* api, Font font) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_SetFontMode(&canvas->fb, 1);
     if(font == FontPrimary) {
@@ -118,12 +118,12 @@ void canvas_font_set(CanvasApi* api, Font font) {
     } else if(font == FontSecondary) {
         u8g2_SetFont(&canvas->fb, u8g2_font_HelvetiPixel_tr);
     } else {
-        assert(0);
+        furi_check(0);
     }
 }
 
 void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) {
-    assert(api);
+    furi_assert(api);
     if(!str) return;
     Canvas* canvas = (Canvas*)api;
     x += canvas->offset_x;
@@ -132,7 +132,7 @@ void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) {
 }
 
 void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon) {
-    assert(api);
+    furi_assert(api);
     if(!icon) return;
     Canvas* canvas = (Canvas*)api;
     x += canvas->offset_x;
@@ -142,25 +142,25 @@ void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon) {
 }
 
 void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_DrawPixel(&canvas->fb, x, y);
 }
 
 void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_DrawBox(&canvas->fb, x, y, width, height);
 }
 
 void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_DrawFrame(&canvas->fb, x, y, width, height);
 }
 
 void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
-    assert(api);
+    furi_assert(api);
     Canvas* canvas = (Canvas*)api;
     u8g2_DrawLine(&canvas->fb, x1, y1, x2, y2);
 }

+ 15 - 13
applications/gui/gui.c

@@ -34,7 +34,7 @@ Widget* gui_widget_find_enabled(WidgetArray_t array) {
 }
 
 void gui_update(Gui* gui) {
-    assert(gui);
+    furi_assert(gui);
     GuiMessage message;
     message.type = GuiMessageTypeRedraw;
     gui_event_messsage_send(gui->event, &message);
@@ -83,7 +83,7 @@ bool gui_redraw_none(Gui* gui) {
 }
 
 void gui_redraw(Gui* gui) {
-    assert(gui);
+    furi_assert(gui);
     gui_lock(gui);
 
     if(!gui_redraw_fs(gui)) {
@@ -98,7 +98,9 @@ void gui_redraw(Gui* gui) {
 }
 
 void gui_input(Gui* gui, InputEvent* input_event) {
-    assert(gui);
+    furi_assert(gui);
+    furi_assert(input_event);
+
     gui_lock(gui);
 
     Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerFullscreen]);
@@ -113,19 +115,19 @@ void gui_input(Gui* gui, InputEvent* input_event) {
 }
 
 void gui_lock(Gui* gui) {
-    assert(gui);
-    assert(osMutexAcquire(gui->mutex, osWaitForever) == osOK);
+    furi_assert(gui);
+    furi_check(osMutexAcquire(gui->mutex, osWaitForever) == osOK);
 }
 
 void gui_unlock(Gui* gui) {
-    assert(gui);
-    assert(osMutexRelease(gui->mutex) == osOK);
+    furi_assert(gui);
+    furi_check(osMutexRelease(gui->mutex) == osOK);
 }
 
 void gui_add_widget(GuiApi* gui_api, Widget* widget, GuiLayer layer) {
-    assert(gui_api);
-    assert(widget);
-    assert(layer < GuiLayerMAX);
+    furi_assert(gui_api);
+    furi_assert(widget);
+    furi_check(layer < GuiLayerMAX);
     Gui* gui = (Gui*)gui_api;
 
     gui_lock(gui);
@@ -136,8 +138,8 @@ void gui_add_widget(GuiApi* gui_api, Widget* widget, GuiLayer layer) {
 }
 
 void gui_remove_widget(GuiApi* gui_api, Widget* widget) {
-    assert(gui_api);
-    assert(widget);
+    furi_assert(gui_api);
+    furi_assert(widget);
     Gui* gui = (Gui*)gui_api;
 
     gui_lock(gui);
@@ -164,7 +166,7 @@ Gui* gui_alloc() {
     gui->api.remove_widget = gui_remove_widget;
     // Allocate mutex
     gui->mutex = osMutexNew(NULL);
-    assert(gui->mutex);
+    furi_check(gui->mutex);
     // Event dispatcher
     gui->event = gui_event_alloc();
     // Drawing canvas api

+ 13 - 11
applications/gui/gui_event.c

@@ -1,7 +1,6 @@
 #include "gui_event.h"
 
 #include <flipper_v2.h>
-#include <assert.h>
 
 #define GUI_EVENT_MQUEUE_SIZE 8
 
@@ -11,7 +10,9 @@ struct GuiEvent {
 };
 
 void gui_event_input_events_callback(const void* value, void* ctx) {
-    assert(ctx);
+    furi_assert(value);
+    furi_assert(ctx);
+
     GuiEvent* gui_event = ctx;
 
     GuiMessage message;
@@ -23,35 +24,36 @@ void gui_event_input_events_callback(const void* value, void* ctx) {
 
 GuiEvent* gui_event_alloc() {
     GuiEvent* gui_event = furi_alloc(sizeof(GuiEvent));
-    // Allocate message que
+
+    // Allocate message queue
     gui_event->mqueue = osMessageQueueNew(GUI_EVENT_MQUEUE_SIZE, sizeof(GuiMessage), NULL);
-    assert(gui_event->mqueue);
+    furi_check(gui_event->mqueue);
 
     // Input
     gui_event->input_event_record = furi_open("input_events");
-    assert(gui_event->input_event_record != NULL);
+    furi_check(gui_event->input_event_record != NULL);
     subscribe_pubsub(gui_event->input_event_record, gui_event_input_events_callback, gui_event);
 
     return gui_event;
 }
 
 void gui_event_free(GuiEvent* gui_event) {
-    assert(gui_event);
-    assert(osMessageQueueDelete(gui_event->mqueue) == osOK);
+    furi_assert(gui_event);
+    furi_check(osMessageQueueDelete(gui_event->mqueue) == osOK);
     free(gui_event);
 }
 
 void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message) {
-    assert(gui_event);
-    assert(message);
+    furi_assert(gui_event);
+    furi_assert(message);
     osMessageQueuePut(gui_event->mqueue, message, 0, 0);
 }
 
 GuiMessage gui_event_message_next(GuiEvent* gui_event) {
-    assert(gui_event);
+    furi_assert(gui_event);
     GuiMessage message;
 
-    assert(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) == osOK);
+    furi_check(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) == osOK);
 
     return message;
 }

+ 9 - 9
applications/gui/icon.c

@@ -3,7 +3,7 @@
 
 #include <cmsis_os2.h>
 #include <flipper.h>
-#include <assert.h>
+#include <flipper_v2.h>
 
 Icon* icon_alloc(const IconData* data) {
     Icon* icon = furi_alloc(sizeof(Icon));
@@ -12,12 +12,12 @@ Icon* icon_alloc(const IconData* data) {
 }
 
 void icon_free(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     free(icon);
 }
 
 const uint8_t* icon_get_data(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     if(icon->tick) {
         uint32_t now = osKernelGetTickCount();
         if(now < icon->tick) {
@@ -32,32 +32,32 @@ const uint8_t* icon_get_data(Icon* icon) {
 }
 
 void icon_next_frame(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     icon->frame = (icon->frame + 1) % icon->data->frame_count;
 }
 
 uint8_t icon_get_width(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     return icon->data->width;
 }
 
 uint8_t icon_get_height(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     return icon->data->height;
 }
 
 bool icon_is_animated(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     return icon->data->frame_count > 1;
 }
 
 void icon_start_animation(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     icon->tick = osKernelGetTickCount();
 }
 
 void icon_stop_animation(Icon* icon) {
-    assert(icon);
+    furi_assert(icon);
     icon->tick = 0;
     icon->frame = 0;
 }

+ 16 - 15
applications/gui/widget.c

@@ -3,6 +3,7 @@
 
 #include <cmsis_os.h>
 #include <flipper.h>
+#include <flipper_v2.h>
 
 #include "gui.h"
 #include "gui_i.h"
@@ -25,13 +26,13 @@ Widget* widget_alloc(WidgetDrawCallback callback, void* callback_context) {
 }
 
 void widget_free(Widget* widget) {
-    assert(widget);
-    assert(widget->gui == NULL);
+    furi_assert(widget);
+    furi_check(widget->gui == NULL);
     free(widget);
 }
 
 void widget_enabled_set(Widget* widget, bool enabled) {
-    assert(widget);
+    furi_assert(widget);
     if(widget->is_enabled != enabled) {
         widget->is_enabled = enabled;
         widget_update(widget);
@@ -39,47 +40,47 @@ void widget_enabled_set(Widget* widget, bool enabled) {
 }
 
 bool widget_is_enabled(Widget* widget) {
-    assert(widget);
+    furi_assert(widget);
     return widget->is_enabled;
 }
 
 void widget_draw_callback_set(Widget* widget, WidgetDrawCallback callback, void* context) {
-    assert(widget);
+    furi_assert(widget);
     widget->draw_callback = callback;
     widget->draw_callback_context = context;
 }
 
 void widget_input_callback_set(Widget* widget, WidgetInputCallback callback, void* context) {
-    assert(widget);
+    furi_assert(widget);
     widget->input_callback = callback;
     widget->input_callback_context = context;
 }
 
 void widget_update(Widget* widget) {
-    assert(widget);
+    furi_assert(widget);
     if(widget->gui) gui_update(widget->gui);
 }
 
 void widget_gui_set(Widget* widget, Gui* gui) {
-    assert(widget);
-    assert(gui);
+    furi_assert(widget);
+    furi_assert(gui);
     widget->gui = gui;
 }
 
 void widget_draw(Widget* widget, CanvasApi* canvas_api) {
-    assert(widget);
-    assert(canvas_api);
-    assert(widget->gui);
+    furi_assert(widget);
+    furi_assert(canvas_api);
 
+    furi_check(widget->gui);
     if(widget->draw_callback) {
         widget->draw_callback(canvas_api, widget->draw_callback_context);
     }
 }
 
 void widget_input(Widget* widget, InputEvent* event) {
-    assert(widget);
-    assert(event);
-    assert(widget->gui);
+    furi_assert(widget);
+    furi_assert(event);
 
+    furi_check(widget->gui);
     if(widget->input_callback) widget->input_callback(event, widget->input_callback_context);
 }

+ 3 - 4
applications/irukagotchi/irukagotchi.c

@@ -1,6 +1,5 @@
 #include "irukagotchi.h"
 
-#include <assert.h>
 #include <flipper_v2.h>
 
 #include <gui/gui.h>
@@ -46,7 +45,7 @@ Irukagotchi* irukagotchi_alloc() {
     widget_input_callback_set(irukagotchi->widget, irukagotchi_input_callback, irukagotchi);
 
     irukagotchi->menu_vm = furi_open("menu");
-    assert(irukagotchi->menu_vm);
+    furi_check(irukagotchi->menu_vm);
 
     return irukagotchi;
 }
@@ -55,9 +54,9 @@ void irukagotchi_task() {
     Irukagotchi* irukagotchi = irukagotchi_alloc();
 
     FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
-    assert(gui_record);
+    furi_check(gui_record);
     GuiApi* gui = furi_take(gui_record);
-    assert(gui);
+    furi_check(gui);
     gui->add_widget(gui, irukagotchi->widget, GuiLayerNone);
     furi_commit(gui_record);
 

+ 12 - 12
applications/menu/menu.c

@@ -41,7 +41,7 @@ ValueMutex* menu_init() {
 
     // Open GUI and register fullscreen widget
     GuiApi* gui = furi_open("gui");
-    assert(gui);
+    furi_check(gui);
     gui->add_widget(gui, menu->widget, GuiLayerFullscreen);
 
     widget_enabled_set(menu->widget, false);
@@ -52,7 +52,7 @@ ValueMutex* menu_init() {
 }
 
 void menu_build_main(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
     // Root point
     menu->root = menu_item_alloc_menu(NULL, NULL);
 
@@ -76,13 +76,13 @@ void menu_draw_secondary(Menu* menu, CanvasApi* canvas) {
 }
 
 void menu_widget_callback(CanvasApi* canvas, void* context) {
-    assert(canvas);
-    assert(context);
+    furi_assert(canvas);
+    furi_assert(context);
 
     Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex
     if(menu == NULL) return; // redraw fail
 
-    assert(menu->current);
+    furi_assert(menu->current);
 
     canvas->clear(canvas);
     canvas->set_color(canvas, ColorBlack);
@@ -123,14 +123,14 @@ void menu_widget_callback(CanvasApi* canvas, void* context) {
 }
 
 void menu_update(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
 
     menu_event_activity_notify(menu->event);
     widget_update(menu->widget);
 }
 
 void menu_up(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
 
     size_t position = menu_item_get_position(menu->current);
     MenuItemArray_t* items = menu_item_get_subitems(menu->current);
@@ -141,7 +141,7 @@ void menu_up(Menu* menu) {
 }
 
 void menu_down(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
     size_t position = menu_item_get_position(menu->current);
     MenuItemArray_t* items = menu_item_get_subitems(menu->current);
     position++;
@@ -151,7 +151,7 @@ void menu_down(Menu* menu) {
 }
 
 void menu_ok(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
 
     if(!menu->current) {
         widget_enabled_set(menu->widget, true);
@@ -180,7 +180,7 @@ void menu_ok(Menu* menu) {
 }
 
 void menu_back(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
     MenuItem* parent = menu_item_get_parent(menu->current);
     if(parent) {
         menu->current = parent;
@@ -191,7 +191,7 @@ void menu_back(Menu* menu) {
 }
 
 void menu_exit(Menu* menu) {
-    assert(menu);
+    furi_assert(menu);
     widget_enabled_set(menu->widget, false);
     menu->current = NULL;
     menu_update(menu);
@@ -203,7 +203,7 @@ void menu_task(void* p) {
     MenuEvent* menu_event = NULL;
     {
         Menu* menu = acquire_mutex_block(menu_mutex);
-        assert(menu);
+        furi_check(menu);
 
         menu_build_main(menu);
 

+ 7 - 9
applications/menu/menu_event.c

@@ -1,11 +1,11 @@
 #include "menu_event.h"
 
 #include <cmsis_os.h>
-#include <assert.h>
 #include <string.h>
 #include <stdlib.h>
 
 #include <flipper.h>
+#include <flipper_v2.h>
 
 #define MENU_MESSAGE_MQUEUE_SIZE 8
 
@@ -25,30 +25,28 @@ MenuEvent* menu_event_alloc() {
     MenuEvent* menu_event = furi_alloc(sizeof(MenuEvent));
 
     menu_event->mqueue = osMessageQueueNew(MENU_MESSAGE_MQUEUE_SIZE, sizeof(MenuMessage), NULL);
-    assert(menu_event->mqueue);
+    furi_check(menu_event->mqueue);
 
     menu_event->timeout_timer =
         osTimerNew(MenuEventimeout_callback, osTimerOnce, menu_event, NULL);
-    assert(menu_event->timeout_timer);
+    furi_check(menu_event->timeout_timer);
 
     return menu_event;
 }
 
 void menu_event_free(MenuEvent* menu_event) {
-    osStatus_t status;
-    assert(menu_event);
-    status = osMessageQueueDelete(menu_event->mqueue);
-    assert(status == osOK);
+    furi_assert(menu_event);
+    furi_check(osMessageQueueDelete(menu_event->mqueue) == osOK);
     free(menu_event);
 }
 
 void menu_event_activity_notify(MenuEvent* menu_event) {
-    assert(menu_event);
+    furi_assert(menu_event);
     osTimerStart(menu_event->timeout_timer, 60000U); // 1m timeout, return to main
 }
 
 MenuMessage menu_event_next(MenuEvent* menu_event) {
-    assert(menu_event);
+    furi_assert(menu_event);
     MenuMessage message;
     while(osMessageQueueGet(menu_event->mqueue, &message, NULL, osWaitForever) != osOK) {
     };

+ 16 - 17
applications/menu/menu_item.c

@@ -1,8 +1,8 @@
 #include "menu_item.h"
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <flipper.h>
+#include <flipper_v2.h>
 
 struct MenuItem {
     MenuItemType type;
@@ -52,7 +52,7 @@ menu_item_alloc_function(const char* label, Icon* icon, MenuItemCallback callbac
 }
 
 void menu_item_release(MenuItem* menu_item) {
-    assert(menu_item);
+    furi_assert(menu_item);
     if(menu_item->type == MenuItemTypeMenu) {
         //TODO: iterate and release
         free(menu_item->data);
@@ -61,62 +61,61 @@ void menu_item_release(MenuItem* menu_item) {
 }
 
 MenuItem* menu_item_get_parent(MenuItem* menu_item) {
-    assert(menu_item);
+    furi_assert(menu_item);
     return menu_item->parent;
 }
 
 void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item) {
-    assert(menu_item);
-    assert(menu_item->type == MenuItemTypeMenu);
+    furi_assert(menu_item);
+    furi_check(menu_item->type == MenuItemTypeMenu);
     MenuItemArray_t* items = menu_item->data;
     sub_item->parent = menu_item;
     MenuItemArray_push_back(*items, sub_item);
 }
 
 uint8_t menu_item_get_type(MenuItem* menu_item) {
-    assert(menu_item);
+    furi_assert(menu_item);
     return menu_item->type;
 }
 
 void menu_item_set_position(MenuItem* menu_item, size_t position) {
-    assert(menu_item);
+    furi_assert(menu_item);
     menu_item->position = position;
 }
 
 size_t menu_item_get_position(MenuItem* menu_item) {
-    assert(menu_item);
+    furi_assert(menu_item);
     return menu_item->position;
 }
 
 void menu_item_set_label(MenuItem* menu_item, const char* label) {
-    assert(menu_item);
+    furi_assert(menu_item);
     menu_item->label = label;
 }
 
 const char* menu_item_get_label(MenuItem* menu_item) {
-    assert(menu_item);
+    furi_assert(menu_item);
     return menu_item->label;
 }
 
 void menu_item_set_icon(MenuItem* menu_item, Icon* icon) {
-    assert(menu_item);
+    furi_assert(menu_item);
     menu_item->icon = icon;
 }
 
 Icon* menu_item_get_icon(MenuItem* menu_item) {
-    assert(menu_item);
+    furi_assert(menu_item);
     return menu_item->icon;
 }
 
 MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item) {
-    assert(menu_item);
-    assert(menu_item->type == MenuItemTypeMenu);
+    furi_assert(menu_item);
+    furi_check(menu_item->type == MenuItemTypeMenu);
     return menu_item->data;
 }
 
 void menu_item_function_call(MenuItem* menu_item) {
-    assert(menu_item);
-    assert(menu_item->type == MenuItemTypeFunction);
-
+    furi_assert(menu_item);
+    furi_check(menu_item->type == MenuItemTypeFunction);
     if(menu_item->callback) menu_item->callback(menu_item->callback_context);
 }

+ 14 - 13
applications/nfc/dispatcher.c

@@ -1,6 +1,7 @@
 #include "dispatcher.h"
 
 #include <flipper.h>
+#include <flipper_v2.h>
 
 struct Dispatcher {
     void* message;
@@ -16,41 +17,41 @@ Dispatcher* dispatcher_alloc(size_t queue_size, size_t message_size) {
     dispatcher->message_size = message_size;
 
     dispatcher->mqueue = osMessageQueueNew(queue_size, message_size, NULL);
-    assert(dispatcher->mqueue);
+    furi_check(dispatcher->mqueue);
 
     dispatcher->lock_mutex = osMutexNew(NULL);
-    assert(dispatcher->lock_mutex);
+    furi_check(dispatcher->lock_mutex);
     dispatcher_lock(dispatcher);
 
     return dispatcher;
 }
 
 void dispatcher_free(Dispatcher* dispatcher) {
-    assert(dispatcher);
+    furi_assert(dispatcher);
     free(dispatcher);
 }
 
 void dispatcher_send(Dispatcher* dispatcher, Message* message) {
-    assert(dispatcher);
-    assert(message);
-    assert(osMessageQueuePut(dispatcher->mqueue, message, 0, osWaitForever) == osOK);
+    furi_assert(dispatcher);
+    furi_assert(message);
+    furi_check(osMessageQueuePut(dispatcher->mqueue, message, 0, osWaitForever) == osOK);
 }
 
 // TODO: bad side-effect
 void dispatcher_recieve(Dispatcher* dispatcher, Message* message) {
-    assert(dispatcher);
-    assert(message);
+    furi_assert(dispatcher);
+    furi_assert(message);
     dispatcher_unlock(dispatcher);
-    assert(osMessageQueueGet(dispatcher->mqueue, message, NULL, osWaitForever) == osOK);
+    furi_check(osMessageQueueGet(dispatcher->mqueue, message, NULL, osWaitForever) == osOK);
     dispatcher_lock(dispatcher);
 }
 
 void dispatcher_lock(Dispatcher* dispatcher) {
-    assert(dispatcher);
-    assert(osMutexAcquire(dispatcher->lock_mutex, osWaitForever) == osOK);
+    furi_assert(dispatcher);
+    furi_check(osMutexAcquire(dispatcher->lock_mutex, osWaitForever) == osOK);
 }
 
 void dispatcher_unlock(Dispatcher* dispatcher) {
-    assert(dispatcher);
-    assert(osMutexRelease(dispatcher->lock_mutex) == osOK);
+    furi_assert(dispatcher);
+    furi_check(osMutexRelease(dispatcher->lock_mutex) == osOK);
 }

+ 12 - 10
applications/nfc/nfc.c

@@ -1,6 +1,5 @@
 #include "nfc.h"
 
-#include <assert.h>
 #include <flipper_v2.h>
 
 #include <gui/gui.h>
@@ -152,7 +151,9 @@ void nfc_worker_task(void* context) {
 }
 
 void nfc_draw_callback(CanvasApi* canvas, void* context) {
-    assert(context);
+    furi_assert(canvas);
+    furi_assert(context);
+
     Nfc* nfc = context;
 
     dispatcher_lock(nfc->dispatcher);
@@ -187,7 +188,8 @@ void nfc_draw_callback(CanvasApi* canvas, void* context) {
 }
 
 void nfc_input_callback(InputEvent* event, void* context) {
-    assert(context);
+    furi_assert(event);
+    furi_assert(context);
     Nfc* nfc = context;
 
     if(!event->state) return;
@@ -196,7 +198,7 @@ void nfc_input_callback(InputEvent* event, void* context) {
 }
 
 void nfc_test_callback(void* context) {
-    assert(context);
+    furi_assert(context);
     Nfc* nfc = context;
 
     dispatcher_lock(nfc->dispatcher);
@@ -213,21 +215,21 @@ void nfc_test_callback(void* context) {
 }
 
 void nfc_read_callback(void* context) {
-    assert(context);
+    furi_assert(context);
     Nfc* nfc = context;
     nfc->screen = 1;
     widget_enabled_set(nfc->widget, true);
 }
 
 void nfc_write_callback(void* context) {
-    assert(context);
+    furi_assert(context);
     Nfc* nfc = context;
     nfc->screen = 1;
     widget_enabled_set(nfc->widget, true);
 }
 
 void nfc_bridge_callback(void* context) {
-    assert(context);
+    furi_assert(context);
     Nfc* nfc = context;
     nfc->screen = 1;
     widget_enabled_set(nfc->widget, true);
@@ -244,7 +246,7 @@ Nfc* nfc_alloc() {
     widget_input_callback_set(nfc->widget, nfc_input_callback, nfc);
 
     nfc->menu_vm = furi_open("menu");
-    assert(nfc->menu_vm);
+    furi_check(nfc->menu_vm);
 
     nfc->menu = menu_item_alloc_menu("NFC", nfc->icon);
     menu_item_subitem_add(
@@ -266,9 +268,9 @@ void nfc_task(void* p) {
     Nfc* nfc = nfc_alloc();
 
     FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL);
-    assert(gui_record);
+    furi_check(gui_record);
     GuiApi* gui = furi_take(gui_record);
-    assert(gui);
+    furi_check(gui);
     widget_enabled_set(nfc->widget, false);
     gui->add_widget(gui, nfc->widget, GuiLayerFullscreen);
     furi_commit(gui_record);

+ 41 - 0
core/api-basic/check.c

@@ -0,0 +1,41 @@
+#include "check.h"
+#include "api-hal-task.h"
+
+void __furi_abort(void);
+
+// TODO printf doesnt work in ISR context
+void __furi_check(void) {
+    printf("assertion failed in release mode, switch to debug mode to see full assert info");
+    __furi_abort();
+}
+
+// TODO printf doesnt work in ISR context
+void __furi_check_debug(const char* file, int line, const char* function, const char* condition) {
+    printf(
+        "assertion \"%s\" failed: file \"%s\", line %d%s%s",
+        condition,
+        file,
+        line,
+        function ? ", function: " : "",
+        function ? function : "");
+
+    if(task_is_isr_context()) {
+        printf(" in [ISR] context");
+    } else {
+        FuriApp* app = find_task(xTaskGetCurrentTaskHandle());
+
+        if(app == NULL) {
+            printf(", in [main] context");
+        } else {
+            printf(", in [%s] app context", app->name);
+        }
+    }
+
+    __furi_abort();
+}
+
+void __furi_abort(void) {
+    taskDISABLE_INTERRUPTS();
+    while(1) {
+    }
+}

+ 41 - 0
core/api-basic/check.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include "flipper.h"
+
+// Find how to how get function's pretty name
+#ifndef __FURI_CHECK_FUNC
+// Use g++'s demangled names in C++
+#if defined __cplusplus && defined __GNUC__
+#define __FURI_CHECK_FUNC __PRETTY_FUNCTION__
+
+// C99 requires the use of __func__
+#elif __STDC_VERSION__ >= 199901L
+#define __FURI_CHECK_FUNC __func__
+
+// Older versions of gcc don't have __func__ but can use __FUNCTION__
+#elif __GNUC__ >= 2
+#define __FURI_CHECK_FUNC __FUNCTION__
+
+// failed to detect __func__ support
+#else
+#define __FURI_CHECK_FUNC ((char*)0)
+#endif
+#endif
+// !__FURI_CHECK_FUNC
+
+// We have two levels of assertion
+// One - furi_check, which always runs, the only difference is in the level of debug information
+// The second is furi_assert, which doesn't compile in release mode
+#ifdef NDEBUG
+#define furi_check(__e) ((__e) ? (void)0 : __furi_check())
+#define furi_assert(__e) ((void)0)
+#else
+#define furi_check(__e) \
+    ((__e) ? (void)0 : __furi_check_debug(__FILE__, __LINE__, __FURI_CHECK_FUNC, #__e))
+#define furi_assert(__e) \
+    ((__e) ? (void)0 : __furi_check_debug(__FILE__, __LINE__, __FURI_CHECK_FUNC, #__e))
+#endif
+// !NDEBUG
+
+void __furi_check(void);
+void __furi_check_debug(const char* file, int line, const char* function, const char* condition);

+ 1 - 1
core/api-basic/valuemutex.h

@@ -49,7 +49,7 @@ static inline void* acquire_mutex_block(ValueMutex* valuemutex) {
 #define with_value_mutex(value_mutex, function_body) \
     {                                                \
         void* p = acquire_mutex_block(value_mutex);  \
-        assert(p);                                   \
+        furi_check(p);                               \
         ({ void __fn__ function_body __fn__; })(p);  \
         release_mutex(value_mutex, p);               \
     }

+ 1 - 0
core/flipper_v2.h

@@ -15,6 +15,7 @@ extern "C" {
 #include "api-basic/event.h"
 
 #include "api-basic/memmgr.h"
+#include "api-basic/check.h"
 
 #include "api-hal/api-gpio.h"
 

+ 54 - 0
firmware/targets/f2/api-hal/api-hal-task.c

@@ -0,0 +1,54 @@
+#include "api-hal-task.h"
+#include "cmsis_os.h"
+
+//-----------------------------cmsis_os2.c-------------------------------
+// helpers to get isr context
+// get arch
+#ifndef __ARM_ARCH_6M__
+#define __ARM_ARCH_6M__ 0
+#endif
+#ifndef __ARM_ARCH_7M__
+#define __ARM_ARCH_7M__ 0
+#endif
+#ifndef __ARM_ARCH_7EM__
+#define __ARM_ARCH_7EM__ 0
+#endif
+#ifndef __ARM_ARCH_8M_MAIN__
+#define __ARM_ARCH_8M_MAIN__ 0
+#endif
+#ifndef __ARM_ARCH_7A__
+#define __ARM_ARCH_7A__ 0
+#endif
+
+// get masks
+#if((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M_MAIN__ == 1U))
+#define IS_IRQ_MASKED() ((__get_PRIMASK() != 0U) || (__get_BASEPRI() != 0U))
+#elif(__ARM_ARCH_6M__ == 1U)
+#define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
+#elif(__ARM_ARCH_7A__ == 1U)
+/* CPSR mask bits */
+#define CPSR_MASKBIT_I 0x80U
+
+#define IS_IRQ_MASKED() ((__get_CPSR() & CPSR_MASKBIT_I) != 0U)
+#else
+#define IS_IRQ_MASKED() (__get_PRIMASK() != 0U)
+#endif
+
+// get is irq mode
+#if(__ARM_ARCH_7A__ == 1U)
+/* CPSR mode bitmasks */
+#define CPSR_MODE_USER 0x10U
+#define CPSR_MODE_SYSTEM 0x1FU
+
+#define IS_IRQ_MODE() ((__get_mode() != CPSR_MODE_USER) && (__get_mode() != CPSR_MODE_SYSTEM))
+#else
+#define IS_IRQ_MODE() (__get_IPSR() != 0U)
+#endif
+
+// added osKernelGetState(), because KernelState is a static var
+#define IS_IRQ() (IS_IRQ_MODE() || (IS_IRQ_MASKED() && (osKernelGetState() == osKernelRunning)))
+//-------------------------end of cmsis_os2.c----------------------------
+
+bool task_is_isr_context(void) {
+    return IS_IRQ();
+}

+ 5 - 0
firmware/targets/f2/api-hal/api-hal-task.h

@@ -0,0 +1,5 @@
+#pragma once
+#include "main.h"
+#include <stdbool.h>
+
+bool task_is_isr_context(void);

+ 1 - 0
firmware/targets/f2/api-hal/api-hal.h

@@ -3,3 +3,4 @@
 #include "api-hal-gpio.h"
 #include "api-hal-delay.h"
 #include "api-hal-pwm.h"
+#include "api-hal-task.h"

+ 5 - 0
firmware/targets/local/api-hal/api-hal-task.c

@@ -0,0 +1,5 @@
+#include "api-hal-task.h"
+
+bool task_is_isr_context(void) {
+    return false;
+}

+ 5 - 0
firmware/targets/local/api-hal/api-hal-task.h

@@ -0,0 +1,5 @@
+#pragma once
+#include "main.h"
+#include <stdbool.h>
+
+bool task_is_isr_context(void);