1 /*
2  * Copyright (c) 2016-2018 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdint.h>
9 #include <stdbool.h>
10 
11 #include "hal/cntr.h"
12 
13 #include "util/memq.h"
14 #include "util/mayfly.h"
15 
16 #include "ticker/ticker.h"
17 
18 #include "hal/debug.h"
19 
20 #if defined(CONFIG_BT_LL_SW_SPLIT)
21 #include "ll_sw/lll.h"
22 #define TICKER_MAYFLY_CALL_ID_ISR     TICKER_USER_ID_LLL
23 #define TICKER_MAYFLY_CALL_ID_TRIGGER TICKER_USER_ID_ULL_HIGH
24 #define TICKER_MAYFLY_CALL_ID_WORKER  TICKER_USER_ID_ULL_HIGH
25 #define TICKER_MAYFLY_CALL_ID_JOB     TICKER_USER_ID_ULL_LOW
26 #define TICKER_MAYFLY_CALL_ID_PROGRAM TICKER_USER_ID_THREAD
27 static uint8_t const caller_id_lut[] = {
28 	TICKER_CALL_ID_ISR,
29 	TICKER_CALL_ID_WORKER,
30 	TICKER_CALL_ID_JOB,
31 	TICKER_CALL_ID_PROGRAM
32 };
33 #else
34 #error Unknown LL variant.
35 #endif
36 
hal_ticker_instance0_caller_id_get(uint8_t user_id)37 uint8_t hal_ticker_instance0_caller_id_get(uint8_t user_id)
38 {
39 	uint8_t caller_id;
40 
41 	LL_ASSERT(user_id < sizeof(caller_id_lut));
42 
43 	caller_id = caller_id_lut[user_id];
44 	LL_ASSERT(caller_id != TICKER_CALL_ID_NONE);
45 
46 	return caller_id;
47 }
48 
hal_ticker_instance0_sched(uint8_t caller_id,uint8_t callee_id,uint8_t chain,void * instance)49 void hal_ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, uint8_t chain,
50 				void *instance)
51 {
52 	/* return value not checked as we allow multiple calls to schedule
53 	 * before being actually needing the work to complete before new
54 	 * schedule.
55 	 */
56 	switch (caller_id) {
57 #if defined(CONFIG_BT_LL_SW_SPLIT)
58 	case TICKER_CALL_ID_ISR:
59 		switch (callee_id) {
60 		case TICKER_CALL_ID_JOB:
61 		{
62 			static memq_link_t link;
63 			static struct mayfly m = {0, 0, &link, NULL,
64 						  ticker_job};
65 
66 			m.param = instance;
67 
68 			/* TODO: scheduler lock, if preemptive threads used */
69 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_ISR,
70 				       TICKER_MAYFLY_CALL_ID_JOB,
71 				       chain,
72 				       &m);
73 		}
74 		break;
75 
76 		default:
77 			LL_ASSERT(0);
78 			break;
79 		}
80 		break;
81 #endif /* CONFIG_BT_LL_SW_SPLIT */
82 
83 	case TICKER_CALL_ID_TRIGGER:
84 		switch (callee_id) {
85 		case TICKER_CALL_ID_WORKER:
86 		{
87 			static memq_link_t link;
88 			static struct mayfly m = {0, 0, &link, NULL,
89 						  ticker_worker};
90 
91 			m.param = instance;
92 
93 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER,
94 				       TICKER_MAYFLY_CALL_ID_WORKER,
95 				       chain,
96 				       &m);
97 		}
98 		break;
99 
100 		default:
101 			LL_ASSERT(0);
102 			break;
103 		}
104 		break;
105 
106 	case TICKER_CALL_ID_WORKER:
107 		switch (callee_id) {
108 		case TICKER_CALL_ID_JOB:
109 		{
110 			static memq_link_t link;
111 			static struct mayfly m = {0, 0, &link, NULL,
112 						  ticker_job};
113 
114 			m.param = instance;
115 
116 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER,
117 				       TICKER_MAYFLY_CALL_ID_JOB,
118 				       chain,
119 				       &m);
120 		}
121 		break;
122 
123 		default:
124 			LL_ASSERT(0);
125 			break;
126 		}
127 		break;
128 
129 	case TICKER_CALL_ID_JOB:
130 		switch (callee_id) {
131 		case TICKER_CALL_ID_WORKER:
132 		{
133 			static memq_link_t link;
134 			static struct mayfly m = {0, 0, &link, NULL,
135 						  ticker_worker};
136 
137 			m.param = instance;
138 
139 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
140 				       TICKER_MAYFLY_CALL_ID_WORKER,
141 				       chain,
142 				       &m);
143 		}
144 		break;
145 
146 		case TICKER_CALL_ID_JOB:
147 		{
148 			static memq_link_t link;
149 			static struct mayfly m = {0, 0, &link, NULL,
150 						  ticker_job};
151 
152 			m.param = instance;
153 
154 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB,
155 				       TICKER_MAYFLY_CALL_ID_JOB,
156 				       chain,
157 				       &m);
158 		}
159 		break;
160 
161 		default:
162 			LL_ASSERT(0);
163 			break;
164 		}
165 		break;
166 
167 	case TICKER_CALL_ID_PROGRAM:
168 		switch (callee_id) {
169 		case TICKER_CALL_ID_JOB:
170 		{
171 			static memq_link_t link;
172 			static struct mayfly m = {0, 0, &link, NULL,
173 						  ticker_job};
174 
175 			m.param = instance;
176 
177 			/* TODO: scheduler lock, if preemptive threads used */
178 			mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM,
179 				       TICKER_MAYFLY_CALL_ID_JOB,
180 				       chain,
181 				       &m);
182 		}
183 		break;
184 
185 		default:
186 			LL_ASSERT(0);
187 			break;
188 		}
189 		break;
190 
191 	default:
192 		LL_ASSERT(0);
193 		break;
194 	}
195 }
196 
hal_ticker_instance0_trigger_set(uint32_t value)197 void hal_ticker_instance0_trigger_set(uint32_t value)
198 {
199 	cntr_cmp_set(0, value);
200 }
201