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

Protect screen refresh from switch_view() with a mutex.

antirez 3 лет назад
Родитель
Сommit
2a791b176a
3 измененных файлов с 14 добавлено и 2 удалено
  1. 7 0
      app.c
  2. 4 0
      app.h
  3. 3 2
      view_direct_sampling.c

+ 7 - 0
app.c

@@ -16,6 +16,7 @@ extern const SubGhzProtocolRegistry protoview_protocol_registry;
  * and setting color to black. */
 static void render_callback(Canvas *const canvas, void *ctx) {
     ProtoViewApp *app = ctx;
+    furi_mutex_acquire(app->view_updating_mutex,FuriWaitForever);
 
     /* Clear screen. */
     canvas_set_color(canvas, ColorWhite);
@@ -37,6 +38,7 @@ static void render_callback(Canvas *const canvas, void *ctx) {
 
     /* Draw the alert box if set. */
     ui_draw_alert_if_needed(canvas, app);
+    furi_mutex_release(app->view_updating_mutex);
 }
 
 /* Here all we do is putting the events into the queue that will be handled
@@ -55,6 +57,8 @@ static void input_callback(InputEvent* input_event, void* ctx)
  * special views ViewGoNext and ViewGoPrev in order to move to
  * the logical next/prev view. */
 static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) {
+    furi_mutex_acquire(app->view_updating_mutex,FuriWaitForever);
+
     /* Switch to the specified view. */
     ProtoViewCurrentView old = app->current_view;
     if (switchto == ViewGoNext) {
@@ -98,6 +102,7 @@ static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) {
     /* If there is an alert on screen, dismiss it: if the user is
      * switching view she already read it. */
     ui_dismiss_alert(app);
+    furi_mutex_release(app->view_updating_mutex);
 }
 
 /* Allocate the application state and initialize a number of stuff.
@@ -126,6 +131,7 @@ ProtoViewApp* protoview_app_alloc() {
     app->show_text_input = false;
     app->alert_dismiss_time = 0;
     app->current_view = ViewRawPulses;
+    app->view_updating_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
     for (int j = 0; j < ViewLast; j++) app->current_subview[j] = 0;
     app->direct_sampling_enabled = false;
     app->view_privdata = malloc(PROTOVIEW_VIEW_PRIVDATA_LEN);
@@ -173,6 +179,7 @@ void protoview_app_free(ProtoViewApp *app) {
     furi_record_close(RECORD_GUI);
     furi_record_close(RECORD_NOTIFICATION);
     furi_message_queue_free(app->event_queue);
+    furi_mutex_free(app->view_updating_mutex);
     app->gui = NULL;
 
     // Frequency setting.

+ 4 - 0
app.h

@@ -102,6 +102,10 @@ struct ProtoViewApp {
     ViewPort *view_port;     /* We just use a raw viewport and we render
                                 everything into the low level canvas. */
     ProtoViewCurrentView current_view;      /* Active left-right view ID. */
+    FuriMutex *view_updating_mutex; /* The Flipper GUI calls the screen redraw
+                                       callback in a different thread. We
+                                       use this mutex to protect the redraw
+                                       from changes in app->view_privdata. */
     int current_subview[ViewLast];  /* Active up-down subview ID. */
     FuriMessageQueue *event_queue;  /* Keypress events go here. */
 

+ 3 - 2
view_direct_sampling.c

@@ -32,6 +32,8 @@ void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) {
         privdata->captured = malloc(CAPTURED_BITMAP_SIZE);
 
     /* Read from data from GPIO */
+    if (privdata->captured == NULL)
+        FURI_LOG_E(TAG, "captured is NULL reading GPIO.");
     for (int j = 0; j < CAPTURED_BITMAP_SIZE*8; j++) {
         uint32_t start_time = DWT->CYCCNT;
         bool level = furi_hal_gpio_read(&gpio_cc1101_g0);
@@ -91,8 +93,7 @@ void view_enter_direct_sampling(ProtoViewApp *app) {
 /* Exit view. Restore the subghz thread. */
 void view_exit_direct_sampling(ProtoViewApp *app) {
     DirectSamplingViewPrivData *privdata = app->view_privdata;
-    free(privdata->captured);
-    privdata->captured = NULL;
+    if (privdata->captured) free(privdata->captured);
     app->direct_sampling_enabled = false;
 
     /* Restart normal data feeding. */