]> granicus.if.org Git - esp-idf/commitdiff
component/bt : modify alarm APIs to be safely accessible from multiple tasks
authorTian Hao <tianhao@espressif.com>
Thu, 9 Mar 2017 12:46:19 +0000 (20:46 +0800)
committerwangmengyang <wangmengyang@espressif.com>
Wed, 5 Apr 2017 09:34:26 +0000 (17:34 +0800)
components/bt/bluedroid/btc/core/btc_main.c
components/bt/bluedroid/main/bte_main.c
components/bt/bluedroid/osi/alarm.c
components/bt/bluedroid/osi/include/alarm.h

index 323a81f75ac98ff755dc22a86cea3318d875f4fe..8394c8a44d4c81b093296b38c9dd8f3138a564b1 100644 (file)
@@ -16,6 +16,7 @@
 #include "btc_main.h"
 #include "future.h"
 #include "esp_err.h"
+#include "alarm.h"
 
 static future_t *main_future[BTC_MAIN_FUTURE_NUM];
 
@@ -60,6 +61,8 @@ void btc_init_callback(void)
 
 static void btc_init_bluetooth(void)
 {
+    osi_alarm_create_mux();
+    osi_alarm_init();
     bte_main_boot_entry(btc_init_callback);
 }
 
@@ -67,6 +70,8 @@ static void btc_init_bluetooth(void)
 static void btc_deinit_bluetooth(void)
 {
     bte_main_shutdown();
+    osi_alarm_deinit();
+    osi_alarm_delete_mux();
     future_ready(*btc_main_get_future_p(BTC_MAIN_DEINIT_FUTURE), FUTURE_SUCCESS);
 }
 
index 1ca3946d62d4747931185523c2558b4ee04f1440..1b74d558fdb9e34e0464fd1c97f9901ec8e30eda 100644 (file)
@@ -144,8 +144,6 @@ int bte_main_boot_entry(bluedroid_init_done_cb_t cb)
     //data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);
     hci->set_data_queue(btu_hci_msg_queue);
 
-    osi_alarm_init();
-
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
     //bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);
 #endif
index 6ef8d304adac2baae66c10bf17fdeff7b1d6a225..3d36be7270ecfc729a6d3376a400c74cd4c96fac 100644 (file)
 #define BT_ALARM_FREE_WAIT_TICKS    100
 #define BT_ALARM_CHG_PERIOD_WAIT_TICKS  100
 
+enum {
+    ALARM_STATE_IDLE,
+    ALARM_STATE_OPEN,
+};
+
+static osi_mutex_t alarm_mutex;
+static int alarm_state;
+
 static struct alarm_t alarm_cbs[ALARM_CBS_NUM];
 
+static int alarm_free(osi_alarm_t *alarm);
+
+int osi_alarm_create_mux(void)
+{
+    if (alarm_state != ALARM_STATE_IDLE) {
+        LOG_WARN("%s, invalid state %d\n", __func__, alarm_state);
+        return -1;
+    }
+    osi_mutex_new(&alarm_mutex);
+    return 0;
+}
+
+int osi_alarm_delete_mux(void)
+{
+    if (alarm_state != ALARM_STATE_IDLE) {
+        LOG_WARN("%s, invalid state %d\n", __func__, alarm_state);
+        return -1;
+    }
+    osi_mutex_free(&alarm_mutex);
+    return 0;
+}
+    
 void osi_alarm_init(void)
 {
-    memset(&alarm_cbs[0], 0x00, sizeof(alarm_cbs));
+    assert(alarm_mutex != NULL);
+    
+    osi_mutex_lock(&alarm_mutex);
+    if (alarm_state != ALARM_STATE_IDLE) {
+        LOG_WARN("%s, invalid state %d\n", __func__, alarm_state);
+        goto end;
+    }
+    memset(alarm_cbs, 0x00, sizeof(alarm_cbs));
+    alarm_state = ALARM_STATE_OPEN;
+    
+end:
+    osi_mutex_unlock(&alarm_mutex);
+}
+
+void osi_alarm_deinit(void)
+{
+    assert(alarm_mutex != NULL);
+    
+    osi_mutex_lock(&alarm_mutex);
+    if (alarm_state != ALARM_STATE_OPEN) {
+        LOG_WARN("%s, invalid state %d\n", __func__, alarm_state);
+        goto end;
+    }
+    
+    for (int i = 0; i < ALARM_CBS_NUM; i++) {
+        if (alarm_cbs[i].alarm_hdl != NULL) {
+            alarm_free(&alarm_cbs[i]);
+        }
+    }
+    alarm_state = ALARM_STATE_IDLE;
+
+end:
+    osi_mutex_unlock(&alarm_mutex);
 }
 
 static struct alarm_t *alarm_cbs_lookfor_available(void)
