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