]> granicus.if.org Git - esp-idf/commitdiff
component/bt: modify the implementation and interface of osi_alarm module
authorwangmengyang <wangmengyang@espressif.com>
Wed, 8 Nov 2017 09:12:08 +0000 (17:12 +0800)
committerwangmengyang <wangmengyang@espressif.com>
Fri, 10 Nov 2017 03:53:55 +0000 (11:53 +0800)
1. use esp_timer instead of FreeRTOS timer to implement osi_alarm in bluedroid
2. Remove two APIs: osi_alarm_now() and osi_alarm_time_diff() and modify the hci layer logic that use them
3. Implement osi_alarm_get_remaining_ms()
4. Move the definition of struct alarm_t in source file "alarm.c"
5. Add definition of module error code

components/bt/bluedroid/hci/hci_layer.c
components/bt/bluedroid/osi/alarm.c
components/bt/bluedroid/osi/include/alarm.h

index cbf180f7ecd6f1b1e172803e5480e1e4d0b771c4..9519fd1d27284d5a763f20525b6437556adef21e 100644 (file)
@@ -40,7 +40,6 @@ typedef struct {
     command_complete_cb complete_callback;
     command_status_cb status_callback;
     void *context;
-    uint32_t sent_time;
     BT_HDR *command;
 } waiting_command_t;
 
@@ -90,9 +89,7 @@ static void hci_layer_deinit_env(void);
 static void hci_host_thread_handler(void *arg);
 static void event_command_ready(fixed_queue_t *queue);
 static void event_packet_ready(fixed_queue_t *queue);
-static void restart_comamnd_waiting_response_timer(
-    command_waiting_response_t *cmd_wait_q,
-    bool tigger_by_sending_command);
+static void restart_command_waiting_response_timer(command_waiting_response_t *cmd_wait_q);
 static void command_timed_out(void *context);
 static void hal_says_packet_ready(BT_HDR *packet);
 static bool filter_incoming_event(BT_HDR *packet);
@@ -330,8 +327,7 @@ static void event_command_ready(fixed_queue_t *queue)
     // Send it off
     packet_fragmenter->fragment_and_dispatch(wait_entry->command);
 
-    wait_entry->sent_time = osi_alarm_now();
-    restart_comamnd_waiting_response_timer(cmd_wait_q, true);
+    restart_command_waiting_response_timer(cmd_wait_q);
 }
 
 static void event_packet_ready(fixed_queue_t *queue)
@@ -377,41 +373,18 @@ static void fragmenter_transmit_finished(BT_HDR *packet, bool all_fragments_sent
     }
 }
 
-static void restart_comamnd_waiting_response_timer(
-    command_waiting_response_t *cmd_wait_q,
-    bool tigger_by_sending_command)
+static void restart_command_waiting_response_timer(command_waiting_response_t *cmd_wait_q)
 {
-    uint32_t timeout;
-    waiting_command_t *wait_entry;
-    if (!cmd_wait_q) {
-        return;
-    }
-
+    osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT);
     if (cmd_wait_q->timer_is_set) {
-        if (tigger_by_sending_command) {
-            return;
-        }
-
-        //Cancel Previous command timeout timer setted when sending command
         osi_alarm_cancel(cmd_wait_q->command_response_timer);
         cmd_wait_q->timer_is_set = false;
     }
-
-    osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT);
-    wait_entry = (list_is_empty(cmd_wait_q->commands_pending_response) ?
-                  NULL : list_front(cmd_wait_q->commands_pending_response));
-    osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
-
-    if (wait_entry == NULL) {
-        return;
+    if (!list_is_empty(cmd_wait_q->commands_pending_response)) {
+        osi_alarm_set(cmd_wait_q->command_response_timer, COMMAND_PENDING_TIMEOUT);
+        cmd_wait_q->timer_is_set = true;
     }
-
-    timeout = osi_alarm_time_diff(osi_alarm_now(), wait_entry->sent_time);
-    timeout = osi_alarm_time_diff(COMMAND_PENDING_TIMEOUT, timeout);
-    timeout = (timeout <= COMMAND_PENDING_TIMEOUT) ? timeout : COMMAND_PENDING_TIMEOUT;
-
-    cmd_wait_q->timer_is_set = true;
-    osi_alarm_set(cmd_wait_q->command_response_timer, timeout);
+    osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
 }
 
 static void command_timed_out(void *context)
@@ -493,7 +466,7 @@ static bool filter_incoming_event(BT_HDR *packet)
 
     return false;
 intercepted:
