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 <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-02-28 12:34:47 +05:30 committed by Carles Cufí
commit 489bebfb04
2 changed files with 102 additions and 10 deletions

View file

@ -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
*

View file

@ -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,