Bluetooth: controller: Add ticker_yield_abs interface
Add ticker_yield_abs interface to reduce ticks_slot_previous value when radio events yield/stop earlier than their time reservations. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
9f8c180522
commit
bce82ad49b
2 changed files with 94 additions and 25 deletions
|
|
@ -99,8 +99,9 @@ struct ticker_node {
|
||||||
#define TICKER_USER_OP_TYPE_PRIORITY_SET 3
|
#define TICKER_USER_OP_TYPE_PRIORITY_SET 3
|
||||||
#define TICKER_USER_OP_TYPE_START 4
|
#define TICKER_USER_OP_TYPE_START 4
|
||||||
#define TICKER_USER_OP_TYPE_UPDATE 5
|
#define TICKER_USER_OP_TYPE_UPDATE 5
|
||||||
#define TICKER_USER_OP_TYPE_STOP 6
|
#define TICKER_USER_OP_TYPE_YIELD_ABS 6
|
||||||
#define TICKER_USER_OP_TYPE_STOP_ABS 7
|
#define TICKER_USER_OP_TYPE_STOP 7
|
||||||
|
#define TICKER_USER_OP_TYPE_STOP_ABS 8
|
||||||
|
|
||||||
/* Slot window re-schedule states */
|
/* Slot window re-schedule states */
|
||||||
#define TICKER_RESCHEDULE_STATE_NONE 0
|
#define TICKER_RESCHEDULE_STATE_NONE 0
|
||||||
|
|
@ -166,11 +167,11 @@ struct ticker_user_op_update {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* User operation data structure for stop opcode. Used for passing stop
|
/* User operation data structure for yield/stop opcode. Used for passing yield/
|
||||||
* requests with absolute tick to ticker_job
|
* stop requests with absolute tick to ticker_job
|
||||||
*/
|
*/
|
||||||
struct ticker_user_op_stop {
|
struct ticker_user_op_yield {
|
||||||
uint32_t ticks_at_stop; /* Anchor ticks (absolute) */
|
uint32_t ticks_at_yield; /* Anchor ticks (absolute) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* User operation data structure for slot_get opcode. Used for passing request
|
/* User operation data structure for slot_get opcode. Used for passing request
|
||||||
|
|
@ -205,7 +206,7 @@ struct ticker_user_op {
|
||||||
union {
|
union {
|
||||||
struct ticker_user_op_start start;
|
struct ticker_user_op_start start;
|
||||||
struct ticker_user_op_update update;
|
struct ticker_user_op_update update;
|
||||||
struct ticker_user_op_stop stop;
|
struct ticker_user_op_yield yield;
|
||||||
struct ticker_user_op_slot_get slot_get;
|
struct ticker_user_op_slot_get slot_get;
|
||||||
struct ticker_user_op_priority_set priority_set;
|
struct ticker_user_op_priority_set priority_set;
|
||||||
} params; /* User operation parameters */
|
} params; /* User operation parameters */
|
||||||
|
|
@ -1279,11 +1280,12 @@ static inline void ticker_job_node_manage(struct ticker_instance *instance,
|
||||||
uint32_t ticks_elapsed,
|
uint32_t ticks_elapsed,
|
||||||
uint8_t *insert_head)
|
uint8_t *insert_head)
|
||||||
{
|
{
|
||||||
/* Remove ticker node from list */
|
|
||||||
ticker->ticks_to_expire = ticker_dequeue(instance, user_op->id);
|
|
||||||
|
|
||||||
/* Handle update of ticker by re-inserting it back. */
|
/* Handle update of ticker by re-inserting it back. */
|
||||||
if (user_op->op == TICKER_USER_OP_TYPE_UPDATE) {
|
if (user_op->op == TICKER_USER_OP_TYPE_UPDATE) {
|
||||||
|
/* Remove ticker node from list */
|
||||||
|
ticker->ticks_to_expire = ticker_dequeue(instance, user_op->id);
|
||||||
|
|
||||||
|
/* Update node and insert back */
|
||||||
ticker_job_node_update(ticker, user_op, instance->ticks_current,
|
ticker_job_node_update(ticker, user_op, instance->ticks_current,
|
||||||
ticks_elapsed, insert_head);
|
ticks_elapsed, insert_head);
|
||||||
|
|
||||||
|
|
@ -1292,33 +1294,42 @@ static inline void ticker_job_node_manage(struct ticker_instance *instance,
|
||||||
*/
|
*/
|
||||||
ticker->req++;
|
ticker->req++;
|
||||||
} else {
|
} else {
|
||||||
/* Reset schedule status of node */
|
/* If stop/stop_abs requested, then dequeue node */
|
||||||
ticker->req = ticker->ack;
|
if (user_op->op != TICKER_USER_OP_TYPE_YIELD_ABS) {
|
||||||
|
/* Remove ticker node from list */
|
||||||
|
ticker->ticks_to_expire = ticker_dequeue(instance,
|
||||||
|
user_op->id);
|
||||||
|
|
||||||
|
/* Reset schedule status of node */
|
||||||
|
ticker->req = ticker->ack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If yield_abs/stop/stop_abs then adjust ticks_slot_previous */
|
||||||
if (instance->ticker_id_slot_previous == user_op->id) {
|
if (instance->ticker_id_slot_previous == user_op->id) {
|
||||||
uint32_t ticks_current;
|
uint32_t ticks_current;
|
||||||
uint32_t ticks_at_stop;
|
uint32_t ticks_at_yield;
|
||||||
uint32_t ticks_used;
|
uint32_t ticks_used;
|
||||||
|
|
||||||
instance->ticker_id_slot_previous = TICKER_NULL;
|
instance->ticker_id_slot_previous = TICKER_NULL;
|
||||||
|
|
||||||
if (user_op->op == TICKER_USER_OP_TYPE_STOP_ABS) {
|
if ((user_op->op == TICKER_USER_OP_TYPE_YIELD_ABS) ||
|
||||||
ticks_at_stop =
|
(user_op->op == TICKER_USER_OP_TYPE_STOP_ABS)) {
|
||||||
user_op->params.stop.ticks_at_stop;
|
ticks_at_yield =
|
||||||
|
user_op->params.yield.ticks_at_yield;
|
||||||
} else {
|
} else {
|
||||||
ticks_at_stop = cntr_cnt_get();
|
ticks_at_yield = cntr_cnt_get();
|
||||||
}
|
}
|
||||||
|
|
||||||
ticks_current = instance->ticks_current;
|
ticks_current = instance->ticks_current;
|
||||||
if (!((ticks_at_stop - ticks_current) &
|
if (!((ticks_at_yield - ticks_current) &
|
||||||
BIT(HAL_TICKER_CNTR_MSBIT))) {
|
BIT(HAL_TICKER_CNTR_MSBIT))) {
|
||||||
ticks_used = ticks_elapsed +
|
ticks_used = ticks_elapsed +
|
||||||
ticker_ticks_diff_get(ticks_at_stop,
|
ticker_ticks_diff_get(ticks_at_yield,
|
||||||
ticks_current);
|
ticks_current);
|
||||||
} else {
|
} else {
|
||||||
ticks_used =
|
ticks_used =
|
||||||
ticker_ticks_diff_get(ticks_current,
|
ticker_ticks_diff_get(ticks_current,
|
||||||
ticks_at_stop);
|
ticks_at_yield);
|
||||||
if (ticks_elapsed > ticks_used) {
|
if (ticks_elapsed > ticks_used) {
|
||||||
ticks_used = ticks_elapsed -
|
ticks_used = ticks_elapsed -
|
||||||
ticks_used;
|
ticks_used;
|
||||||
|
|
@ -1425,7 +1436,7 @@ static inline uint8_t ticker_job_list_manage(struct ticker_instance *instance,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete node, if not expired */
|
/* Delete or yield node, if not expired */
|
||||||
if (state == 1U) {
|
if (state == 1U) {
|
||||||
ticker_job_node_manage(instance, ticker,
|
ticker_job_node_manage(instance, ticker,
|
||||||
user_op, ticks_elapsed,
|
user_op, ticks_elapsed,
|
||||||
|
|
@ -2808,6 +2819,61 @@ uint32_t ticker_update_ext(uint8_t instance_index, uint8_t user_id,
|
||||||
return user_op->status;
|
return user_op->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Yield a ticker node with supplied absolute ticks reference
|
||||||
|
*
|
||||||
|
* @details Creates a new user operation of type TICKER_USER_OP_TYPE_YIELD_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_yield Absolute tick count at ticker yield 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
|
||||||
|
*/
|
||||||
|
uint32_t ticker_yield_abs(uint8_t instance_index, uint8_t user_id,
|
||||||
|
uint8_t ticker_id, uint32_t ticks_at_yield,
|
||||||
|
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;
|
||||||
|
uint8_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_YIELD_ABS;
|
||||||
|
user_op->id = ticker_id;
|
||||||
|
user_op->params.yield.ticks_at_yield = ticks_at_yield;
|
||||||
|
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 Stop a ticker node
|
* @brief Stop a ticker node
|
||||||
*
|
*
|
||||||
|
|
@ -2879,9 +2945,9 @@ uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
|
||||||
* available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
|
* available, and TICKER_STATUS_SUCCESS is returned if ticker_job gets to run
|
||||||
* before exiting ticker_stop
|
* before exiting ticker_stop
|
||||||
*/
|
*/
|
||||||
uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
|
uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id,
|
||||||
uint32_t ticks_at_stop, ticker_op_func fp_op_func,
|
uint8_t ticker_id, uint32_t ticks_at_stop,
|
||||||
void *op_context)
|
ticker_op_func fp_op_func, void *op_context)
|
||||||
{
|
{
|
||||||
struct ticker_instance *instance = &_instance[instance_index];
|
struct ticker_instance *instance = &_instance[instance_index];
|
||||||
struct ticker_user_op *user_op;
|
struct ticker_user_op *user_op;
|
||||||
|
|
@ -2902,7 +2968,7 @@ uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id, uint8_t ticker
|
||||||
user_op = &user->user_op[user->last];
|
user_op = &user->user_op[user->last];
|
||||||
user_op->op = TICKER_USER_OP_TYPE_STOP_ABS;
|
user_op->op = TICKER_USER_OP_TYPE_STOP_ABS;
|
||||||
user_op->id = ticker_id;
|
user_op->id = ticker_id;
|
||||||
user_op->params.stop.ticks_at_stop = ticks_at_stop;
|
user_op->params.yield.ticks_at_yield = ticks_at_stop;
|
||||||
user_op->status = TICKER_STATUS_BUSY;
|
user_op->status = TICKER_STATUS_BUSY;
|
||||||
user_op->fp_op_func = fp_op_func;
|
user_op->fp_op_func = fp_op_func;
|
||||||
user_op->op_context = op_context;
|
user_op->op_context = op_context;
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,9 @@ uint32_t ticker_update(uint8_t instance_index, uint8_t user_id, uint8_t ticker_i
|
||||||
uint32_t ticks_drift_plus, uint32_t ticks_drift_minus,
|
uint32_t ticks_drift_plus, uint32_t ticks_drift_minus,
|
||||||
uint32_t ticks_slot_plus, uint32_t ticks_slot_minus, uint16_t lazy,
|
uint32_t ticks_slot_plus, uint32_t ticks_slot_minus, uint16_t lazy,
|
||||||
uint8_t force, ticker_op_func fp_op_func, void *op_context);
|
uint8_t force, ticker_op_func fp_op_func, void *op_context);
|
||||||
|
uint32_t ticker_yield_abs(uint8_t instance_index, uint8_t user_id,
|
||||||
|
uint8_t ticker_id, uint32_t ticks_at_yield,
|
||||||
|
ticker_op_func fp_op_func, void *op_context);
|
||||||
uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
|
uint32_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
|
||||||
ticker_op_func fp_op_func, void *op_context);
|
ticker_op_func fp_op_func, void *op_context);
|
||||||
uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
|
uint32_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue