1 /** @file
2 * @brief Bluetooth Controller Ticker functions
3 *
4 */
5
6 /*
7 * Copyright (c) 2017-2018 Nordic Semiconductor ASA
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <zephyr/kernel.h>
13
14 #include <zephyr/bluetooth/bluetooth.h>
15 #include <zephyr/bluetooth/conn.h>
16
17 #include <zephyr/shell/shell.h>
18
19 #include "controller/util/memq.h"
20 #include "controller/util/mayfly.h"
21 #include "controller/hal/ticker.h"
22 #include "controller/ticker/ticker.h"
23
24 #if defined(CONFIG_BT_MAX_CONN)
25 #define TICKERS_MAX (CONFIG_BT_MAX_CONN + 2)
26 #else
27 #define TICKERS_MAX 2
28 #endif
29
30 #include "host/shell/bt.h"
31
ticker_op_done(uint32_t err,void * context)32 static void ticker_op_done(uint32_t err, void *context)
33 {
34 *((uint32_t volatile *)context) = err;
35 }
36
cmd_ticker_info(const struct shell * sh,size_t argc,char * argv[])37 int cmd_ticker_info(const struct shell *sh, size_t argc, char *argv[])
38 {
39 struct {
40 uint8_t id;
41 uint32_t ticks_to_expire;
42 } tickers[TICKERS_MAX];
43 uint32_t ticks_to_expire;
44 uint32_t ticks_current;
45 uint8_t tickers_count;
46 uint8_t ticker_id;
47 uint8_t retry;
48 uint8_t i;
49
50 ticker_id = TICKER_NULL;
51 ticks_to_expire = 0U;
52 ticks_current = 0U;
53 tickers_count = 0U;
54 retry = 4U;
55 do {
56 uint32_t volatile err_cb = TICKER_STATUS_BUSY;
57 uint32_t ticks_previous;
58 uint32_t err;
59
60 ticks_previous = ticks_current;
61
62 err = ticker_next_slot_get(0, MAYFLY_CALL_ID_PROGRAM,
63 &ticker_id, &ticks_current,
64 &ticks_to_expire,
65 ticker_op_done, (void *)&err_cb);
66 if (err == TICKER_STATUS_BUSY) {
67 while (err_cb == TICKER_STATUS_BUSY) {
68 ticker_job_sched(0, MAYFLY_CALL_ID_PROGRAM);
69 }
70 }
71
72 if ((err_cb != TICKER_STATUS_SUCCESS) ||
73 (ticker_id == TICKER_NULL)) {
74 shell_print(sh, "Query done (0x%02x, err= %u).",
75 ticker_id, err);
76
77 break;
78 }
79
80 if (ticks_current != ticks_previous) {
81 retry--;
82 if (!retry) {
83 shell_print(sh, "Retry again, tickers too "
84 "busy now.");
85
86 return -EAGAIN;
87 }
88
89 if (tickers_count) {
90 tickers_count = 0U;
91
92 shell_print(sh, "Query reset, %u retries "
93 "remaining.", retry);
94 }
95 }
96
97 tickers[tickers_count].id = ticker_id;
98 tickers[tickers_count].ticks_to_expire = ticks_to_expire;
99 tickers_count++;
100
101 } while (tickers_count < TICKERS_MAX);
102
103 shell_print(sh, "Tickers: %u.", tickers_count);
104 shell_print(sh, "Tick: %u (%uus).", ticks_current,
105 HAL_TICKER_TICKS_TO_US(ticks_current));
106
107 if (!tickers_count) {
108 return 0;
109 }
110
111 shell_print(sh, "---------------------");
112 shell_print(sh, " id offset offset");
113 shell_print(sh, " (tick) (us)");
114 shell_print(sh, "---------------------");
115 for (i = 0U; i < tickers_count; i++) {
116 shell_print(sh, "%03u %08u %08u", tickers[i].id,
117 tickers[i].ticks_to_expire,
118 HAL_TICKER_TICKS_TO_US(tickers[i].ticks_to_expire));
119 }
120 shell_print(sh, "---------------------");
121
122 return 0;
123 }
124
125 #define HELP_NONE "[none]"
126
127 SHELL_STATIC_SUBCMD_SET_CREATE(ticker_cmds,
128 SHELL_CMD_ARG(info, NULL, HELP_NONE, cmd_ticker_info, 1, 0),
129 SHELL_SUBCMD_SET_END
130 );
131
cmd_ticker(const struct shell * sh,size_t argc,char ** argv)132 static int cmd_ticker(const struct shell *sh, size_t argc, char **argv)
133 {
134 if (argc == 1) {
135 shell_help(sh);
136 /* shell returns 1 when help is printed */
137 return 1;
138 }
139
140 shell_error(sh, "%s:%s%s", argv[0], "unknown parameter: ", argv[1]);
141 return -ENOEXEC;
142 }
143
144 SHELL_CMD_ARG_REGISTER(ticker, &ticker_cmds, "Bluetooth Ticker shell commands",
145 cmd_ticker, 1, 1);
146