[FL-2383, FL-2384] iButton, Desktop bug fixes (#1062)

* iButton HAL: correct init and emulation sequence
* FuriHal: cleanup init/deinit routines for emulation timer
* FuriHal: cleanup TIM initialization routines in RFID and SubGhz
* iButton: delay in emulate loop
* Desktop: fix crash caused by invalid animation manager state, described in FL-2384

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
SG 2022-03-28 23:42:31 +10:00 committed by GitHub
parent 413a03defb
commit 425a74a001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 55 additions and 74 deletions

View File

@ -4,8 +4,6 @@
#include <furi.h> #include <furi.h>
#include <furi_hal.h> #include <furi_hal.h>
#include <loader/loader.h>
#include "animations/animation_manager.h" #include "animations/animation_manager.h"
#include "desktop/scenes/desktop_scene.h" #include "desktop/scenes/desktop_scene.h"
#include "desktop/scenes/desktop_scene_i.h" #include "desktop/scenes/desktop_scene_i.h"
@ -15,6 +13,18 @@
#include "desktop_i.h" #include "desktop_i.h"
#include "desktop_helpers.h" #include "desktop_helpers.h"
static void desktop_loader_callback(const void* message, void* context) {
furi_assert(context);
Desktop* desktop = context;
const LoaderEvent* event = message;
if(event->type == LoaderEventTypeApplicationStarted) {
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalBeforeAppStarted);
} else if(event->type == LoaderEventTypeApplicationStopped) {
view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished);
}
}
static void desktop_lock_icon_callback(Canvas* canvas, void* context) { static void desktop_lock_icon_callback(Canvas* canvas, void* context) {
furi_assert(canvas); furi_assert(canvas);
canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8);
@ -23,6 +33,16 @@ static void desktop_lock_icon_callback(Canvas* canvas, void* context) {
static bool desktop_custom_event_callback(void* context, uint32_t event) { static bool desktop_custom_event_callback(void* context, uint32_t event) {
furi_assert(context); furi_assert(context);
Desktop* desktop = (Desktop*)context; Desktop* desktop = (Desktop*)context;
switch(event) {
case DesktopGlobalBeforeAppStarted:
animation_manager_unload_and_stall_animation(desktop->animation_manager);
return true;
case DesktopGlobalAfterAppFinished:
animation_manager_load_and_continue_animation(desktop->animation_manager);
return true;
}
return scene_manager_handle_custom_event(desktop->scene_manager, event); return scene_manager_handle_custom_event(desktop->scene_manager, event);
} }
@ -41,7 +61,6 @@ static void desktop_tick_event_callback(void* context) {
Desktop* desktop_alloc() { Desktop* desktop_alloc() {
Desktop* desktop = malloc(sizeof(Desktop)); Desktop* desktop = malloc(sizeof(Desktop));
desktop->unload_animation_semaphore = osSemaphoreNew(1, 0, NULL);
desktop->animation_manager = animation_manager_alloc(); desktop->animation_manager = animation_manager_alloc();
desktop->gui = furi_record_open("gui"); desktop->gui = furi_record_open("gui");
desktop->scene_thread = furi_thread_alloc(); desktop->scene_thread = furi_thread_alloc();
@ -122,12 +141,13 @@ Desktop* desktop_alloc() {
gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft); gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft);
// Special case: autostart application is already running // Special case: autostart application is already running
Loader* loader = furi_record_open("loader"); desktop->loader = furi_record_open("loader");
if(loader_is_locked(loader) && if(loader_is_locked(desktop->loader) &&
animation_manager_is_animation_loaded(desktop->animation_manager)) { animation_manager_is_animation_loaded(desktop->animation_manager)) {
animation_manager_unload_and_stall_animation(desktop->animation_manager); animation_manager_unload_and_stall_animation(desktop->animation_manager);
} }
furi_record_close("loader"); desktop->app_start_stop_subscription = furi_pubsub_subscribe(
loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop);
return desktop; return desktop;
} }
@ -135,6 +155,11 @@ Desktop* desktop_alloc() {
void desktop_free(Desktop* desktop) { void desktop_free(Desktop* desktop) {
furi_assert(desktop); furi_assert(desktop);
furi_pubsub_unsubscribe(
loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription);
desktop->loader = NULL;
furi_record_close("loader");
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain);
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu);
view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked);
@ -159,8 +184,6 @@ void desktop_free(Desktop* desktop) {
popup_free(desktop->hw_mismatch_popup); popup_free(desktop->hw_mismatch_popup);
desktop_view_pin_timeout_free(desktop->pin_timeout_view); desktop_view_pin_timeout_free(desktop->pin_timeout_view);
osSemaphoreDelete(desktop->unload_animation_semaphore);
furi_record_close("gui"); furi_record_close("gui");
desktop->gui = NULL; desktop->gui = NULL;

View File

@ -18,6 +18,8 @@
#include <gui/modules/popup.h> #include <gui/modules/popup.h>
#include <gui/scene_manager.h> #include <gui/scene_manager.h>
#include <loader/loader.h>
#define STATUS_BAR_Y_SHIFT 13 #define STATUS_BAR_Y_SHIFT 13
typedef enum { typedef enum {
@ -57,7 +59,7 @@ struct Desktop {
ViewPort* lock_viewport; ViewPort* lock_viewport;
AnimationManager* animation_manager; AnimationManager* animation_manager;
osSemaphoreId_t unload_animation_semaphore; Loader* loader;
FuriPubSubSubscription* app_start_stop_subscription; FuriPubSubSubscription* app_start_stop_subscription;
}; };

View File

@ -60,10 +60,8 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER);
scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked);
} else { } else {
Loader* loader = furi_record_open("loader");
LoaderStatus status = LoaderStatus status =
loader_start(loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG);
furi_record_close("loader");
if(status == LoaderStatusOk) { if(status == LoaderStatusOk) {
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1);
} else { } else {

View File

@ -12,21 +12,6 @@
#define TAG "DesktopSrv" #define TAG "DesktopSrv"
static void desktop_scene_main_app_started_callback(const void* message, void* context) {
furi_assert(context);
Desktop* desktop = context;
const LoaderEvent* event = message;
if(event->type == LoaderEventTypeApplicationStarted) {
view_dispatcher_send_custom_event(
desktop->view_dispatcher, DesktopMainEventBeforeAppStarted);
osSemaphoreAcquire(desktop->unload_animation_semaphore, osWaitForever);
} else if(event->type == LoaderEventTypeApplicationStopped) {
view_dispatcher_send_custom_event(
desktop->view_dispatcher, DesktopMainEventAfterAppFinished);
}
}
static void desktop_scene_main_new_idle_animation_callback(void* context) { static void desktop_scene_main_new_idle_animation_callback(void* context) {
furi_assert(context); furi_assert(context);
Desktop* desktop = context; Desktop* desktop = context;
@ -85,12 +70,6 @@ void desktop_scene_main_on_enter(void* context) {
animation_manager_set_interact_callback( animation_manager_set_interact_callback(
desktop->animation_manager, desktop_scene_main_interact_animation_callback); desktop->animation_manager, desktop_scene_main_interact_animation_callback);
furi_assert(osSemaphoreGetCount(desktop->unload_animation_semaphore) == 0);
Loader* loader = furi_record_open("loader");
desktop->app_start_stop_subscription = furi_pubsub_subscribe(
loader_get_pubsub(loader), desktop_scene_main_app_started_callback, desktop);
furi_record_close("loader");
desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop); desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop);
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain);
@ -127,13 +106,11 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
case DesktopMainEventOpenFavorite: case DesktopMainEventOpenFavorite:
LOAD_DESKTOP_SETTINGS(&desktop->settings); LOAD_DESKTOP_SETTINGS(&desktop->settings);
if(desktop->settings.favorite < FLIPPER_APPS_COUNT) { if(desktop->settings.favorite < FLIPPER_APPS_COUNT) {
Loader* loader = furi_record_open("loader"); LoaderStatus status = loader_start(
LoaderStatus status = desktop->loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL);
loader_start(loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL);
if(status != LoaderStatusOk) { if(status != LoaderStatusOk) {
FURI_LOG_E(TAG, "loader_start failed: %d", status); FURI_LOG_E(TAG, "loader_start failed: %d", status);
} }
furi_record_close("loader");
} else { } else {
FURI_LOG_E(TAG, "Can't find favorite application"); FURI_LOG_E(TAG, "Can't find favorite application");
} }
@ -152,15 +129,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
animation_manager_interact_process(desktop->animation_manager); animation_manager_interact_process(desktop->animation_manager);
consumed = true; consumed = true;
break; break;
case DesktopMainEventBeforeAppStarted:
animation_manager_unload_and_stall_animation(desktop->animation_manager);
osSemaphoreRelease(desktop->unload_animation_semaphore);
consumed = true;
break;
case DesktopMainEventAfterAppFinished:
animation_manager_load_and_continue_animation(desktop->animation_manager);
consumed = true;
break;
case DesktopLockedEventUpdate: case DesktopLockedEventUpdate:
desktop_view_locked_update(desktop->locked_view); desktop_view_locked_update(desktop->locked_view);
consumed = true; consumed = true;
@ -177,16 +145,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
void desktop_scene_main_on_exit(void* context) { void desktop_scene_main_on_exit(void* context) {
Desktop* desktop = (Desktop*)context; Desktop* desktop = (Desktop*)context;
/**
* We're allowed to leave this scene only when any other app & loader
* is finished, that's why we can be sure there is no task waiting
* for start/stop semaphore
*/
Loader* loader = furi_record_open("loader");
furi_pubsub_unsubscribe(loader_get_pubsub(loader), desktop->app_start_stop_subscription);
furi_record_close("loader");
furi_assert(osSemaphoreGetCount(desktop->unload_animation_semaphore) == 0);
animation_manager_set_new_idle_callback(desktop->animation_manager, NULL); animation_manager_set_new_idle_callback(desktop->animation_manager, NULL);
animation_manager_set_check_callback(desktop->animation_manager, NULL); animation_manager_set_check_callback(desktop->animation_manager, NULL);
animation_manager_set_interact_callback(desktop->animation_manager, NULL); animation_manager_set_interact_callback(desktop->animation_manager, NULL);

View File

@ -7,8 +7,6 @@ typedef enum {
DesktopMainEventOpenMenu, DesktopMainEventOpenMenu,
DesktopMainEventOpenDebug, DesktopMainEventOpenDebug,
DesktopMainEventRightShort, DesktopMainEventRightShort,
DesktopMainEventBeforeAppStarted,
DesktopMainEventAfterAppFinished,
DesktopLockedEventUnlocked, DesktopLockedEventUnlocked,
DesktopLockedEventUpdate, DesktopLockedEventUpdate,
@ -37,4 +35,7 @@ typedef enum {
DesktopAnimationEventNewIdleAnimation, DesktopAnimationEventNewIdleAnimation,
DesktopAnimationEventInteractAnimation, DesktopAnimationEventInteractAnimation,
// Global events
DesktopGlobalBeforeAppStarted,
DesktopGlobalAfterAppFinished,
} DesktopEvent; } DesktopEvent;

View File

@ -209,6 +209,7 @@ void ibutton_cli_emulate(Cli* cli, string_t args) {
while(!exit) { while(!exit) {
exit = cli_cmd_interrupt_received(cli); exit = cli_cmd_interrupt_received(cli);
delay(100);
}; };
worker->stop_emulate(); worker->stop_emulate();

View File

@ -49,6 +49,11 @@ void furi_hal_ibutton_emulate_start(
LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER); LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER);
FURI_CRITICAL_EXIT(); FURI_CRITICAL_EXIT();
furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, furi_hal_ibutton_emulate_isr);
NVIC_SetPriority(
FURI_HAL_IBUTTON_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(FURI_HAL_IBUTTON_TIMER_IRQ);
LL_TIM_SetPrescaler(FURI_HAL_IBUTTON_TIMER, 0); LL_TIM_SetPrescaler(FURI_HAL_IBUTTON_TIMER, 0);
LL_TIM_SetCounterMode(FURI_HAL_IBUTTON_TIMER, LL_TIM_COUNTERMODE_UP); LL_TIM_SetCounterMode(FURI_HAL_IBUTTON_TIMER, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetAutoReload(FURI_HAL_IBUTTON_TIMER, period); LL_TIM_SetAutoReload(FURI_HAL_IBUTTON_TIMER, period);
@ -61,12 +66,6 @@ void furi_hal_ibutton_emulate_start(
LL_TIM_EnableIT_UPDATE(FURI_HAL_IBUTTON_TIMER); LL_TIM_EnableIT_UPDATE(FURI_HAL_IBUTTON_TIMER);
furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, furi_hal_ibutton_emulate_isr);
NVIC_SetPriority(
FURI_HAL_IBUTTON_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(FURI_HAL_IBUTTON_TIMER_IRQ);
LL_TIM_EnableCounter(FURI_HAL_IBUTTON_TIMER); LL_TIM_EnableCounter(FURI_HAL_IBUTTON_TIMER);
} }
@ -80,6 +79,11 @@ void furi_hal_ibutton_emulate_stop() {
if(furi_hal_ibutton->state == FuriHalIbuttonStateRunning) { if(furi_hal_ibutton->state == FuriHalIbuttonStateRunning) {
furi_hal_ibutton->state = FuriHalIbuttonStateIdle; furi_hal_ibutton->state = FuriHalIbuttonStateIdle;
LL_TIM_DisableCounter(FURI_HAL_IBUTTON_TIMER); LL_TIM_DisableCounter(FURI_HAL_IBUTTON_TIMER);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER);
FURI_CRITICAL_EXIT();
furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, NULL); furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, NULL);
furi_hal_ibutton->callback = NULL; furi_hal_ibutton->callback = NULL;

View File

@ -193,7 +193,6 @@ void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void*
} }
furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, furi_hal_rfid_emulate_isr); furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, furi_hal_rfid_emulate_isr);
NVIC_SetPriority( NVIC_SetPriority(
FURI_HAL_RFID_EMULATE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); FURI_HAL_RFID_EMULATE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(FURI_HAL_RFID_EMULATE_TIMER_IRQ); NVIC_EnableIRQ(FURI_HAL_RFID_EMULATE_TIMER_IRQ);
@ -204,9 +203,9 @@ void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void*
} }
void furi_hal_rfid_tim_emulate_stop() { void furi_hal_rfid_tim_emulate_stop() {
furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, NULL);
LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER); LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER);
LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER); LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, NULL);
} }
void furi_hal_rfid_tim_reset() { void furi_hal_rfid_tim_reset() {

View File

@ -732,10 +732,6 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1); LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
// Enable NVIC
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(TIM2_IRQn);
// Start timer // Start timer
LL_TIM_SetCounter(TIM2, 0); LL_TIM_SetCounter(TIM2, 0);
LL_TIM_EnableCounter(TIM2); LL_TIM_EnableCounter(TIM2);
@ -919,6 +915,9 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
LL_TIM_DisableMasterSlaveMode(TIM2); LL_TIM_DisableMasterSlaveMode(TIM2);
furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_async_tx_timer_isr); furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_async_tx_timer_isr);
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(TIM2_IRQn);
LL_TIM_EnableIT_UPDATE(TIM2); LL_TIM_EnableIT_UPDATE(TIM2);
LL_TIM_EnableDMAReq_UPDATE(TIM2); LL_TIM_EnableDMAReq_UPDATE(TIM2);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
@ -930,10 +929,6 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
#endif #endif
furi_hal_subghz_tx(); furi_hal_subghz_tx();
// Enable NVIC
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(TIM2_IRQn);
LL_TIM_SetCounter(TIM2, 0); LL_TIM_SetCounter(TIM2, 0);
LL_TIM_EnableCounter(TIM2); LL_TIM_EnableCounter(TIM2);
return true; return true;