Lines Matching +full:instance +full:- +full:id

2  * Copyright (c) 2016-2018 Nordic Semiconductor ASA
5 * SPDX-License-Identifier: Apache-2.0
55 uint8_t force:1; /* If non-zero, node timeout should
59 uint8_t start_pending:1; /* If non-zero, start is pending for
63 uint32_t ticks_periodic; /* If non-zero, interval
73 uint32_t ticks_slot; /* Air-time reservation for node */
83 uint32_t remainder_periodic;/* Sub-microsecond tick remainder
93 uint32_t remainder_current; /* Current sub-microsecond tick
145 /* Slot window re-schedule states */
152 ((_ticker)->ext_data && ((_ticker)->ext_data->ticks_slot_window != 0U))
154 (_ticker->ext_data && (_ticker->ext_data->reschedule_state == \
170 uint32_t remainder_periodic; /* Sub-microsecond tick remainder */
173 uint32_t remainder_first; /* Sub-microsecond tick remainder */
182 uint32_t ticks_slot; /* Air-time reservation ticks */
189 struct ticker_ext *ext_data; /* Ticker extension data instance */
201 * reservation (air-time)
204 * slot reservation (air-time)
210 * >1: latency = lazy - 1
265 uint8_t id; /* Ticker node id */ member
291 /* Ticker instance
324 uint8_t ticker_id_slot_previous; /* Id of previous slot reserving
328 * by a ticker node (active air-time)
338 * the caller id from user
339 * id
392 * @param ticker_id_head Id of initial ticker node
395 * @return Id of ticker expiring within slot or TICKER_NULL
406 ticks_to_expire = ticker->ticks_to_expire; in ticker_by_slot_get()
413 if (ticker->ticks_slot) { in ticker_by_slot_get()
420 ticks_slot -= ticks_to_expire; in ticker_by_slot_get()
421 ticker_id_head = ticker->next; in ticker_by_slot_get()
432 * @details Iterates ticker nodes from ticker_id_head. If no head id is provided
437 * - Gets the next ticker which has slot ticks specified and return the ticker
438 * id and accumulated ticks until expiration.
439 * - If a matching function is provided, this function is called and node iteration
443 * - Gets the next ticker node.
444 * - If a matching function is provided, this function is called and node iteration
447 * @param instance Pointer to ticker instance
448 * @param ticker_id_head Pointer to id of first ticker node [in/out]
458 static void ticker_by_next_slot_get(struct ticker_instance *instance, argument
471 node = instance->nodes;
476 (*ticks_current != instance->ticks_current)) {
477 /* Initialize with instance head */
478 _ticker_id_head = instance->ticker_id_head;
479 *ticks_current = instance->ticks_current;
482 /* Get ticker id for next node */
484 _ticker_id_head = ticker->next;
496 ticks_slot += ticker->ticks_slot;
499 /* Match node id */
502 ticker->ticks_to_expire,
514 if (ticker->ticks_slot) {
525 _ticks_to_expire += ticker->ticks_to_expire;
526 _ticker_id_head = ticker->next;
531 _ticks_to_expire += ticker->ticks_to_expire;
536 *remainder = ticker->remainder_current;
547 *lazy = ticker->lazy_current;
566 * @param instance Pointer to ticker instance
567 * @param id Ticker node id to enqueue
569 * @return Id of enqueued ticker node
572 static uint8_t ticker_enqueue(struct ticker_instance *instance, uint8_t id)
582 node = &instance->nodes[0];
583 ticker_new = &node[id];
584 ticks_to_expire = ticker_new->ticks_to_expire;
585 current = instance->ticker_id_head;
594 (ticker_current = &node[current])->ticks_to_expire))) {
596 ticks_to_expire -= ticks_to_expire_current;
598 /* Check for timeout in same tick - prioritize according to
601 if (ticks_to_expire == 0 && (ticker_new->lazy_current >
602 ticker_current->lazy_current)) {
608 current = ticker_current->next;
613 ticker_new->ticks_to_expire = ticks_to_expire;
614 ticker_new->next = current;
617 instance->ticker_id_head = id;
619 node[previous].next = id;
623 node[current].ticks_to_expire -= ticks_to_expire;
626 return id;
638 * @param instance Pointer to ticker instance
639 * @param id Ticker node id to enqueue
641 * @return Id of enqueued ticker node, or id of previous- or colliding
645 static uint8_t ticker_enqueue(struct ticker_instance *instance, uint8_t id)
658 node = &instance->nodes[0];
659 ticker_new = &node[id];
660 ticks_to_expire = ticker_new->ticks_to_expire;
663 current = instance->ticker_id_head;
665 ticks_slot_previous = instance->ticks_slot_previous;
673 (ticker_current = &node[current])->ticks_to_expire))) {
674 ticks_to_expire -= ticks_to_expire_current;
676 if (ticker_current->ticks_slot != 0U) {
677 ticks_slot_previous = ticker_current->ticks_slot;
681 ticks_slot_previous -= ticks_to_expire_current;
687 current = ticker_current->next;
692 ticks_to_expire + ticker_new->ticks_slot);
694 if ((ticker_new->ticks_slot == 0U) ||
697 /* New ticker node has no slot ticks or there is no collision -
700 ticker_new->ticks_to_expire = ticks_to_expire;
701 ticker_new->next = current;
704 instance->ticker_id_head = id;
706 node[previous].next = id;
710 node[current].ticks_to_expire -= ticks_to_expire;
713 /* Collision - no ticker node insertion, set id to that of
717 id = ticker_id_slot_previous;
719 id = collide;
723 return id;
734 * @param instance Pointer to ticker instance
735 * @param id Ticker node id to dequeue
741 static uint32_t ticker_dequeue(struct ticker_instance *instance, uint8_t id)
753 node = &instance->nodes[0];
754 previous = instance->ticker_id_head;
761 if (current == id) {
765 total += ticker_current->ticks_to_expire;
767 current = ticker_current->next;
777 instance->ticker_id_head = ticker_current->next;
781 timeout = ticker_current->ticks_to_expire;
786 node[previous].next = ticker_current->next;
791 if (ticker_current->next != TICKER_NULL) {
792 node[ticker_current->next].ticks_to_expire += timeout;
804 * and returns non-zero if the ticker node collides and should be skipped.
831 if ((ticker->priority != TICKER_PRIORITY_CRITICAL) &&
832 (ticker->next != TICKER_NULL)) {
835 if (ticker->next != TICKER_NULL) {
839 uint16_t lazy_current = ticker->lazy_current;
842 if (TICKER_HAS_SLOT_WINDOW(ticker) && !ticker->ticks_slot) {
845 ticker_ticks_slot = ticker->ticks_slot;
851 if (lazy_current >= ticker->lazy_periodic) {
852 lazy_current -= ticker->lazy_periodic;
854 uint8_t id_head = ticker->next;
858 uint32_t current_age = ticker->ticks_periodic +
859 (lazy_current * ticker->ticks_periodic);
866 acc_ticks_to_expire += ticker_next->ticks_to_expire;
872 (ticker_next->ticks_slot == 0U)) {
877 ticker_next->ticks_slot;
882 id_head = ticker_next->next;
886 uint16_t lazy_next = ticker_next->lazy_current;
888 ticker_next->lazy_periodic > lazy_next;
891 lazy_next -= ticker_next->lazy_periodic;
895 uint32_t next_age = (ticker_next->ticks_periodic == 0U ?
897 (ticker_next->ticks_periodic -
898 ticker_next->ticks_to_expire)) +
900 ticker_next->ticks_periodic);
904 (ticker->ticks_periodic == 0U) ||
908 (ticker->ticks_periodic != 0U) &&
913 (ticker->force == ticker_next->force);
914 /* Is force requested for next node (e.g. update) -
918 (ticker_next->force > ticker->force);
925 (ticker_next->priority ==
930 (ticker->priority == ticker_next->priority);
945 ((lazy_next - ticker_next->priority) >
946 (lazy_current - ticker->priority));
955 (ticker_next->ext_data->is_drift_in_window &&
958 ticker_next->ext_data->ticks_slot_window -
959 ticker_next->ticks_slot) <
960 ticker->ticks_slot);
968 ticker_next->ticks_slot) <=
969 (ticker->ext_data->ticks_slot_window -
970 ticker->ticks_slot));
976 (lazy_next - ticker_next->priority) >
977 (lazy_current - ticker->priority);
990 !ticker->ticks_slot &&
992 ticker_next->ticks_slot) <=
993 (ticker->ext_data->ticks_slot_window)));
1000 (lazy_next - ticker_next->priority) >
1001 (lazy_current - ticker->priority);
1020 /* This node must be skipped - check window */
1023 id_head = ticker_next->next;
1035 * @brief Get expiration delta from one ticker id to another ticker id
1039 * @param instance Ticker instance
1040 * @param to_ticker_id Target ticker id
1041 * @param from_ticker_id Ticker id to compare with
1047 static void ticker_get_expire_info(struct ticker_instance *instance, uint8_t to_ticker_id,
1059 current_ticker_id = instance->ticker_id_head;
1060 current_node = &instance->nodes[instance->ticker_id_head];
1063 acc_ticks_to_expire += current_node->ticks_to_expire;
1073 current_ticker_id = current_node->next;
1074 current_node = &instance->nodes[current_ticker_id];
1078 struct ticker_node *to_ticker = &instance->nodes[to_ticker_id];
1081 uint32_t to_remainder = to_ticker->remainder_current;
1085 /* from ticker is scheduled after the to ticker - use period
1088 if (to_ticker->ticks_periodic == 0) {
1090 expire_info->found = 0;
1094 to_ticks += to_ticker->ticks_periodic;
1098 to_ticker->remainder_periodic);
1103 expire_info->ticks_to_expire = to_ticks - from_ticks;
1104 expire_info->remainder = to_remainder;
1105 expire_info->lazy = to_ticker->lazy_current;
1106 expire_info->found = 1;
1108 expire_info->found = 0;
1113 * @brief Allocate an expire info for the given ticker ID
1115 * @param instance Ticker instance
1116 * @param ticker_id Ticker ID to allocate for
1123 static uint32_t ticker_alloc_expire_info(struct ticker_instance *instance, uint8_t ticker_id)
1129 if (instance->expire_infos[i].ticker_id == TICKER_NULL) {
1130 struct ticker_node *ticker = &instance->nodes[ticker_id];
1132 instance->expire_infos[i].ticker_id = ticker_id;
1133 instance->expire_infos[i].outdated = true;
1134 instance->expire_infos[i].last = is_last;
1135 ticker->ext_data->other_expire_info = &instance->expire_infos[i];
1136 instance->expire_infos_outdated = true;
1139 } else if (instance->expire_infos[i].last && i < TICKER_EXPIRE_INFO_MAX - 1) {
1140 instance->expire_infos[i].last = 0;
1149 * @brief Free a previously allocated expire info for the given ticker ID
1151 * @param instance Ticker instance
1152 * @param ticker_id Ticker ID to free up the allocation for
1156 static void ticker_free_expire_info(struct ticker_instance *instance, uint8_t ticker_id)
1162 if (instance->expire_infos[index].ticker_id == ticker_id) {
1163 instance->expire_infos[index].ticker_id = TICKER_NULL;
1164 is_last = instance->expire_infos[index].last;
1165 instance->expire_infos[index].last = 0;
1172 for (; index >= 0; index--) {
1173 if (instance->expire_infos[index].ticker_id != TICKER_NULL || index == 0) {
1174 instance->expire_infos[index].last = 1;
1182 * @brief Mark all expire infos involving a ticker ID as outdated
1185 * infos (if any) that involve that ticker as outdated and in need of re-calculation.
1189 * @param instance Ticker instance
1190 * @param ticker_id ID of ticker that has moved
1194 static void ticker_mark_expire_info_outdated(struct ticker_instance *instance, uint8_t ticker_id)
1197 if (instance->expire_infos[i].ticker_id != TICKER_NULL) {
1198 uint8_t current_id = instance->expire_infos[i].ticker_id;
1199 struct ticker_node *ticker = &instance->nodes[current_id];
1202 ticker->ext_data->expire_info_id == ticker_id) {
1203 instance->expire_infos[i].outdated = true;
1204 instance->expire_infos_outdated = true;
1207 if (instance->expire_infos[i].last) {
1220 * @param param Pointer to ticker instance
1224 static void ticker_job_update_expire_infos(struct ticker_instance *instance)
1227 struct ticker_expire_info_internal *info = &instance->expire_infos[i];
1229 if (info->ticker_id != TICKER_NULL && info->outdated) {
1230 struct ticker_node *ticker = &instance->nodes[info->ticker_id];
1232 ticker_get_expire_info(instance, ticker->ext_data->expire_info_id,
1233 info->ticker_id, info);
1234 info->outdated = false;
1237 if (info->last) {
1242 instance->expire_infos_outdated = false;
1257 * @param param Pointer to ticker instance
1262 struct ticker_instance *instance = param;
1270 instance->worker_trigger = 1U;
1271 if (instance->job_guard) {
1276 if (instance->ticker_id_head == TICKER_NULL) {
1277 instance->worker_trigger = 0U;
1285 instance->ticks_current);
1291 ticker_id_head = instance->ticker_id_head;
1295 /* Check if the previous ticker node which had air-time, is still
1300 if (instance->ticks_slot_previous > ticks_elapsed) {
1309 node = &instance->nodes[0];
1320 ticks_to_expire = ticker->ticks_to_expire;
1326 ticks_elapsed -= ticks_to_expire;
1330 ticker_id_head = ticker->next;
1334 if (((ticker->req - ticker->ack) & 0xff) != 1U) {
1343 (ticker->ticks_slot == 0U)) {
1346 ticker_ticks_slot = ticker->ticks_slot;
1354 (instance->ticks_slot_previous > ticks_expired) ||
1357 struct ticker_ext *ext_data = ticker->ext_data;
1360 ext_data->ticks_slot_window != 0U &&
1361 ext_data->reschedule_state ==
1363 (ticker->lazy_periodic <= ticker->lazy_current)) {
1364 /* Mark node for re-scheduling in ticker_job */
1365 ext_data->reschedule_state =
1368 /* Mark node as not re-scheduling */
1369 ext_data->reschedule_state =
1374 * of re-scheduled node, the lazy count will be decremented in
1377 ticker->lazy_current++;
1379 if ((ticker->must_expire == 0U) ||
1380 (ticker->lazy_periodic >= ticker->lazy_current) ||
1382 /* Not a must-expire node or this is periodic
1383 * latency or pending re-schedule. Skip this
1386 ticker->ack--;
1395 if (ticker->ext_data) {
1396 ticks_drift = ticker->ext_data->ticks_drift;
1397 ticker->ext_data->ticks_drift = 0U;
1398 /* Mark node as not re-scheduling */
1399 ticker->ext_data->reschedule_state =
1418 ticker->ack--;
1420 if (ticker->timeout_func) {
1424 ticks_at_expire = (instance->ticks_current +
1425 ticks_expired -
1426 ticker->ticks_to_expire_minus) &
1430 remainder_current = ticker->remainder_current;
1436 if (ticker->ext_data &&
1437 ticker->ext_data->ext_timeout_func) {
1442 timeout_func = ticker->ext_data->ext_timeout_func;
1443 expire_info = ticker->ext_data->other_expire_info;
1444 if (ticker->ext_data->expire_info_id != TICKER_NULL) {
1445 LL_ASSERT(expire_info && !expire_info->outdated);
1448 ext_context.context = ticker->context;
1449 if (expire_info && expire_info->found) {
1463 ticker->lazy_current,
1464 ticker->force,
1472 ticker->timeout_func(ticks_at_expire,
1477 ticker->lazy_current,
1478 ticker->force,
1479 ticker->context);
1486 ticker->lazy_current = 0U;
1487 ticker->force = 0U;
1504 if (instance->ticks_elapsed_first == instance->ticks_elapsed_last) {
1505 ticker_next_elapsed(&instance->ticks_elapsed_last);
1507 instance->ticks_elapsed[instance->ticks_elapsed_last] = ticks_expired;
1509 instance->worker_trigger = 0U;
1512 instance->sched_cb(TICKER_CALL_ID_WORKER, TICKER_CALL_ID_JOB, 1,
1513 instance);
1531 uint32_t ticks_to_expire = ticker->ticks_to_expire;
1532 uint32_t ticks_to_expire_minus = ticker->ticks_to_expire_minus;
1535 if (!((ticks_at_start - ticks_current) & BIT(HAL_TICKER_CNTR_MSBIT))) {
1549 /* There's still time until expiration - subtract
1552 ticks_to_expire -= delta_current_start;
1560 (delta_current_start - ticks_to_expire);
1567 ticks_to_expire -= ticks_to_expire_minus;
1570 ticks_to_expire_minus -= ticks_to_expire;
1575 ticker->ticks_to_expire = ticks_to_expire;
1576 ticker->ticks_to_expire_minus = ticks_to_expire_minus;
1583 * for above-microsecond precision counter HW. The remainder enables improved
1584 * ticker precision, but is disabled for sub-microsecond precision
1600 *remainder -= HAL_TICKER_REMAINDER_RANGE;
1613 * for above-microsecond precision counter HW. The remainder enables improved
1614 * ticker precision, but is disabled for sub-microsecond precision
1624 return ticker_add_to_remainder(&ticker->remainder_current, ticker->remainder_periodic);
1631 * for above-microsecond precision counter HW. The remainder enables improved
1632 * ticker precision, but is disabled for sub-microsecond precision
1644 if ((ticker->remainder_current >= BIT(31)) ||
1645 (ticker->remainder_current <= (HAL_TICKER_REMAINDER_RANGE >> 1))) {
1647 ticker->remainder_current += HAL_TICKER_REMAINDER_RANGE;
1650 ticker->remainder_current -= ticker->remainder_periodic;
1666 user_op->op = TICKER_USER_OP_TYPE_NONE;
1667 user_op->status = status;
1668 if (user_op->fp_op_func) {
1669 user_op->fp_op_func(user_op->status, user_op->op_context);
1681 * @param ticks_current Current ticker instance ticks
1683 * @param insert_head Pointer to current head (id). Contains id
1687 static inline uint32_t ticker_job_node_update(struct ticker_instance *instance,
1695 uint32_t ticks_to_expire = ticker->ticks_to_expire;
1699 ticks_to_expire -= ticks_elapsed;
1701 ticker->ticks_to_expire_minus += ticks_elapsed -
1707 if ((ticker->ticks_periodic != 0U) &&
1708 (user_op->params.update.lazy != 0U)) {
1709 user_op->params.update.lazy--;
1710 while ((ticks_to_expire > ticker->ticks_periodic) &&
1711 (ticker->lazy_current > user_op->params.update.lazy)) {
1712 ticks_to_expire -= ticker->ticks_periodic;
1715 ticks_to_expire -= ticker_remainder_dec(ticker);
1718 ticker->lazy_current--;
1721 while (ticker->lazy_current < user_op->params.update.lazy) {
1722 ticks_to_expire += ticker->ticks_periodic;
1728 ticker->lazy_current++;
1730 ticker->lazy_periodic = user_op->params.update.lazy;
1734 ticker->ticks_to_expire = ticks_to_expire +
1735 user_op->params.update.ticks_drift_plus;
1736 ticker->ticks_to_expire_minus +=
1737 user_op->params.update.ticks_drift_minus;
1741 * (ADV => randomization) if re-sceduling fails. We would still store
1743 * allow the ticker to use the full window for re-scheduling.
1745 struct ticker_ext *ext_data = ticker->ext_data;
1747 if (ext_data && ext_data->ticks_slot_window != 0U) {
1748 ext_data->ticks_drift =
1749 user_op->params.update.ticks_drift_plus -
1750 user_op->params.update.ticks_drift_minus;
1758 ticker->ticks_slot += user_op->params.update.ticks_slot_plus;
1759 if (ticker->ticks_slot > user_op->params.update.ticks_slot_minus) {
1760 ticker->ticks_slot -= user_op->params.update.ticks_slot_minus;
1762 ticker->ticks_slot = 0U;
1767 if (user_op->params.update.force != 0U) {
1768 ticker->force = user_op->params.update.force;
1774 if (user_op->params.update.must_expire) {
1776 ticker->must_expire = (user_op->params.update.must_expire - 1);
1781 if (ticker->ext_data && user_op->params.update.expire_info_id != user_op->id) {
1782 if (user_op->params.update.expire_info_id != TICKER_NULL &&
1783 !ticker->ext_data->other_expire_info) {
1786 status = ticker_alloc_expire_info(instance, user_op->id);
1790 } else if (user_op->params.update.expire_info_id == TICKER_NULL &&
1791 ticker->ext_data->other_expire_info) {
1792 ticker_free_expire_info(instance, user_op->id);
1793 ticker->ext_data->other_expire_info = NULL;
1796 ticker->ext_data->expire_info_id = user_op->params.update.expire_info_id;
1797 if (ticker->ext_data->expire_info_id != TICKER_NULL) {
1798 ticker_mark_expire_info_outdated(instance, user_op->id);
1802 ARG_UNUSED(instance);
1805 ticker->next = *insert_head;
1806 *insert_head = user_op->id;
1818 * @param instance Pointer to ticker instance
1822 * @param insert_head Pointer to current head (id). For update operation,
1823 * contains operation id upon exit
1826 static inline void ticker_job_node_manage(struct ticker_instance *instance,
1833 /* Handle update of ticker by re-inserting it back. */
1835 (user_op->op == TICKER_USER_OP_TYPE_UPDATE)) {
1837 ticker->ticks_to_expire = ticker_dequeue(instance, user_op->id);
1840 ticker_job_node_update(instance, ticker, user_op, ticks_now,
1841 instance->ticks_current, ticks_elapsed,
1845 ticker_mark_expire_info_outdated(instance, user_op->id);
1851 ticker->req++;
1854 if (user_op->op != TICKER_USER_OP_TYPE_YIELD_ABS) {
1856 ticker->ticks_to_expire = ticker_dequeue(instance,
1857 user_op->id);
1860 if (ticker->ext_data && ticker->ext_data->expire_info_id != TICKER_NULL) {
1861 ticker_free_expire_info(instance, user_op->id);
1862 ticker->ext_data->other_expire_info = NULL;
1865 ticker_mark_expire_info_outdated(instance, user_op->id);
1869 ticker->req = ticker->ack;
1874 if (instance->ticker_id_slot_previous == user_op->id) {
1879 if (user_op->op != TICKER_USER_OP_TYPE_YIELD_ABS) {
1880 instance->ticker_id_slot_previous = TICKER_NULL;
1883 if ((user_op->op == TICKER_USER_OP_TYPE_YIELD_ABS) ||
1884 (user_op->op == TICKER_USER_OP_TYPE_STOP_ABS)) {
1886 user_op->params.yield.ticks_at_yield;
1891 ticks_current = instance->ticks_current;
1892 if (!((ticks_at_yield - ticks_current) &
1902 ticks_used = ticks_elapsed -
1909 if (instance->ticks_slot_previous > ticks_used) {
1910 instance->ticks_slot_previous = ticks_used;
1931 * @param instance Pointer to ticker instance
1933 * @param insert_head Pointer to current head (id). For update operation,
1934 * contains operation id upon exit
1938 static inline uint8_t ticker_job_list_manage(struct ticker_instance *instance,
1949 node = &instance->nodes[0];
1950 users = &instance->users[0];
1951 count_user = instance->count_user;
1952 /* Traverse users - highest id first */
1953 while (count_user--) {
1958 user_ops = &user->user_op[0];
1959 /* Traverse user operation queue - middle to last (with wrap).
1960 * This operation updates user->middle to be the past the last
1962 * ticker_job_list_insert, for handling user->first to middle.
1964 while (user->middle != user->last) {
1971 user_op = &user_ops[user->middle];
1974 prev = user->middle;
1975 middle = user->middle + 1;
1976 if (middle == user->count_user_op) {
1979 user->middle = middle;
1981 ticker = &node[user_op->id];
1984 if (user_op->op < TICKER_USER_OP_TYPE_UPDATE) {
1986 if (user_op->op == TICKER_USER_OP_TYPE_START) {
1990 ticker->start_pending = 1U;
1998 state = (ticker->req - ticker->ack) & 0xff;
2003 if ((user_op->op > TICKER_USER_OP_TYPE_STOP_ABS) ||
2006 !ticker->start_pending &&
2008 (user_op->op != TICKER_USER_OP_TYPE_YIELD_ABS)) ||
2009 ((user_op->op == TICKER_USER_OP_TYPE_UPDATE) &&
2010 (user_op->params.update.ticks_drift_plus == 0U) &&
2011 (user_op->params.update.ticks_drift_minus == 0U) &&
2013 (user_op->params.update.ticks_slot_plus == 0U) &&
2014 (user_op->params.update.ticks_slot_minus == 0U) &&
2017 (!ticker->ext_data ||
2018 user_op->params.update.expire_info_id == user_op->id) &&
2020 (user_op->params.update.lazy == 0U) &&
2021 (user_op->params.update.force == 0U))) {
2029 (user_op->op == TICKER_USER_OP_TYPE_YIELD_ABS)) {
2030 ticker_job_node_manage(instance, ticker,
2040 instance->sched_cb(TICKER_CALL_ID_JOB,
2042 instance);
2047 user->middle = prev;
2062 * nodes are removed from the active list, and re-inserted if periodic.
2064 * @param instance Pointer to ticker instance
2067 * @param insert_head Pointer to current head (id). Updated if nodes are
2068 * re-inserted
2071 static inline void ticker_job_worker_bh(struct ticker_instance *instance,
2083 node = &instance->nodes[0];
2085 while (instance->ticker_id_head != TICKER_NULL) {
2093 id_expired = instance->ticker_id_head;
2097 ticks_to_expire = ticker->ticks_to_expire;
2099 ticker->ticks_to_expire -= ticks_elapsed;
2104 ticks_elapsed -= ticks_to_expire;
2105 ticks_latency -= ticks_to_expire;
2108 state = (ticker->req - ticker->ack) & 0xff;
2112 * was either a collision or re-scheduled. This node should
2115 skip_collision = (ticker->lazy_current != 0U);
2120 if (instance->ticks_slot_previous > ticks_to_expire) {
2121 instance->ticks_slot_previous -= ticks_to_expire;
2123 instance->ticker_id_slot_previous = TICKER_NULL;
2124 instance->ticks_slot_previous = 0U;
2129 if (TICKER_HAS_SLOT_WINDOW(ticker) && !ticker->ticks_slot) {
2132 ticker_ticks_slot = ticker->ticks_slot;
2140 instance->ticker_id_slot_previous = id_expired;
2141 instance->ticks_slot_previous = ticker_ticks_slot;
2146 ticker->ticks_to_expire = 0U;
2149 ticker_mark_expire_info_outdated(instance, instance->ticker_id_head);
2153 instance->ticker_id_head = ticker->next;
2155 /* Ticker will be restarted if periodic or to be re-scheduled */
2156 if ((ticker->ticks_periodic != 0U) ||
2160 /* Set the re-scheduled node to now. Will be
2164 ticker->ticks_to_expire = ticks_elapsed;
2170 ticker->req = ticker->ack;
2177 if (!ticker->lazy_current) {
2178 lazy_periodic = ticker->lazy_periodic;
2186 ticker->req = ticker->ack;
2194 while (count--) {
2196 ticker->ticks_periodic;
2211 } else if (!ticker->must_expire) {
2218 ticker->ticks_periodic;
2232 ticker->ticks_to_expire = ticks_to_expire;
2233 ticker->lazy_current += (lazy_periodic + lazy);
2236 ticks_to_expire_prep(ticker, instance->ticks_current,
2245 count = 1 + ticker->lazy_periodic;
2246 while (count--) {
2247 ticks_to_expire += ticker->ticks_periodic;
2258 ticks_to_expire += ticker->ticks_periodic;
2264 ticker->ticks_to_expire = ticks_to_expire;
2265 ticker->lazy_current = ticker->lazy_periodic + lazy;
2267 ticks_to_expire_prep(ticker, instance->ticks_current,
2272 ticker->force = 0U;
2276 ticker->next = *insert_head;
2280 ticker->req++;
2283 /* A single-shot ticker in requested or skipped due to
2288 ticker->fp_op_func) {
2289 ticker->fp_op_func(TICKER_STATUS_FAILURE,
2290 ticker->op_context);
2295 ticker->req = ticker->ack;
2311 static inline uint32_t ticker_job_op_start(struct ticker_instance *instance,
2316 struct ticker_user_op_start *start = (void *)&user_op->params.start;
2320 LL_ASSERT(start->lazy < TICKER_LAZY_MUST_EXPIRE_KEEP);
2323 if (start->lazy != TICKER_LAZY_MUST_EXPIRE_KEEP) {
2325 ticker->must_expire =
2326 (start->lazy == TICKER_LAZY_MUST_EXPIRE) ? 1U : 0U;
2332 ticker->ext_data = start->ext_data;
2335 if (ticker->ext_data) {
2336 ticker->ext_data->other_expire_info = NULL;
2337 if (ticker->ext_data->expire_info_id != TICKER_NULL) {
2340 status = ticker_alloc_expire_info(instance, user_op->id);
2347 ticker_mark_expire_info_outdated(instance, user_op->id);
2349 ARG_UNUSED(instance);
2352 ARG_UNUSED(instance);
2355 ticker->ticks_periodic = start->ticks_periodic;
2358 ticker->remainder_periodic = start->remainder_periodic;
2361 ticker->remainder_current = start->remainder_first;
2363 ticker->remainder_current = 0U;
2367 ticker->lazy_periodic =
2368 (start->lazy < TICKER_LAZY_MUST_EXPIRE_KEEP) ? start->lazy :
2371 ticker->ticks_slot = start->ticks_slot;
2374 ticker->timeout_func = start->fp_timeout_func;
2375 ticker->context = start->context;
2376 ticker->ticks_to_expire = start->ticks_first;
2377 ticker->ticks_to_expire_minus = 0U;
2378 ticks_to_expire_prep(ticker, ticks_current, start->ticks_at_start);
2380 ticker->lazy_current = 0U;
2381 ticker->force = 1U;
2392 * node is un-scheduled. Decision is based on latency and the force-state of
2395 * @param instance Pointer to ticker instance
2396 * @param id_insert Id of ticker to insert
2399 * are un-scheduled
2402 static inline uint8_t ticker_job_insert(struct ticker_instance *instance,
2410 ticker->next = TICKER_NULL;
2413 (void)ticker_enqueue(instance, id_insert);
2416 ticker->req = ticker->ack + 1;
2423 * @brief Re-schedule ticker nodes within slot_window
2425 * @details This function is responsible for re-scheduling ticker nodes
2426 * which have been marked for re-scheduling in ticker_worker. These nodes
2427 * have a non-zero ticks_slot_window configuration, which indicates a
2428 * valid range in which to re-schedule the node.
2429 * The function iterates over nodes, and handles one re-schedule at a
2430 * time. After a re-schedule, nodes are once again iterated until no more
2431 * nodes are marked for re-scheduling.
2433 * @param instance Pointer to ticker instance
2438 static uint8_t ticker_job_reschedule_in_window(struct ticker_instance *instance)
2444 nodes = &instance->nodes[0];
2446 /* Do until all pending re-schedules handled */
2465 /* Find first pending re-schedule */
2467 ticker_id_resched = instance->ticker_id_head;
2476 ticker_id_resched = ticker_resched->next;
2485 LL_ASSERT(ticker_resched->ticks_to_expire == 0U);
2490 if (ticker_resched->ticks_slot) {
2491 ticks_slot = ticker_resched->ticks_slot;
2499 window_start_ticks = instance->ticks_slot_previous +
2507 * drift (ADV => randomization) if re-sceduling fails. Then the
2508 * ticker would have the best possible window to re-schedule in
2509 * and not be restricted to ticks_slot_window - ticks_drift.
2511 ext_data = ticker_resched->ext_data;
2513 ticker_resched->ticks_slot &&
2514 !ext_data->ticks_drift &&
2515 !ext_data->is_drift_in_window) {
2526 ticker_id_next = ticker_resched->next;
2528 } else if (ext_data->ticks_drift < ext_data->ticks_slot_window) {
2530 ticks_slot_window = ext_data->ticks_slot_window -
2531 ext_data->ticks_drift;
2536 ticker_id_next = ticker_resched->next;
2539 /* Window has been exhausted - we can't reschedule */
2546 /* Try to find available slot for re-scheduling */
2557 ticks_to_expire_offset += ticker_next->ticks_to_expire;
2567 ticks_to_expire_offset -
2570 /* Next expiry is too close - try the next
2583 if (!ticker_resched->ticks_slot ||
2584 ext_data->is_drift_in_window) {
2593 ticks_to_expire = window_end_ticks -
2597 /* No space in window - try the next node */
2601 /* Decide if the re-scheduling ticker node fits in the
2602 * slot found - break if it fits
2606 (ticks_to_expire <= (window_end_ticks -
2608 /* Re-scheduled node fits before this node */
2615 /* Skip other pending re-schedule nodes and
2619 !ticker_next->ticks_slot ||
2620 !ticker_next->ticks_periodic) {
2621 ticker_id_next = ticker_next->next;
2626 /* We din't find a valid slot for re-scheduling - try
2631 ticker_next->ticks_slot +
2635 if (!ticker_resched->ticks_slot ||
2636 ext_data->is_drift_in_window) {
2637 if (!ticker_resched->ticks_slot ||
2638 (window_start_ticks <= (ticks_slot_window -
2649 ticks_to_expire = ticks_slot_window -
2653 ticker_id_next = ticker_next->next;
2656 ext_data->ticks_drift += ticks_to_expire;
2661 ticker_id_next = ticker_resched->next;
2667 if (ticks_to_expire > ticker_next->ticks_to_expire) {
2668 /* Node is after this - adjust delta */
2669 ticks_to_expire -= ticker_next->ticks_to_expire;
2672 ticker_next->ticks_to_expire -= ticks_to_expire;
2676 ticker_id_next = ticker_next->next;
2679 ticker_resched->ticks_to_expire = ticks_to_expire;
2687 ticker_resched->next;
2690 instance->ticker_id_head = ticker_resched->next;
2694 ticker_resched->next = nodes[ticker_id_prev].next;
2699 ticker_resched->lazy_current--;
2701 /* Prevent repeated re-scheduling */
2702 ext_data->reschedule_state =
2706 ticker_mark_expire_info_outdated(instance, ticker_id_resched);
2709 /* Check for other pending re-schedules and set exit flag */
2724 * node is un-scheduled. Decision is based on latency and the force-state of
2727 * @param instance Pointer to ticker instance
2728 * @param id_insert Id of ticker to insert
2731 * are un-scheduled
2734 static inline uint8_t ticker_job_insert(struct ticker_instance *instance,
2739 struct ticker_node *node = &instance->nodes[0];
2744 ticker->next = TICKER_NULL;
2747 if (ticker->lazy_current > ticker->lazy_periodic) {
2748 skip = ticker->lazy_current -
2749 ticker->lazy_periodic;
2756 (id_collide = ticker_enqueue(instance, id_insert))) {
2765 if (ticker_collide->lazy_current >
2766 ticker_collide->lazy_periodic) {
2767 skip_collide = ticker_collide->lazy_current -
2768 ticker_collide->lazy_periodic;
2773 /* Check if colliding node should be un-scheduled */
2774 if (ticker_collide->ticks_periodic &&
2776 ticker_collide->force < ticker->force) {
2780 ticker_collide->ticks_to_expire =
2781 ticker_dequeue(instance, id_collide);
2783 ticker_collide->req = ticker_collide->ack;
2785 /* Enqueue for re-insertion */
2786 ticker_collide->next = *insert_head;
2794 if (ticker->ticks_periodic != 0U) {
2795 ticker->ticks_to_expire += ticker->ticks_periodic +
2797 ticker->lazy_current++;
2800 if (ticker->lazy_current > ticker->lazy_periodic) {
2801 skip = ticker->lazy_current -
2802 ticker->lazy_periodic;
2810 if (ticker->ticks_to_expire >
2811 ticker->ticks_to_expire_minus) {
2812 ticker->ticks_to_expire -=
2813 ticker->ticks_to_expire_minus;
2814 ticker->ticks_to_expire_minus = 0U;
2816 ticker->ticks_to_expire_minus -=
2817 ticker->ticks_to_expire;
2818 ticker->ticks_to_expire = 0U;
2826 ticker->req = ticker->ack + 1;
2839 * @param instance Pointer to ticker instance
2840 * @param insert_head Id of ticker node to insert, or TICKER_NULL if only
2844 static inline void ticker_job_list_insert(struct ticker_instance *instance,
2851 node = &instance->nodes[0];
2852 users = &instance->users[0];
2853 count_user = instance->count_user;
2856 while (count_user--) {
2862 user_ops = (void *)&user->user_op[0];
2863 user_ops_first = user->first;
2864 /* Traverse user operation queue - first to middle (wrap) */
2866 (user_ops_first != user->middle)) {
2878 insert_head = ticker->next;
2889 if (first == user->count_user_op) {
2894 id_insert = user_op->id;
2896 if (user_op->op != TICKER_USER_OP_TYPE_START) {
2897 /* User operation is not start - skip
2904 ticker->start_pending = 0U;
2907 if (((ticker->req -
2908 ticker->ack) & 0xff) != 0U) {
2915 status = ticker_job_op_start(instance, ticker, user_op,
2916 instance->ticks_current);
2921 status = ticker_job_insert(instance, id_insert, ticker,
2929 (ticker->ticks_periodic == 0U) &&
2931 ticker->fp_op_func =
2932 user_op->fp_op_func;
2933 ticker->op_context =
2934 user_op->op_context;
2942 user->first = user_ops_first;
2957 * @param instance Pointer to ticker instance
2962 static inline void ticker_job_op_inquire(struct ticker_instance *instance,
2968 switch (uop->op) {
2971 ticker_by_next_slot_get(instance,
2972 uop->params.slot_get.ticker_id,
2973 uop->params.slot_get.ticks_current,
2974 uop->params.slot_get.ticks_to_expire,
2976 uop->params.slot_get.fp_match_op_func,
2977 uop->params.slot_get.match_op_context,
2982 uop->params.slot_get.remainder,
2987 uop->params.slot_get.lazy);
2997 uop->status = TICKER_STATUS_SUCCESS;
2998 fp_op_func = uop->fp_op_func;
3008 if (uop->id < instance->count_node) {
3009 struct ticker_node *node = instance->nodes;
3011 node[uop->id].priority =
3012 uop->params.priority_set.priority;
3013 uop->status = TICKER_STATUS_SUCCESS;
3015 uop->status = TICKER_STATUS_FAILURE;
3017 fp_op_func = uop->fp_op_func;
3030 fp_op_func(uop->status, uop->op_context);
3041 * This operation modifies the user->first index, indicating user operations
3044 * @param instance Pointer to ticker instance
3048 static inline void ticker_job_list_inquire(struct ticker_instance *instance)
3053 users = &instance->users[0];
3054 count_user = instance->count_user;
3055 /* Traverse user operation queue - first to last (with wrap) */
3056 while (count_user--) {
3061 user_op = &user->user_op[0];
3062 while (user->first != user->last) {
3065 ticker_job_op_inquire(instance, &user_op[user->first]);
3067 first = user->first + 1;
3068 if (first == user->count_user_op) {
3071 user->first = first;
3085 * and makes sure - by iteration - that compare value is set in the future
3088 * @param instance Pointer to ticker instance
3094 ticker_job_compare_update(struct ticker_instance *instance,
3104 if (instance->ticker_id_head == TICKER_NULL) {
3107 instance->ticks_slot_previous = 0U;
3114 instance->ticks_current = cntr_cnt_get();
3138 instance->ticks_current = ticks_current;
3143 ticker = &instance->nodes[instance->ticker_id_head];
3144 ticks_to_expire = ticker->ticks_to_expire;
3154 * the operation is pre-empted and current h/w counter runs
3164 i--;
3166 cc = instance->ticks_current;
3176 instance->trigger_set_cb(cc);
3192 * re-inserting ticker nodes, based on next elapsing and periodicity of the
3197 * @param param Pointer to ticker instance
3203 struct ticker_instance *instance = param;
3217 if (instance->worker_trigger) {
3223 if (instance->job_guard) {
3224 instance->sched_cb(TICKER_CALL_ID_JOB, TICKER_CALL_ID_JOB, 1,
3225 instance);
3228 instance->job_guard = 1U;
3231 ticks_previous = instance->ticks_current;
3234 if (instance->ticks_elapsed_first != instance->ticks_elapsed_last) {
3235 ticker_next_elapsed(&instance->ticks_elapsed_first);
3238 instance->ticks_elapsed[instance->ticks_elapsed_first];
3240 instance->ticks_current += ticks_elapsed;
3241 instance->ticks_current &= HAL_TICKER_CNTR_MASK;
3250 /* Initialise internal re-insert list */
3259 ticker_id_old_head = instance->ticker_id_head;
3278 instance->ticks_current = ticks_now;
3284 pending = ticker_job_list_manage(instance, ticks_now, ticks_elapsed,
3288 if (instance->ticker_id_head != ticker_id_old_head) {
3294 ticker_job_worker_bh(instance, ticks_now, ticks_previous,
3298 if (instance->ticker_id_head != ticker_id_old_head) {
3303 ticker_job_list_insert(instance, insert_head);
3307 /* Re-schedule any pending nodes with slot_window */
3308 if (ticker_job_reschedule_in_window(instance)) {
3314 ticker_job_list_insert(instance, insert_head);
3318 if (instance->ticker_id_head != ticker_id_old_head) {
3328 ticker_job_list_inquire(instance);
3341 if (instance->expire_infos_outdated) {
3342 ticker_job_update_expire_infos(instance);
3348 compare_trigger = ticker_job_compare_update(instance,
3355 instance->job_guard = 0U;
3359 if (instance->worker_trigger || compare_trigger) {
3360 instance->sched_cb(TICKER_CALL_ID_JOB, TICKER_CALL_ID_WORKER, 1,
3361 instance);
3372 * @brief Initialize ticker instance
3374 * @details Called by ticker instance client once to initialize the ticker.
3376 * @param instance_index Index of ticker instance
3384 * user id
3399 struct ticker_instance *instance = &_instance[instance_index];
3407 instance->count_node = count_node;
3408 instance->nodes = node;
3413 while (count_node--) {
3414 instance->nodes[count_node].priority = 0;
3421 instance->count_user = count_user;
3422 instance->users = user;
3426 users = &instance->users[0];
3427 while (count_user--) {
3430 count_op -= users[count_user].count_user_op;
3437 instance->caller_id_get_cb = caller_id_get_cb;
3438 instance->sched_cb = sched_cb;
3439 instance->trigger_set_cb = trigger_set_cb;
3441 instance->ticker_id_head = TICKER_NULL;
3444 instance->ticks_current = 0U;
3447 instance->ticks_current = cntr_cnt_get();
3449 instance->ticks_elapsed_first = 0U;
3450 instance->ticks_elapsed_last = 0U;
3453 instance->ticker_id_slot_previous = TICKER_NULL;
3454 instance->ticks_slot_previous = 0U;
3459 instance->expire_infos[i].ticker_id = TICKER_NULL;
3460 instance->expire_infos[i].last = 1;
3468 * @brief Check if ticker instance is initialized
3470 * @param instance_index Index of ticker instance
3472 * @return true if ticker instance is initialized, false otherwise
3485 * @param instance_index Index of ticker instance
3489 struct ticker_instance *instance;
3493 instance = &_instance[instance_index];
3494 if (instance->sched_cb) {
3495 instance->sched_cb(TICKER_CALL_ID_TRIGGER,
3496 TICKER_CALL_ID_WORKER, 1, instance);
3508 * @param instance_index Index of ticker instance
3509 * @param user_id Ticker user id. Used for indexing user operations
3510 * and mapping to mayfly caller id
3511 * @param ticker_id Id of ticker node
3516 * ticker node is treated as one-shot
3520 * @param ticks_slot Slot reservation ticks for node (air-time)
3522 * re-scheduled to avoid collision. Set to 0 for
3627 struct ticker_instance *instance = &_instance[instance_index];
3632 user = &instance->users[user_id];
3634 last = user->last + 1;
3635 if (last >= user->count_user_op) {
3639 if (last == user->first) {
3643 user_op = &user->user_op[user->last];
3644 user_op->op = TICKER_USER_OP_TYPE_START;
3645 user_op->id = ticker_id;
3646 user_op->params.start.ticks_at_start = ticks_anchor;
3647 user_op->params.start.ticks_first = ticks_first;
3648 user_op->params.start.ticks_periodic = ticks_periodic;
3651 user_op->params.start.remainder_periodic = remainder_periodic;
3654 user_op->params.start.remainder_first = remainder_first;
3661 user_op->params.start.ticks_slot = ticks_slot;
3663 user_op->params.start.lazy = lazy;
3665 user_op->params.start.ext_data = ext_data;
3667 user_op->params.start.fp_timeout_func = fp_timeout_func;
3668 user_op->params.start.context = context;
3669 user_op->status = TICKER_STATUS_BUSY;
3670 user_op->fp_op_func = fp_op_func;
3671 user_op->op_context = op_context;
3675 user->last = last;
3677 instance->sched_cb(instance->caller_id_get_cb(user_id),
3678 TICKER_CALL_ID_JOB, 0, instance);
3680 return user_op->status;
3690 * @param instance_index Index of ticker instance
3691 * @param user_id Ticker user id. Used for indexing user operations
3692 * and mapping to mayfly caller id
3693 * @param ticker_id Id of ticker node
3701 * value >1 means latency = lazy - 1
3708 * @param must_expire Disable, enable or ignore the must-expire state.
3756 struct ticker_instance *instance = &_instance[instance_index];
3761 user = &instance->users[user_id];
3763 last = user->last + 1;
3764 if (last >= user->count_user_op) {
3768 if (last == user->first) {
3772 user_op = &user->user_op[user->last];
3773 user_op->op = TICKER_USER_OP_TYPE_UPDATE;
3774 user_op->id = ticker_id;
3775 user_op->params.update.ticks_drift_plus = ticks_drift_plus;
3776 user_op->params.update.ticks_drift_minus = ticks_drift_minus;
3778 user_op->params.update.ticks_slot_plus = ticks_slot_plus;
3779 user_op->params.update.ticks_slot_minus = ticks_slot_minus;
3781 user_op->params.update.lazy = lazy;
3782 user_op->params.update.force = force;
3785 user_op->params.update.must_expire = must_expire;
3788 user_op->params.update.expire_info_id = expire_info_id;
3791 user_op->status = TICKER_STATUS_BUSY;
3792 user_op->fp_op_func = fp_op_func;
3793 user_op->op_context = op_context;
3797 user->last = last;
3799 instance->sched_cb(instance->caller_id_get_cb(user_id),
3800 TICKER_CALL_ID_JOB, 0, instance);
3802 return user_op->status;
3812 * @param instance_index Index of ticker instance
3813 * @param user_id Ticker user id. Used for indexing user operations
3814 * and mapping to mayfly caller id
3829 struct ticker_instance *instance = &_instance[instance_index];
3834 user = &instance->users[user_id];
3836 last = user->last + 1;
3837 if (last >= user->count_user_op) {
3841 if (last == user->first) {
3845 user_op = &user->user_op[user->last];
3846 user_op->op = TICKER_USER_OP_TYPE_YIELD_ABS;
3847 user_op->id = ticker_id;
3848 user_op->params.yield.ticks_at_yield = ticks_at_yield;
3849 user_op->status = TICKER_STATUS_BUSY;
3850 user_op->fp_op_func = fp_op_func;
3851 user_op->op_context = op_context;
3855 user->last = last;
3857 instance->sched_cb(instance->caller_id_get_cb(user_id),
3858 TICKER_CALL_ID_JOB, 0, instance);
3860 return user_op->status;
3869 * @param instance_index Index of ticker instance
3870 * @param user_id Ticker user id. Used for indexing user operations
3871 * and mapping to mayfly caller id
3884 struct ticker_instance *instance = &_instance[instance_index];
3889 user = &instance->users[user_id];
3891 last = user->last + 1;
3892 if (last >= user->count_user_op) {
3896 if (last == user->first) {
3900 user_op = &user->user_op[user->last];
3901 user_op->op = TICKER_USER_OP_TYPE_STOP;
3902 user_op->id = ticker_id;
3903 user_op->status = TICKER_STATUS_BUSY;
3904 user_op->fp_op_func = fp_op_func;
3905 user_op->op_context = op_context;
3909 user->last = last;
3911 instance->sched_cb(instance->caller_id_get_cb(user_id),
3912 TICKER_CALL_ID_JOB, 0, instance);
3914 return user_op->status;
3923 * @param instance_index Index of ticker instance
3924 * @param user_id Ticker user id. Used for indexing user operations
3925 * and mapping to mayfly caller id
3940 struct ticker_instance *instance = &_instance[instance_index];
3945 user = &instance->users[user_id];
3947 last = user->last + 1;
3948 if (last >= user->count_user_op) {
3952 if (last == user->first) {
3956 user_op = &user->user_op[user->last];
3957 user_op->op = TICKER_USER_OP_TYPE_STOP_ABS;
3958 user_op->id = ticker_id;
3959 user_op->params.yield.ticks_at_yield = ticks_at_stop;
3960 user_op->status = TICKER_STATUS_BUSY;
3961 user_op->fp_op_func = fp_op_func;
3962 user_op->op_context = op_context;
3966 user->last = last;
3968 instance->sched_cb(instance->caller_id_get_cb(user_id),
3969 TICKER_CALL_ID_JOB, 0, instance);
3971 return user_op->status;
3979 * return the ticker id and accumulated ticks until expiration. If no
3981 * If no head id is provided (TICKER_NULL) the first node is returned.
3983 * @param instance_index Index of ticker instance
3984 * @param user_id Ticker user id. Used for indexing user operations
3985 * and mapping to mayfly caller id
3986 * @param ticker_id Pointer to id of ticker node
4024 struct ticker_instance *instance = &_instance[instance_index];
4029 user = &instance->users[user_id];
4031 last = user->last + 1;
4032 if (last >= user->count_user_op) {
4036 if (last == user->first) {
4040 user_op = &user->user_op[user->last];
4041 user_op->op = TICKER_USER_OP_TYPE_SLOT_GET;
4042 user_op->id = TICKER_NULL;
4043 user_op->params.slot_get.ticker_id = ticker_id;
4044 user_op->params.slot_get.ticks_current = ticks_current;
4045 user_op->params.slot_get.ticks_to_expire = ticks_to_expire;
4047 user_op->params.slot_get.remainder = remainder;
4050 user_op->params.slot_get.lazy = lazy;
4053 user_op->params.slot_get.fp_match_op_func = fp_match_op_func;
4054 user_op->params.slot_get.match_op_context = match_op_context;
4056 user_op->status = TICKER_STATUS_BUSY;
4057 user_op->fp_op_func = fp_op_func;
4058 user_op->op_context = op_context;
4062 user->last = last;
4064 instance->sched_cb(instance->caller_id_get_cb(user_id),
4065 TICKER_CALL_ID_JOB, 0, instance);
4067 return user_op->status;
4078 * @param instance_index Index of ticker instance
4079 * @param user_id Ticker user id. Used for indexing user operations
4080 * and mapping to mayfly caller id
4093 struct ticker_instance *instance = &_instance[instance_index];
4098 user = &instance->users[user_id];
4100 last = user->last + 1;
4101 if (last >= user->count_user_op) {
4105 if (last == user->first) {
4109 user_op = &user->user_op[user->last];
4110 user_op->op = TICKER_USER_OP_TYPE_IDLE_GET;
4111 user_op->id = TICKER_NULL;
4112 user_op->status = TICKER_STATUS_BUSY;
4113 user_op->fp_op_func = fp_op_func;
4114 user_op->op_context = op_context;
4118 user->last = last;
4120 instance->sched_cb(instance->caller_id_get_cb(user_id),
4121 TICKER_CALL_ID_JOB, 0, instance);
4123 return user_op->status;
4133 * @param instance_index Index of ticker instance
4134 * @param user_id Ticker user id. Used for indexing user operations
4135 * and mapping to mayfly caller id
4136 * @param ticker_id Id of ticker node to set priority on
4137 * @param priority Priority to set. Range [-128..127], default is 0.
4139 * priority to -128 (TICKER_PRIORITY_CRITICAL) makes
4155 struct ticker_instance *instance = &_instance[instance_index];
4160 user = &instance->users[user_id];
4162 last = user->last + 1;
4163 if (last >= user->count_user_op) {
4167 if (last == user->first) {
4171 user_op = &user->user_op[user->last];
4172 user_op->op = TICKER_USER_OP_TYPE_PRIORITY_SET;
4173 user_op->id = ticker_id;
4174 user_op->params.priority_set.priority = priority;
4175 user_op->status = TICKER_STATUS_BUSY;
4176 user_op->fp_op_func = fp_op_func;
4177 user_op->op_context = op_context;
4181 user->last = last;
4183 instance->sched_cb(instance->caller_id_get_cb(user_id),
4184 TICKER_CALL_ID_JOB, 0, instance);
4186 return user_op->status;
4196 * @param instance_index Index of ticker instance
4197 * @param user_id Ticker user id. Maps to mayfly caller id
4201 struct ticker_instance *instance = &_instance[instance_index];
4203 instance->sched_cb(instance->caller_id_get_cb(user_id),
4204 TICKER_CALL_ID_JOB, 0, instance);
4228 return ((ticks_now - ticks_old) & HAL_TICKER_CNTR_MASK);