From 489bebfb04794126ff1d8977c3e59108be7ff516 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 28 Feb 2020 12:34:47 +0530 Subject: [PATCH] Bluetooth: controller: Add ticker_stop_abs interface Add ticker_stop_abs interface, similar functionality as to ticker_stop interface to stop a running ticker but with a supplied absolute tick reference value. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ticker/ticker.c | 109 ++++++++++++++++++-- subsys/bluetooth/controller/ticker/ticker.h | 3 + 2 files changed, 102 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index bfa97035fc0..5434d5f30ca 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -84,6 +84,7 @@ struct ticker_node { #define TICKER_USER_OP_TYPE_START 4 #define TICKER_USER_OP_TYPE_UPDATE 5 #define TICKER_USER_OP_TYPE_STOP 6 +#define TICKER_USER_OP_TYPE_STOP_ABS 7 /* Slot window re-schedule states */ #define TICKER_RESCHEDULE_STATE_NONE 0 @@ -137,6 +138,13 @@ struct ticker_user_op_update { u8_t force; /* Force update */ }; +/* User operation data structure for stop opcode. Used for passing stop + * requests with absolute tick to ticker_job + */ +struct ticker_user_op_stop { + u32_t ticks_at_stop; /* Anchor ticks (absolute) */ +}; + /* User operation data structure for slot_get opcode. Used for passing request * to get next ticker with slot ticks via ticker_job */ @@ -160,9 +168,10 @@ struct ticker_user_op { u8_t op; /* User operation */ u8_t id; /* Ticker node id */ union { - struct ticker_user_op_start start; - struct ticker_user_op_update update; - struct ticker_user_op_slot_get slot_get; + struct ticker_user_op_start start; + struct ticker_user_op_update update; + struct ticker_user_op_stop stop; + struct ticker_user_op_slot_get slot_get; struct ticker_user_op_priority_set priority_set; } params; /* User operation parameters */ u32_t status; /* Operation result */ @@ -1179,15 +1188,40 @@ static inline void ticker_job_node_manage(struct ticker_instance *instance, ticker->req = ticker->ack; if (instance->ticker_id_slot_previous == user_op->id) { - u32_t ticks_now = cntr_cnt_get(); + u32_t ticks_current; + u32_t ticks_at_stop; u32_t ticks_used; instance->ticker_id_slot_previous = TICKER_NULL; - ticks_used = ticks_elapsed + - ticker_ticks_diff_get(ticks_now, - instance->ticks_current); - instance->ticks_slot_previous = MIN(ticker->ticks_slot, - ticks_used); + + if (user_op->op == TICKER_USER_OP_TYPE_STOP_ABS) { + ticks_at_stop = + user_op->params.stop.ticks_at_stop; + } else { + ticks_at_stop = cntr_cnt_get(); + } + + ticks_current = instance->ticks_current; + if (!((ticks_at_stop - ticks_current) & + BIT(HAL_TICKER_CNTR_MSBIT))) { + ticks_used = ticks_elapsed + + ticker_ticks_diff_get(ticks_at_stop, + ticks_current); + } else { + ticks_used = + ticker_ticks_diff_get(ticks_current, + ticks_at_stop); + if (ticks_elapsed > ticks_used) { + ticks_used = ticks_elapsed - + ticks_used; + } else { + ticks_used = 0; + } + } + + if (instance->ticks_slot_previous > ticks_used) { + instance->ticks_slot_previous = ticks_used; + } } } @@ -1267,7 +1301,7 @@ static inline u8_t ticker_job_list_manage(struct ticker_instance *instance, /* if not started or update not required, * set status and continue. */ - if ((user_op->op > TICKER_USER_OP_TYPE_STOP) || + if ((user_op->op > TICKER_USER_OP_TYPE_STOP_ABS) || (state == 0U) || ((user_op->op == TICKER_USER_OP_TYPE_UPDATE) && (user_op->params.update.ticks_drift_plus == 0U) && @@ -2562,6 +2596,61 @@ u32_t ticker_stop(u8_t instance_index, u8_t user_id, u8_t ticker_id, return user_op->status; } +/** + * @brief Stop a ticker node with supplied absolute ticks reference + * + * @details Creates a new user operation of type TICKER_USER_OP_TYPE_STOP_ABS + * and schedules the ticker_job. + * + * @param instance_index Index of ticker instance + * @param user_id Ticker user id. Used for indexing user operations + * and mapping to mayfly caller id + * @param ticks_at_stop Absolute tick count at ticker stop request + * @param fp_op_func Function pointer of user operation completion + * function + * @param op_context Context passed in operation completion call + * + * @return TICKER_STATUS_BUSY if stop was successful but not yet completed. + * TICKER_STATUS_FAILURE is returned if there are no more user operations + * available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run + * before exiting ticker_stop + */ +u32_t ticker_stop_abs(u8_t instance_index, u8_t user_id, u8_t ticker_id, + u32_t ticks_at_stop, ticker_op_func fp_op_func, + void *op_context) +{ + struct ticker_instance *instance = &_instance[instance_index]; + struct ticker_user_op *user_op; + struct ticker_user *user; + u8_t last; + + user = &instance->users[user_id]; + + last = user->last + 1; + if (last >= user->count_user_op) { + last = 0U; + } + + if (last == user->first) { + return TICKER_STATUS_FAILURE; + } + + user_op = &user->user_op[user->last]; + user_op->op = TICKER_USER_OP_TYPE_STOP_ABS; + user_op->id = ticker_id; + user_op->params.stop.ticks_at_stop = ticks_at_stop; + user_op->status = TICKER_STATUS_BUSY; + user_op->fp_op_func = fp_op_func; + user_op->op_context = op_context; + + user->last = last; + + instance->sched_cb(instance->caller_id_get_cb(user_id), + TICKER_CALL_ID_JOB, 0, instance); + + return user_op->status; +} + /** * @brief Get next ticker node slot * diff --git a/subsys/bluetooth/controller/ticker/ticker.h b/subsys/bluetooth/controller/ticker/ticker.h index 38f7fb8df33..a2f946e4a66 100644 --- a/subsys/bluetooth/controller/ticker/ticker.h +++ b/subsys/bluetooth/controller/ticker/ticker.h @@ -134,6 +134,9 @@ u32_t ticker_update(u8_t instance_index, u8_t user_id, u8_t ticker_id, u8_t force, ticker_op_func fp_op_func, void *op_context); u32_t ticker_stop(u8_t instance_index, u8_t user_id, u8_t ticker_id, ticker_op_func fp_op_func, void *op_context); +u32_t ticker_stop_abs(u8_t instance_index, u8_t user_id, u8_t ticker_id, + u32_t ticks_at_stop, ticker_op_func fp_op_func, + void *op_context); u32_t ticker_next_slot_get(u8_t instance_index, u8_t user_id, u8_t *ticker_id_head, u32_t *ticks_current, u32_t *ticks_to_expire,