From 53273172febadc9757ac59e6ac51b66a52f9f7ac Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Wed, 8 Nov 2017 17:12:08 +0800 Subject: [PATCH] component/bt: modify the implementation and interface of osi_alarm module 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 | 45 ++---- components/bt/bluedroid/osi/alarm.c | 164 ++++++++------------ components/bt/bluedroid/osi/include/alarm.h | 35 ++--- 3 files changed, 86 insertions(+), 158 deletions(-) diff --git a/components/bt/bluedroid/hci/hci_layer.c b/components/bt/bluedroid/hci/hci_layer.c index cbf180f7e..9519fd1d2 100644 --- a/components/bt/bluedroid/hci/hci_layer.c +++ b/components/bt/bluedroid/hci/hci_layer.c @@ -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 && diff --git a/components/bt/bluedroid/osi/alarm.c b/components/bt/bluedroid/osi/alarm.c index 98d2aefef..034ff902c 100644 --- a/components/bt/bluedroid/osi/alarm.c +++ b/components/bt/bluedroid/osi/alarm.c @@ -23,22 +23,18 @@ #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; + ret = OSI_ALARM_ERR_INVALID_ARG; goto end; } + + 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(); - 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; - goto end; - } - - if (xTimerStart(alarm->alarm_hdl, BT_ALARM_START_WAIT_TICKS) != pdPASS) { - LOG_ERROR("%s start error\n", __func__); - ret = -2; - goto end; - } - 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); -} - diff --git a/components/bt/bluedroid/osi/include/alarm.h b/components/bt/bluedroid/osi/include/alarm.h index 07efbc5ac..e71168ea0 100644 --- a/components/bt/bluedroid/osi/include/alarm.h +++ b/components/bt/bluedroid/osi/include/alarm.h @@ -20,20 +20,21 @@ #define _ALARM_H_ #include -#include -#include +#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_*/