-    restart_comamnd_waiting_response_timer(&hci_host_env.cmd_waiting_q, false);
+    restart_command_waiting_response_timer(&hci_host_env.cmd_waiting_q);
 
     /*Tell HCI Host Task to continue TX Pending commands*/
     if (hci_host_env.command_credits &&
index 98d2aefef9b57ec2b3733087e8b55e8474177561..034ff902c88d0846dfba457c734f328a7a6e790d 100644 (file)
 #include "alarm.h"
 #include "allocator.h"
 #include "list.h"
-#include "thread.h"
-#include "freertos/FreeRTOSConfig.h"
-#include "freertos/xtensa_api.h"
-#include "rom/ets_sys.h"
+#include "esp_timer.h"
 #include "btc_task.h"
 #include "btc_alarm.h"
 #include "mutex.h"
-#include "time.h"
 
-#define RTC_TIMER_TICKS_TO_MS(ticks)            (((ticks/625)<<1) + (ticks-(ticks/625)*625)/312)
-
-
-#define BT_ALARM_START_WAIT_TICKS   100
-#define BT_ALARM_STOP_WAIT_TICKS    100
-#define BT_ALARM_FREE_WAIT_TICKS    100
-#define BT_ALARM_CHG_PERIOD_WAIT_TICKS  100
+typedef struct alarm_t {
+    /* timer id point to here */
+    esp_timer_handle_t alarm_hdl;
+    osi_alarm_callback_t cb;
+    void *cb_data;
+    int64_t deadline_us;
+} osi_alarm_t;
 
 enum {
     ALARM_STATE_IDLE,
@@ -50,7 +46,7 @@ static int alarm_state;
 
 static struct alarm_t alarm_cbs[ALARM_CBS_NUM];
 
-static int alarm_free(osi_alarm_t *alarm);
+static osi_alarm_err_t alarm_free(osi_alarm_t *alarm);
 
 int osi_alarm_create_mux(void)
 {
@@ -123,17 +119,9 @@ static struct alarm_t *alarm_cbs_lookfor_available(void)
     return NULL;
 }
 
-static void alarm_cb_handler(TimerHandle_t xTimer)
+static void alarm_cb_handler(struct alarm_t *alarm)
 {
-    struct alarm_t *alarm;
-    if (!xTimer) {
-        LOG_ERROR("TimerName: NULL\n");
-        return;
-    }
-    
-    alarm = pvTimerGetTimerID(xTimer);
-    LOG_DEBUG("TimerID %p, Name %s\n", alarm, pcTimerGetTimerName(xTimer));
-    
+    LOG_DEBUG("TimerID %p\n", alarm);
     btc_msg_t msg;
     btc_alarm_args_t arg;
     msg.sig = BTC_SIG_API_CALL;
@@ -143,7 +131,7 @@ static void alarm_cb_handler(TimerHandle_t xTimer)
     btc_transfer_context(&msg, &arg, sizeof(btc_alarm_args_t), NULL);
 }
 
-osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire)
+osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire)
 {
     assert(alarm_mutex != NULL);
 
@@ -164,161 +152,133 @@ osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void
         goto end;
     }
 
-    if (timer_expire == 0) {
-        timer_expire = 1000;
-    }
+    esp_timer_create_args_t tca;
+    tca.callback = (esp_timer_cb_t)alarm_cb_handler;
+    tca.arg = timer_id;
+    tca.dispatch_method = ESP_TIMER_TASK;
+    tca.name = alarm_name;
 
-    TimerHandle_t t = xTimerCreate(alarm_name, timer_expire / portTICK_PERIOD_MS, pdFALSE, timer_id, alarm_cb_handler);
-    if (!t) {
-        LOG_ERROR("%s failed to create timer\n", __func__);
+    timer_id->cb = callback;
+    timer_id->cb_data = data;
+    timer_id->deadline_us = 0;
+    
+    esp_err_t stat = esp_timer_create(&tca, &timer_id->alarm_hdl);
+    if (stat != ESP_OK) {
+        LOG_ERROR("%s failed to create timer, err 0x%x\n", __func__, stat);
         timer_id = NULL;
         goto end;
     }
 
-    timer_id->alarm_hdl = t;
-    timer_id->cb = callback;
-    timer_id->cb_data = data;
-
 end:
     osi_mutex_unlock(&alarm_mutex);
     return timer_id;
 }
 
