1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #ifndef _NIMBLE_NPL_OS_H_
21 #define _NIMBLE_NPL_OS_H_
22
23 #include <stdint.h>
24 #include <stdbool.h>
25 #include "event/callback.h"
26 #include "mutex.h"
27 #include "semaphore.h"
28 #include "xtimer.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 #define BLE_NPL_OS_ALIGNMENT 4
35
36 #define BLE_NPL_TIME_FOREVER UINT32_MAX
37
38 typedef uint32_t ble_npl_time_t;
39 typedef int32_t ble_npl_stime_t;
40
41 struct ble_npl_event {
42 event_callback_t e;
43 void *arg;
44 };
45
46 struct ble_npl_eventq {
47 event_queue_t q;
48 };
49
50 struct ble_npl_callout {
51 xtimer_t timer;
52 ble_npl_time_t target_ticks;
53 struct ble_npl_event e;
54 event_queue_t *q;
55 };
56
57 struct ble_npl_mutex {
58 mutex_t mu;
59 };
60
61 struct ble_npl_sem {
62 sem_t sem;
63 };
64
65 static inline bool
ble_npl_os_started(void)66 ble_npl_os_started(void)
67 {
68 return true;
69 }
70
71 static inline void *
ble_npl_get_current_task_id(void)72 ble_npl_get_current_task_id(void)
73 {
74 return (void *)(uint32_t)thread_getpid();
75 }
76
77 static inline void
ble_npl_eventq_init(struct ble_npl_eventq * evq)78 ble_npl_eventq_init(struct ble_npl_eventq *evq)
79 {
80 event_queue_init(&evq->q);
81 }
82
83 static inline void
ble_npl_eventq_put(struct ble_npl_eventq * evq,struct ble_npl_event * ev)84 ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
85 {
86 event_post(&evq->q, &ev->e.super);
87 }
88
89 static inline struct ble_npl_event *
ble_npl_eventq_get(struct ble_npl_eventq * evq,ble_npl_time_t tmo)90 ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
91 {
92 assert((tmo == 0) || (tmo == BLE_NPL_TIME_FOREVER));
93
94 if (tmo == 0) {
95 return (struct ble_npl_event *)event_get(&evq->q);
96 } else {
97 return (struct ble_npl_event *)event_wait(&evq->q);
98 }
99 }
100
101 static inline void
ble_npl_eventq_remove(struct ble_npl_eventq * evq,struct ble_npl_event * ev)102 ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
103 {
104 event_cancel(&evq->q, &ev->e.super);
105 }
106
107 static inline void
ble_npl_event_run(struct ble_npl_event * ev)108 ble_npl_event_run(struct ble_npl_event *ev)
109 {
110 ev->e.super.handler(&ev->e.super);
111 }
112
113 static inline void
ble_npl_event_init(struct ble_npl_event * ev,ble_npl_event_fn * fn,void * arg)114 ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg)
115 {
116 /*
117 * Need to clear list_node manually since init function below does not do
118 * this.
119 */
120 ev->e.super.list_node.next = NULL;
121 event_callback_init(&ev->e, (void(*)(void *))fn, ev);
122 ev->arg = arg;
123 }
124
125 static inline bool
ble_npl_event_is_queued(struct ble_npl_event * ev)126 ble_npl_event_is_queued(struct ble_npl_event *ev)
127 {
128 return (ev->e.super.list_node.next != NULL);
129 }
130
131 static inline void *
ble_npl_event_get_arg(struct ble_npl_event * ev)132 ble_npl_event_get_arg(struct ble_npl_event *ev)
133 {
134 return ev->arg;
135 }
136
137 static inline void
ble_npl_event_set_arg(struct ble_npl_event * ev,void * arg)138 ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg)
139 {
140 ev->arg = arg;
141 }
142
143 static inline ble_npl_error_t
ble_npl_mutex_init(struct ble_npl_mutex * mu)144 ble_npl_mutex_init(struct ble_npl_mutex *mu)
145 {
146 mutex_init(&mu->mu);
147 return BLE_NPL_OK;
148 }
149
150 static inline ble_npl_error_t
ble_npl_mutex_pend(struct ble_npl_mutex * mu,ble_npl_time_t timeout)151 ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
152 {
153 assert(timeout == BLE_NPL_TIME_FOREVER);
154 (void)timeout;
155
156 mutex_lock(&mu->mu);
157 return BLE_NPL_OK;
158 }
159
160 static inline ble_npl_error_t
ble_npl_mutex_release(struct ble_npl_mutex * mu)161 ble_npl_mutex_release(struct ble_npl_mutex *mu)
162 {
163 mutex_unlock(&mu->mu);
164 return BLE_NPL_OK;
165 }
166
167 static inline ble_npl_error_t
ble_npl_sem_init(struct ble_npl_sem * sem,uint16_t tokens)168 ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
169 {
170 int rc;
171
172 rc = sem_init(&sem->sem, 0, tokens);
173
174 return rc == 0 ? BLE_NPL_OK : BLE_NPL_ERROR;
175 }
176
177 static inline ble_npl_error_t
ble_npl_sem_release(struct ble_npl_sem * sem)178 ble_npl_sem_release(struct ble_npl_sem *sem)
179 {
180 int rc;
181
182 rc = sem_post(&sem->sem);
183
184 return rc == 0 ? BLE_NPL_OK : BLE_NPL_ERROR;
185 }
186
187 static inline uint16_t
ble_npl_sem_get_count(struct ble_npl_sem * sem)188 ble_npl_sem_get_count(struct ble_npl_sem *sem)
189 {
190 int val = 0;
191
192 sem_getvalue(&sem->sem, &val);
193
194 return (uint16_t)val;
195 }
196
197 static inline void
ble_npl_callout_stop(struct ble_npl_callout * co)198 ble_npl_callout_stop(struct ble_npl_callout *co)
199 {
200 xtimer_remove(&co->timer);
201 }
202
203 static inline bool
ble_npl_callout_is_active(struct ble_npl_callout * c)204 ble_npl_callout_is_active(struct ble_npl_callout *c)
205 {
206 return (c->timer.target || c->timer.long_target);
207 }
208
209 static inline ble_npl_time_t
ble_npl_callout_get_ticks(struct ble_npl_callout * co)210 ble_npl_callout_get_ticks(struct ble_npl_callout *co)
211 {
212 return co->target_ticks;
213 }
214
215 static inline uint32_t
ble_npl_time_get(void)216 ble_npl_time_get(void)
217 {
218 return xtimer_now_usec() / 1000;
219 }
220
221 static inline ble_npl_error_t
ble_npl_time_ms_to_ticks(uint32_t ms,ble_npl_time_t * out_ticks)222 ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
223 {
224 *out_ticks = ms;
225 return BLE_NPL_OK;
226 }
227
228 static inline ble_npl_error_t
ble_npl_time_ticks_to_ms(ble_npl_time_t ticks,uint32_t * out_ms)229 ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
230 {
231 *out_ms = ticks;
232 return BLE_NPL_OK;
233 }
234
235 static inline ble_npl_time_t
ble_npl_time_ms_to_ticks32(uint32_t ms)236 ble_npl_time_ms_to_ticks32(uint32_t ms)
237 {
238 return ms;
239 }
240
241 static inline uint32_t
ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)242 ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)
243 {
244 return ticks;
245 }
246
247 static inline uint32_t
ble_npl_hw_enter_critical(void)248 ble_npl_hw_enter_critical(void)
249 {
250 return (uint32_t)irq_disable();
251 }
252
253 static inline void
ble_npl_hw_exit_critical(uint32_t ctx)254 ble_npl_hw_exit_critical(uint32_t ctx)
255 {
256 irq_restore((unsigned)ctx);
257 }
258
259 #ifdef __cplusplus
260 }
261 #endif
262
263 #endif /* _NPL_H_ */
264