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 #include <assert.h>
21 #include <stddef.h>
22 #include <string.h>
23 #include "securec.h"
24 #include "nimble/nimble_npl.h"
25 #include "wm_osal.h"
26
npl_freertos_eventq_get(struct ble_npl_eventq * evq,ble_npl_time_t tmo)27 struct ble_npl_event *npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
28 {
29 struct ble_npl_event *ev = NULL;
30 tls_os_status_t status;
31 status = tls_os_queue_receive(evq->q, (void **)&ev, sizeof(ev), tmo);
32 if (status == TLS_OS_SUCCESS) {
33 if (ev) {
34 ev->queued = false;
35 }
36 }
37
38 return ev;
39 }
40
npl_freertos_eventq_put(struct ble_npl_eventq * evq,struct ble_npl_event * ev)41 void npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
42 {
43 tls_os_status_t status;
44
45 if (ev->queued) {
46 return;
47 }
48
49 ev->queued = true;
50 status = tls_os_queue_send(evq->q, ev, sizeof(ev));
51 assert(status == TLS_OS_SUCCESS);
52 }
53
npl_freertos_eventq_remove(struct ble_npl_eventq * evq,struct ble_npl_event * ev)54 void npl_freertos_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
55 {
56 tls_os_status_t status;
57
58 if (!ev->queued) {
59 return;
60 }
61
62 status = tls_os_queue_remove(evq->q, ev, sizeof(ev));
63 assert(status == TLS_OS_SUCCESS);
64 ev->queued = 0;
65 }
66
npl_freertos_mutex_init(struct ble_npl_mutex * mu)67 ble_npl_error_t npl_freertos_mutex_init(struct ble_npl_mutex *mu)
68 {
69 tls_os_status_t status;
70
71 if (!mu) {
72 return BLE_NPL_INVALID_PARAM;
73 }
74
75 status = tls_os_mutex_create(0, &mu->handle);
76 assert(status == TLS_OS_SUCCESS);
77 assert(mu->handle);
78 return BLE_NPL_OK;
79 }
80
npl_freertos_mutex_deinit(struct ble_npl_mutex * mu)81 ble_npl_error_t npl_freertos_mutex_deinit(struct ble_npl_mutex *mu)
82 {
83 tls_os_status_t status;
84
85 if (!mu) {
86 return BLE_NPL_INVALID_PARAM;
87 }
88
89 if (mu->handle) {
90 status = tls_os_mutex_delete(mu->handle);
91 assert(status == TLS_OS_SUCCESS);
92 }
93
94 return BLE_NPL_OK;
95 }
96
npl_freertos_mutex_pend(struct ble_npl_mutex * mu,ble_npl_time_t timeout)97 ble_npl_error_t npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
98 {
99 tls_os_status_t status;
100
101 if (!mu) {
102 return BLE_NPL_INVALID_PARAM;
103 }
104
105 assert(mu->handle);
106
107 if (tls_get_isr_count() > 0) {
108 status = TLS_OS_ERROR;
109 assert(0);
110 } else {
111 status = tls_os_mutex_acquire(mu->handle, timeout);
112 }
113
114 return status == TLS_OS_SUCCESS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
115 }
116
npl_freertos_mutex_release(struct ble_npl_mutex * mu)117 ble_npl_error_t npl_freertos_mutex_release(struct ble_npl_mutex *mu)
118 {
119 tls_os_status_t status;
120
121 if (!mu) {
122 return BLE_NPL_INVALID_PARAM;
123 }
124
125 assert(mu->handle);
126
127 if (tls_get_isr_count() > 0) {
128 assert(0);
129 } else {
130 status = tls_os_mutex_release(mu->handle);
131 if (status != TLS_OS_SUCCESS) {
132 return BLE_NPL_BAD_MUTEX;
133 }
134 }
135
136 return BLE_NPL_OK;
137 }
138
npl_freertos_sem_init(struct ble_npl_sem * sem,uint16_t tokens)139 ble_npl_error_t npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
140 {
141 tls_os_status_t status;
142
143 if (!sem) {
144 return BLE_NPL_INVALID_PARAM;
145 }
146
147 status = tls_os_sem_create(&sem->handle, tokens);
148 assert(status == TLS_OS_SUCCESS);
149 assert(sem->handle);
150 return BLE_NPL_OK;
151 }
npl_freertos_sem_deinit(struct ble_npl_sem * sem)152 ble_npl_error_t npl_freertos_sem_deinit(struct ble_npl_sem *sem)
153 {
154 tls_os_status_t status;
155
156 if (!sem) {
157 return BLE_NPL_INVALID_PARAM;
158 }
159
160 if (sem->handle) {
161 status = tls_os_sem_delete(sem->handle);
162 assert(status == TLS_OS_SUCCESS);
163 }
164
165 return BLE_NPL_OK;
166 }
167
npl_freertos_sem_pend(struct ble_npl_sem * sem,ble_npl_time_t timeout)168 ble_npl_error_t npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
169 {
170 tls_os_status_t status;
171
172 if (!sem) {
173 return BLE_NPL_INVALID_PARAM;
174 }
175
176 assert(sem->handle);
177 status = tls_os_sem_acquire(sem->handle, timeout);
178 return status == TLS_OS_SUCCESS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
179 }
npl_freertos_get_sem_count(struct ble_npl_sem * sem)180 uint16_t npl_freertos_get_sem_count(struct ble_npl_sem *sem)
181 {
182 if (!sem) {
183 return BLE_NPL_INVALID_PARAM;
184 }
185
186 assert(sem->handle);
187 return (uint16_t)tls_os_sem_get_count(sem->handle);
188 }
189
npl_freertos_sem_release(struct ble_npl_sem * sem)190 ble_npl_error_t npl_freertos_sem_release(struct ble_npl_sem *sem)
191 {
192 tls_os_status_t status;
193
194 if (!sem) {
195 return BLE_NPL_INVALID_PARAM;
196 }
197
198 assert(sem->handle);
199 status = tls_os_sem_release(sem->handle);
200 assert(status == TLS_OS_SUCCESS);
201 return BLE_NPL_OK;
202 }
os_callout_timer_cb(void * ptmr,void * parg)203 static void os_callout_timer_cb(void *ptmr, void *parg)
204 {
205 struct ble_npl_callout *co;
206 co = (struct ble_npl_callout *)parg;
207 if (co->evq) {
208 ble_npl_eventq_put(co->evq, &co->ev);
209 } else {
210 co->ev.fn(&co->ev);
211 }
212 }
213
npl_freertos_callout_init(struct ble_npl_callout * co,struct ble_npl_eventq * evq,ble_npl_event_fn * ev_cb,void * ev_arg)214 void npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
215 ble_npl_event_fn *ev_cb, void *ev_arg)
216 {
217 tls_os_status_t status;
218 memset_s(co, sizeof(*co), 0, sizeof(*co));
219 status = tls_os_timer_create(&co->handle, os_callout_timer_cb, (void *)co, 1, 0, (u8 *)"co");
220 assert(status == TLS_OS_SUCCESS);
221 co->evq = evq;
222 ble_npl_event_init(&co->ev, ev_cb, ev_arg);
223 }
224
npl_freertos_callout_reset(struct ble_npl_callout * co,ble_npl_time_t ticks)225 ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
226 {
227 tls_os_timer_change(co->handle, ticks);
228 return BLE_NPL_OK;
229 }
230
npl_freertos_callout_remaining_ticks(struct ble_npl_callout * co,ble_npl_time_t now)231 ble_npl_time_t npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co, ble_npl_time_t now)
232 {
233 ble_npl_time_t rt;
234 uint32_t exp;
235 exp = tls_os_timer_expirytime(co->handle);
236 if (exp > now) {
237 rt = exp - now;
238 } else {
239 rt = 0;
240 }
241
242 return rt;
243 }
244
npl_freertos_time_ms_to_ticks(uint32_t ms,ble_npl_time_t * out_ticks)245 ble_npl_error_t npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
246 {
247 uint64_t ticks;
248 ticks = ((uint64_t)ms * HZ) / 1000; // 1000:time unit
249 if (ticks > UINT32_MAX) {
250 return BLE_NPL_EINVAL;
251 }
252
253 *out_ticks = ticks;
254 return 0;
255 }
256
npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks,uint32_t * out_ms)257 ble_npl_error_t npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
258 {
259 uint64_t ms;
260 ms = ((uint64_t)ticks * 1000) / HZ; // 1000:time unit
261 if (ms > UINT32_MAX) {
262 return BLE_NPL_EINVAL;
263 }
264
265 *out_ms = ms;
266 return 0;
267 }