-static int alarm_free(osi_alarm_t *alarm)
+static osi_alarm_err_t alarm_free(osi_alarm_t *alarm)
 {
     if (!alarm || alarm->alarm_hdl == NULL) {
         LOG_ERROR("%s null\n", __func__);
-        return -1;
+        return OSI_ALARM_ERR_INVALID_ARG;
     }
 
-    if (xTimerDelete(alarm->alarm_hdl, BT_ALARM_FREE_WAIT_TICKS) != pdPASS) {
-        LOG_ERROR("%s alarm delete error\n", __func__);
-        return -2;
+    esp_err_t stat = esp_timer_delete(alarm->alarm_hdl);
+    if (stat != ESP_OK) {
+        LOG_ERROR("%s failed to delete timer, err 0x%x\n", __func__, stat);
+        return OSI_ALARM_ERR_FAIL;
     }
     
     memset(alarm, 0, sizeof(osi_alarm_t));
-    return 0;
+    return OSI_ALARM_ERR_PASS;
 }
 
-int osi_alarm_free(osi_alarm_t *alarm)
+void osi_alarm_free(osi_alarm_t *alarm)
 {
     assert(alarm_mutex != NULL);
     
-    int ret = 0;
     osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
     if (alarm_state != ALARM_STATE_OPEN) {
         LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
-        ret = -3;
         goto end;
     }
     alarm_free(alarm);
 
 end:
     osi_mutex_unlock(&alarm_mutex);
-    return ret;
+    return;
 }
 
-
-int osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout)
+osi_alarm_err_t osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout)
 {
     assert(alarm_mutex != NULL);
     
-    int ret = 0;
+    osi_alarm_err_t ret = OSI_ALARM_ERR_PASS;
     osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
     if (alarm_state != ALARM_STATE_OPEN) {
         LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
-        ret = -3;
+        ret = OSI_ALARM_ERR_INVALID_STATE;
         goto end;
     }
     
     if (!alarm || alarm->alarm_hdl == NULL) {
         LOG_ERROR("%s null\n", __func__);
-        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__);
-        ret = -2;
+        ret = OSI_ALARM_ERR_INVALID_ARG;
         goto end;
     }
 
-    if (xTimerStart(alarm->alarm_hdl, BT_ALARM_START_WAIT_TICKS) != pdPASS) {
-        LOG_ERROR("%s start error\n", __func__);
-        ret = -2;
+    int64_t timeout_us = 1000 * (int64_t)timeout;
+    esp_err_t stat = esp_timer_start_once(alarm->alarm_hdl, (uint64_t)timeout_us);
+    if (stat != ESP_OK) {
+        LOG_ERROR("%s failed to start timer, err 0x%x\n", __func__, stat);
+        ret = OSI_ALARM_ERR_FAIL;
         goto end;
     }
-
+    alarm->deadline_us = timeout_us + esp_timer_get_time();
+    
 end:
     osi_mutex_unlock(&alarm_mutex);
     return ret;
 }
 
-
-int osi_alarm_cancel(osi_alarm_t *alarm)
+osi_alarm_err_t osi_alarm_cancel(osi_alarm_t *alarm)
 {
-    int ret = 0;
+    int ret = OSI_ALARM_ERR_PASS;
     osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
     if (alarm_state != ALARM_STATE_OPEN) {
         LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state);
-        ret = -3;
+        ret = OSI_ALARM_ERR_INVALID_STATE;
         goto end;
     }
     
     if (!alarm || alarm->alarm_hdl == NULL) {
         LOG_ERROR("%s null\n", __func__);
-        ret = -1;
+        ret = OSI_ALARM_ERR_INVALID_ARG;
         goto end;
     }
 
-    if (xTimerStop(alarm->alarm_hdl, BT_ALARM_STOP_WAIT_TICKS) != pdPASS) {
-        LOG_ERROR("%s failed to stop timer\n", __func__);
-        ret = -2;
+    esp_err_t stat = esp_timer_stop(alarm->alarm_hdl);
+    if (stat != ESP_OK) {
+        LOG_DEBUG("%s failed to stop timer, err 0x%x\n", __func__, stat);
+        ret = OSI_ALARM_ERR_FAIL;
         goto end;
     }
-
 end:
     osi_mutex_unlock(&alarm_mutex);
     return ret;
 }
 
-static uint32_t alarm_current_tick(void)
-{
-    return xTaskGetTickCount();
-}
-
-// todo: this is not accurate
-// max return value: 0xffffffff / 312 = 13765920 = 0xD20D20
-period_ms_t osi_alarm_now(void)
-{
-    return RTC_TIMER_TICKS_TO_MS((alarm_current_tick()));
-}
-
 period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm)
 {
-    /* TODO: use FreeRTOS timer.c implement ??? */
-    return 0xffffffff;
-}
+    assert(alarm_mutex != NULL);
+    int64_t dt_us = 0;
+    
+    osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
+    dt_us = alarm->deadline_us - esp_timer_get_time();
+    osi_mutex_unlock(&alarm_mutex);
 