@@ -75,88 +137,141 @@ static void alarm_cb_handler(TimerHandle_t xTimer)
 
 osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire)
 {
-    struct alarm_t *timer_id;
-    TimerHandle_t t;
-
-    if (timer_expire == 0) {
-        timer_expire = 1000;
+    assert(alarm_mutex != NULL);
+
+    struct alarm_t *timer_id = NULL;
+    
+    osi_mutex_lock(&alarm_mutex);
+    if (alarm_state != ALARM_STATE_OPEN) {
+        LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
+        timer_id = NULL;
+        goto end;
     }
-
-    /* TODO mutex lock */
+    
     timer_id = alarm_cbs_lookfor_available();
+
     if (!timer_id) {
-        LOG_ERROR("%s full\n", __func__);
-        return NULL;
+        LOG_ERROR("%s alarm_cbs exhausted\n", __func__);
+        timer_id = NULL;
+        goto end;
+    }
+
+    if (timer_expire == 0) {
+        timer_expire = 1000;
     }
 
-    t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler);
+    TimerHandle_t t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler);
     if (!t) {
-        LOG_ERROR("%s error\n", __func__);
-        return NULL;
+        LOG_ERROR("%s failed to create timer\n", __func__);
+        timer_id = NULL;
+        goto end;
     }
 
     timer_id->alarm_hdl = t;
     timer_id->cb = callback;
     timer_id->cb_data = data;
-    /* TODO mutex unlock */
 
+end:
+    osi_mutex_unlock(&alarm_mutex);
     return timer_id;
 }
 
-int osi_alarm_free(osi_alarm_t *alarm)
+static int alarm_free(osi_alarm_t *alarm)
 {
-    if (!alarm) {
+    if (!alarm || alarm->alarm_hdl == NULL) {
         LOG_ERROR("%s null\n", __func__);
         return -1;
     }
 
     if (xTimerDelete(alarm->alarm_hdl, BT_ALARM_FREE_WAIT_TICKS) != pdPASS) {
-        LOG_ERROR("%s error\n", __func__);
+        LOG_ERROR("%s alarm delete error\n", __func__);
         return -2;
     }
+    
+    memset(alarm, 0, sizeof(osi_alarm_t));
+    return 0;
+}
 
-    /* TODO mutex lock */
-    memset(alarm, 0x00, sizeof(osi_alarm_t));
-    /* TODO mutex unlock */
+int osi_alarm_free(osi_alarm_t *alarm)
+{
+    assert(alarm_mutex != NULL);
+    
+    int ret = 0;
+    osi_mutex_lock(&alarm_mutex);
+    if (alarm_state != ALARM_STATE_OPEN) {
+        LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
+        ret = -3;
+        goto end;
+    }
+    alarm_free(alarm);
 
-    return 0;
+end:
+    osi_mutex_unlock(&alarm_mutex);
+    return ret;
 }
 
 
 int osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout)
 {
-    if (!alarm) {
+    assert(alarm_mutex != NULL);
+    
+    int ret = 0;
+    osi_mutex_lock(&alarm_mutex);
+    if (alarm_state != ALARM_STATE_OPEN) {
+        LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
+        ret = -3;
+        goto end;
+    }
+    
+    if (!alarm || alarm->alarm_hdl == NULL) {
         LOG_ERROR("%s null\n", __func__);
-        return -1;
+        ret = -1;
+        goto end;
     }
-
+    
     if (xTimerChangePeriod(alarm->alarm_hdl, timeout / portTICK_PERIOD_MS, BT_ALARM_CHG_PERIOD_WAIT_TICKS) != pdPASS) {
         LOG_ERROR("%s chg period error\n", __func__);
-        return -2;
+        ret = -2;
+        goto end;
     }
 
     if (xTimerStart(alarm->alarm_hdl, BT_ALARM_START_WAIT_TICKS) != pdPASS) {
         LOG_ERROR("%s start error\n", __func__);
-        return -3;
+        ret = -2;
+        goto end;
     }
 
-    return 0;
+end:
+    osi_mutex_unlock(&alarm_mutex);
+    return ret;
 }
 
 
 int osi_alarm_cancel(osi_alarm_t *alarm)
 {
-    if (!alarm) {
+    int ret = 0;
+    osi_mutex_lock(&alarm_mutex);
+    if (alarm_state != ALARM_STATE_OPEN) {
+        LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
+        ret = -3;
+        goto end;
+    }
+    
+    if (!alarm || alarm->alarm_hdl == NULL) {
         LOG_ERROR("%s null\n", __func__);
-        return -1;
+        ret = -1;
+        goto end;
     }
 
     if (xTimerStop(alarm->alarm_hdl, BT_ALARM_STOP_WAIT_TICKS) != pdPASS) {
-        LOG_ERROR("%s error\n", __func__);
-        return -2;
+        LOG_ERROR("%s failed to stop timer\n", __func__);
+        ret = -2;
+        goto end;
     }
 
-    return 0;
+end:
+    osi_mutex_unlock(&alarm_mutex);
+    return ret;
 }
 
 static uint32_t alarm_current_tick(void)
index 2e226ed27f62dcaea356ff815b18c9693d067223..35c0f4666b218718b42d39f16adf18fed8bd2eb4 100644 (file)
@@ -35,7 +35,10 @@ typedef struct alarm_t {
     void *cb_data;
 } osi_alarm_t;
 
+int osi_alarm_create_mux(void);
+int osi_alarm_delete_mux(void);
 void osi_alarm_init(void);
+void osi_alarm_deinit(void);
 
 // Creates a new alarm object. The returned object must be freed by calling
 // |alarm_free|. Returns NULL on failure.