-// pre-condition: 0 <= t1, t2 <= 0xD20D20
-// return value: 0<= ret <=0XD20D20
-period_ms_t osi_alarm_time_diff(period_ms_t t1, period_ms_t t2)
-{
-#define MAX_ALARM_TIME_MS     (0xD20D20)
-    int32_t diff = (int32_t)(t1) - (int32_t)(t2);
-    if (diff < 0) {
-        diff += MAX_ALARM_TIME_MS;
-    }
-    return (period_ms_t)diff;
+    return (dt_us > 0) ? (period_ms_t)(dt_us / 1000) : 0;
 }
 
 uint32_t osi_time_get_os_boottime_ms(void)
 {
-    return RTC_TIMER_TICKS_TO_MS((alarm_current_tick()));
+    return (uint32_t)(esp_timer_get_time() / 1000);
 }
-
-void osi_delay_ms(uint32_t ms)
-{
-    vTaskDelay(ms / portTICK_PERIOD_MS);
-}
-
index 07efbc5ac1cc170e612f36ae8f35fe7a03daf8f1..e71168ea0d2344c3705244f140691f3eee9fc855 100644 (file)
 #define _ALARM_H_
 
 #include <stdint.h>
-#include <freertos/FreeRTOS.h>
-#include <freertos/timers.h>
+#include "esp_timer.h"
 
-typedef uint32_t period_ms_t;
-typedef void (*osi_alarm_callback_t)(void *data);
+typedef struct alarm_t osi_alarm_t;
+typedef uint64_t period_ms_t;
+typedef esp_timer_cb_t osi_alarm_callback_t;
+
+typedef enum {
+    OSI_ALARM_ERR_PASS = 0,
+    OSI_ALARM_ERR_FAIL = -1,
+    OSI_ALARM_ERR_INVALID_ARG = -2,
+    OSI_ALARM_ERR_INVALID_STATE = -3,
+} osi_alarm_err_t;
 
 #define ALARM_CBS_NUM   30
 #define ALARM_ID_BASE   1000
-typedef struct alarm_t {
-    /* timer id point to here */
-    TimerHandle_t alarm_hdl;
-    osi_alarm_callback_t cb;
-    void *cb_data;
-} osi_alarm_t;
 
 int osi_alarm_create_mux(void);
 int osi_alarm_delete_mux(void);
@@ -42,27 +43,25 @@ void osi_alarm_deinit(void);
 
 // Creates a new alarm object. The returned object must be freed by calling
 // |alarm_free|. Returns NULL on failure.
-osi_alarm_t *osi_alarm_new(char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire);
+osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire);
 
 // Frees an alarm object created by |alarm_new|. |alarm| may be NULL. If the
 // alarm is pending, it will be cancelled. It is not safe to call |alarm_free|
 // from inside the callback of |alarm|.
-int osi_alarm_free(osi_alarm_t *alarm);
+void osi_alarm_free(osi_alarm_t *alarm);
 
 // Sets an alarm to fire |cb| after the given |deadline|. Note that |deadline| is the
 // number of milliseconds relative to the current time. |data| is a context variable
 // for the callback and may be NULL. |cb| will be called back in the context of an
 // unspecified thread (i.e. it will not be called back in the same thread as the caller).
 // |alarm| and |cb| may not be NULL.
-int osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout);
+osi_alarm_err_t osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout);
 
 // This function cancels the |alarm| if it was previously set. When this call
 // returns, the caller has a guarantee that the callback is not in progress and
 // will not be called if it hasn't already been called. This function is idempotent.
 // |alarm| may not be NULL.
-int osi_alarm_cancel(osi_alarm_t *alarm);
-
-period_ms_t osi_alarm_now(void);
+osi_alarm_err_t osi_alarm_cancel(osi_alarm_t *alarm);
 
 // Figure out how much time until next expiration.
 // Returns 0 if not armed. |alarm| may not be NULL.
@@ -72,10 +71,6 @@ period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm);
 // Alarm-related state cleanup
 //void alarm_cleanup(void);
 
-// Compute time difference (t1-t2) considering tick counter wrap
-// t1 and t2 should be no greater than the time of MAX ticks
-period_ms_t osi_alarm_time_diff(period_ms_t t1, period_ms_t t2);
-
 uint32_t osi_time_get_os_boottime_ms(void);
 
 #endif /*_ALARM_H_*/