diff options
Diffstat (limited to 'lib/chibios/os/common/abstractions/cmsis_os')
3 files changed, 1088 insertions, 0 deletions
diff --git a/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.c b/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.c new file mode 100644 index 000000000..9bd63da8f --- /dev/null +++ b/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.c | |||
@@ -0,0 +1,558 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | /* | ||
20 | Concepts and parts of this file have been contributed by Andre R. | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * @file cmsis_os.c | ||
25 | * @brief CMSIS RTOS module code. | ||
26 | * | ||
27 | * @addtogroup CMSIS_OS | ||
28 | * @{ | ||
29 | */ | ||
30 | |||
31 | #include "cmsis_os.h" | ||
32 | #include <string.h> | ||
33 | |||
34 | /*===========================================================================*/ | ||
35 | /* Module local definitions. */ | ||
36 | /*===========================================================================*/ | ||
37 | |||
38 | /*===========================================================================*/ | ||
39 | /* Module exported variables. */ | ||
40 | /*===========================================================================*/ | ||
41 | |||
42 | int32_t cmsis_os_started; | ||
43 | |||
44 | /*===========================================================================*/ | ||
45 | /* Module local types. */ | ||
46 | /*===========================================================================*/ | ||
47 | |||
48 | /*===========================================================================*/ | ||
49 | /* Module local variables. */ | ||
50 | /*===========================================================================*/ | ||
51 | |||
52 | static memory_pool_t sempool; | ||
53 | static semaphore_t semaphores[CMSIS_CFG_NUM_SEMAPHORES]; | ||
54 | |||
55 | static memory_pool_t timpool; | ||
56 | static struct os_timer_cb timers[CMSIS_CFG_NUM_TIMERS]; | ||
57 | |||
58 | /*===========================================================================*/ | ||
59 | /* Module local functions. */ | ||
60 | /*===========================================================================*/ | ||
61 | |||
62 | /** | ||
63 | * @brief Virtual timers common callback. | ||
64 | */ | ||
65 | static void timer_cb(void const *arg) { | ||
66 | |||
67 | osTimerId timer_id = (osTimerId)arg; | ||
68 | timer_id->ptimer(timer_id->argument); | ||
69 | if (timer_id->type == osTimerPeriodic) { | ||
70 | chSysLockFromISR(); | ||
71 | chVTDoSetI(&timer_id->vt, TIME_MS2I(timer_id->millisec), | ||
72 | (vtfunc_t)timer_cb, timer_id); | ||
73 | chSysUnlockFromISR(); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | /*===========================================================================*/ | ||
78 | /* Module exported functions. */ | ||
79 | /*===========================================================================*/ | ||
80 | |||
81 | /** | ||
82 | * @brief Kernel initialization. | ||
83 | */ | ||
84 | osStatus osKernelInitialize(void) { | ||
85 | |||
86 | cmsis_os_started = 0; | ||
87 | |||
88 | chSysInit(); | ||
89 | chThdSetPriority(HIGHPRIO); | ||
90 | |||
91 | chPoolObjectInit(&sempool, sizeof(semaphore_t), chCoreAllocAlignedI); | ||
92 | chPoolLoadArray(&sempool, semaphores, CMSIS_CFG_NUM_SEMAPHORES); | ||
93 | |||
94 | chPoolObjectInit(&timpool, sizeof(struct os_timer_cb), chCoreAllocAlignedI); | ||
95 | chPoolLoadArray(&timpool, timers, CMSIS_CFG_NUM_TIMERS); | ||
96 | |||
97 | return osOK; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * @brief Kernel start. | ||
102 | */ | ||
103 | osStatus osKernelStart(void) { | ||
104 | |||
105 | cmsis_os_started = 1; | ||
106 | |||
107 | chThdSetPriority(NORMALPRIO); | ||
108 | |||
109 | return osOK; | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * @brief Creates a thread. | ||
114 | */ | ||
115 | osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument) { | ||
116 | size_t size; | ||
117 | |||
118 | size = thread_def->stacksize == 0 ? CMSIS_CFG_DEFAULT_STACK : | ||
119 | thread_def->stacksize; | ||
120 | return (osThreadId)chThdCreateFromHeap(0, | ||
121 | THD_WORKING_AREA_SIZE(size), | ||
122 | thread_def->name, | ||
123 | NORMALPRIO+thread_def->tpriority, | ||
124 | (tfunc_t)thread_def->pthread, | ||
125 | argument); | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * @brief Thread termination. | ||
130 | * @note The thread is not really terminated but asked to terminate which | ||
131 | * is not compliant. | ||
132 | */ | ||
133 | osStatus osThreadTerminate(osThreadId thread_id) { | ||
134 | |||
135 | if (thread_id == osThreadGetId()) { | ||
136 | /* Note, no memory will be recovered unless a cleaner thread is | ||
137 | implemented using the registry.*/ | ||
138 | chThdExit(0); | ||
139 | } | ||
140 | chThdTerminate(thread_id); | ||
141 | chThdWait((thread_t *)thread_id); | ||
142 | |||
143 | return osOK; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * @brief Change thread priority. | ||
148 | * @note This can interfere with the priority inheritance mechanism. | ||
149 | */ | ||
150 | osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio) { | ||
151 | thread_t * tp = (thread_t *)thread_id; | ||
152 | |||
153 | chSysLock(); | ||
154 | |||
155 | /* Changing priority.*/ | ||
156 | #if CH_CFG_USE_MUTEXES | ||
157 | if ((tp->hdr.pqueue.prio == tp->realprio) || | ||
158 | ((tprio_t)newprio > tp->hdr.pqueue.prio)) | ||
159 | tp->hdr.pqueue.prio = (tprio_t)newprio; | ||
160 | tp->realprio = (tprio_t)newprio; | ||
161 | #else | ||
162 | tp->hdr.pqueue.prio = (tprio_t)newprio; | ||
163 | #endif | ||
164 | |||
165 | /* The following states need priority queues reordering.*/ | ||
166 | switch (tp->state) { | ||
167 | #if CH_CFG_USE_MUTEXES | \ | ||
168 | CH_CFG_USE_CONDVARS | \ | ||
169 | (CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) | \ | ||
170 | (CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY) | ||
171 | #if CH_CFG_USE_MUTEXES | ||
172 | case CH_STATE_WTMTX: | ||
173 | #endif | ||
174 | #if CH_CFG_USE_CONDVARS | ||
175 | case CH_STATE_WTCOND: | ||
176 | #endif | ||
177 | #if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY | ||
178 | case CH_STATE_WTSEM: | ||
179 | #endif | ||
180 | #if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY | ||
181 | case CH_STATE_SNDMSGQ: | ||
182 | #endif | ||
183 | /* Re-enqueues tp with its new priority on the queue.*/ | ||
184 | ch_sch_prio_insert(ch_queue_dequeue(&tp->hdr.queue), | ||
185 | (ch_queue_t *)tp->u.wtobjp); | ||
186 | break; | ||
187 | #endif | ||
188 | case CH_STATE_READY: | ||
189 | #if CH_DBG_ENABLE_ASSERTS | ||
190 | /* Prevents an assertion in chSchReadyI().*/ | ||
191 | tp->state = CH_STATE_CURRENT; | ||
192 | #endif | ||
193 | /* Re-enqueues tp with its new priority on the ready list.*/ | ||
194 | chSchReadyI((thread_t *)ch_queue_dequeue(&tp->hdr.queue)); | ||
195 | break; | ||
196 | } | ||
197 | |||
198 | /* Rescheduling.*/ | ||
199 | chSchRescheduleS(); | ||
200 | |||
201 | chSysUnlock(); | ||
202 | |||
203 | return osOK; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * @brief Create a timer. | ||
208 | */ | ||
209 | osTimerId osTimerCreate(const osTimerDef_t *timer_def, | ||
210 | os_timer_type type, | ||
211 | void *argument) { | ||
212 | |||
213 | osTimerId timer = chPoolAlloc(&timpool); | ||
214 | chVTObjectInit(&timer->vt); | ||
215 | timer->ptimer = timer_def->ptimer; | ||
216 | timer->type = type; | ||
217 | timer->argument = argument; | ||
218 | return timer; | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * @brief Start a timer. | ||
223 | */ | ||
224 | osStatus osTimerStart(osTimerId timer_id, uint32_t millisec) { | ||
225 | |||
226 | if ((millisec == 0) || (millisec == osWaitForever)) | ||
227 | return osErrorValue; | ||
228 | |||
229 | timer_id->millisec = millisec; | ||
230 | chVTSet(&timer_id->vt, TIME_MS2I(millisec), (vtfunc_t)timer_cb, timer_id); | ||
231 | |||
232 | return osOK; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * @brief Stop a timer. | ||
237 | */ | ||
238 | osStatus osTimerStop(osTimerId timer_id) { | ||
239 | |||
240 | chVTReset(&timer_id->vt); | ||
241 | |||
242 | return osOK; | ||
243 | } | ||
244 | |||
245 | /** | ||
246 | * @brief Delete a timer. | ||
247 | */ | ||
248 | osStatus osTimerDelete(osTimerId timer_id) { | ||
249 | |||
250 | chVTReset(&timer_id->vt); | ||
251 | chPoolFree(&timpool, (void *)timer_id); | ||
252 | |||
253 | return osOK; | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * @brief Send signals. | ||
258 | */ | ||
259 | int32_t osSignalSet(osThreadId thread_id, int32_t signals) { | ||
260 | int32_t oldsignals; | ||
261 | |||
262 | syssts_t sts = chSysGetStatusAndLockX(); | ||
263 | oldsignals = (int32_t)thread_id->epending; | ||
264 | chEvtSignalI((thread_t *)thread_id, (eventmask_t)signals); | ||
265 | chSysRestoreStatusX(sts); | ||
266 | |||
267 | return oldsignals; | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * @brief Clear signals. | ||
272 | */ | ||
273 | int32_t osSignalClear(osThreadId thread_id, int32_t signals) { | ||
274 | eventmask_t m; | ||
275 | |||
276 | chSysLock(); | ||
277 | |||
278 | m = thread_id->epending & (eventmask_t)signals; | ||
279 | thread_id->epending &= ~(eventmask_t)signals; | ||
280 | |||
281 | chSysUnlock(); | ||
282 | |||
283 | return (int32_t)m; | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * @brief Wait for signals. | ||
288 | */ | ||
289 | osEvent osSignalWait(int32_t signals, uint32_t millisec) { | ||
290 | osEvent event; | ||
291 | sysinterval_t timeout = (millisec == osWaitForever ? | ||
292 | TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE : | ||
293 | TIME_MS2I(millisec))); | ||
294 | |||
295 | if (signals == 0) | ||
296 | event.value.signals = (uint32_t)chEvtWaitAnyTimeout(ALL_EVENTS, timeout); | ||
297 | else | ||
298 | event.value.signals = (uint32_t)chEvtWaitAllTimeout((eventmask_t)signals, | ||
299 | timeout); | ||
300 | |||
301 | /* Type of event.*/ | ||
302 | if (event.value.signals == 0) | ||
303 | event.status = osEventTimeout; | ||
304 | else | ||
305 | event.status = osEventSignal; | ||
306 | |||
307 | return event; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * @brief Create a semaphore. | ||
312 | * @note @p semaphore_def is not used. | ||
313 | * @note Can involve memory allocation. | ||
314 | */ | ||
315 | osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, | ||
316 | int32_t count) { | ||
317 | |||
318 | (void)semaphore_def; | ||
319 | |||
320 | semaphore_t *sem = chPoolAlloc(&sempool); | ||
321 | chSemObjectInit(sem, (cnt_t)count); | ||
322 | return sem; | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * @brief Wait on a semaphore. | ||
327 | */ | ||
328 | int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec) { | ||
329 | sysinterval_t timeout = (millisec == osWaitForever ? | ||
330 | TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE : | ||
331 | TIME_MS2I(millisec))); | ||
332 | |||
333 | msg_t msg = chSemWaitTimeout((semaphore_t *)semaphore_id, timeout); | ||
334 | switch (msg) { | ||
335 | case MSG_OK: | ||
336 | return osOK; | ||
337 | case MSG_TIMEOUT: | ||
338 | return osErrorTimeoutResource; | ||
339 | } | ||
340 | return osErrorResource; | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * @brief Release a semaphore. | ||
345 | */ | ||
346 | osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) { | ||
347 | |||
348 | syssts_t sts = chSysGetStatusAndLockX(); | ||
349 | chSemSignalI((semaphore_t *)semaphore_id); | ||
350 | chSysRestoreStatusX(sts); | ||
351 | |||
352 | return osOK; | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * @brief Deletes a semaphore. | ||
357 | * @note After deletion there could be references in the system to a | ||
358 | * non-existent semaphore. | ||
359 | */ | ||
360 | osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) { | ||
361 | |||
362 | chSemReset((semaphore_t *)semaphore_id, 0); | ||
363 | chPoolFree(&sempool, (void *)semaphore_id); | ||
364 | |||
365 | return osOK; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * @brief Create a mutex. | ||
370 | * @note @p mutex_def is not used. | ||
371 | * @note Can involve memory allocation. | ||
372 | */ | ||
373 | osMutexId osMutexCreate(const osMutexDef_t *mutex_def) { | ||
374 | |||
375 | (void)mutex_def; | ||
376 | |||
377 | binary_semaphore_t *mtx = chPoolAlloc(&sempool); | ||
378 | chBSemObjectInit(mtx, false); | ||
379 | return mtx; | ||
380 | } | ||
381 | |||
382 | /** | ||
383 | * @brief Wait on a mutex. | ||
384 | */ | ||
385 | osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec) { | ||
386 | sysinterval_t timeout = (millisec == osWaitForever ? | ||
387 | TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE : | ||
388 | TIME_MS2I(millisec))); | ||
389 | |||
390 | msg_t msg = chBSemWaitTimeout((binary_semaphore_t *)mutex_id, timeout); | ||
391 | switch (msg) { | ||
392 | case MSG_OK: | ||
393 | return osOK; | ||
394 | case MSG_TIMEOUT: | ||
395 | return osErrorTimeoutResource; | ||
396 | } | ||
397 | return osErrorResource; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * @brief Release a mutex. | ||
402 | */ | ||
403 | osStatus osMutexRelease(osMutexId mutex_id) { | ||
404 | |||
405 | syssts_t sts = chSysGetStatusAndLockX(); | ||
406 | chBSemSignalI((binary_semaphore_t *)mutex_id); | ||
407 | chSysRestoreStatusX(sts); | ||
408 | |||
409 | return osOK; | ||
410 | } | ||
411 | |||
412 | /** | ||
413 | * @brief Deletes a mutex. | ||
414 | * @note After deletion there could be references in the system to a | ||
415 | * non-existent semaphore. | ||
416 | */ | ||
417 | osStatus osMutexDelete(osMutexId mutex_id) { | ||
418 | |||
419 | chSemReset((semaphore_t *)mutex_id, 0); | ||
420 | chPoolFree(&sempool, (void *)mutex_id); | ||
421 | |||
422 | return osOK; | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * @brief Create a memory pool. | ||
427 | * @note The pool is not really created because it is allocated statically, | ||
428 | * this function just re-initializes it. | ||
429 | */ | ||
430 | osPoolId osPoolCreate(const osPoolDef_t *pool_def) { | ||
431 | |||
432 | chPoolObjectInit(pool_def->pool, (size_t)pool_def->item_sz, NULL); | ||
433 | chPoolLoadArray(pool_def->pool, pool_def->items, (size_t)pool_def->pool_sz); | ||
434 | |||
435 | return (osPoolId)pool_def->pool; | ||
436 | } | ||
437 | |||
438 | /** | ||
439 | * @brief Allocate an object. | ||
440 | */ | ||
441 | void *osPoolAlloc(osPoolId pool_id) { | ||
442 | void *object; | ||
443 | |||
444 | syssts_t sts = chSysGetStatusAndLockX(); | ||
445 | object = chPoolAllocI((memory_pool_t *)pool_id); | ||
446 | chSysRestoreStatusX(sts); | ||
447 | |||
448 | return object; | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * @brief Allocate an object clearing it. | ||
453 | */ | ||
454 | void *osPoolCAlloc(osPoolId pool_id) { | ||
455 | void *object; | ||
456 | |||
457 | object = chPoolAllocI((memory_pool_t *)pool_id); | ||
458 | memset(object, 0, pool_id->object_size); | ||
459 | return object; | ||
460 | } | ||
461 | |||
462 | /** | ||
463 | * @brief Free an object. | ||
464 | */ | ||
465 | osStatus osPoolFree(osPoolId pool_id, void *block) { | ||
466 | |||
467 | syssts_t sts = chSysGetStatusAndLockX(); | ||
468 | chPoolFreeI((memory_pool_t *)pool_id, block); | ||
469 | chSysRestoreStatusX(sts); | ||
470 | |||
471 | return osOK; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * @brief Create a message queue. | ||
476 | * @note The queue is not really created because it is allocated statically, | ||
477 | * this function just re-initializes it. | ||
478 | */ | ||
479 | osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, | ||
480 | osThreadId thread_id) { | ||
481 | |||
482 | /* Ignoring this parameter for now.*/ | ||
483 | (void)thread_id; | ||
484 | |||
485 | if (queue_def->item_sz > sizeof (msg_t)) | ||
486 | return NULL; | ||
487 | |||
488 | chMBObjectInit(queue_def->mailbox, | ||
489 | queue_def->items, | ||
490 | (size_t)queue_def->queue_sz); | ||
491 | |||
492 | return (osMessageQId) queue_def->mailbox; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * @brief Put a message in the queue. | ||
497 | */ | ||
498 | osStatus osMessagePut(osMessageQId queue_id, | ||
499 | uint32_t info, | ||
500 | uint32_t millisec) { | ||
501 | msg_t msg; | ||
502 | sysinterval_t timeout = (millisec == osWaitForever ? | ||
503 | TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE : | ||
504 | TIME_MS2I(millisec))); | ||
505 | |||
506 | if (port_is_isr_context()) { | ||
507 | |||
508 | /* Waiting makes no sense in ISRs so any value except "immediate" | ||
509 | makes no sense.*/ | ||
510 | if (millisec != 0) | ||
511 | return osErrorValue; | ||
512 | |||
513 | chSysLockFromISR(); | ||
514 | msg = chMBPostI((mailbox_t *)queue_id, (msg_t)info); | ||
515 | chSysUnlockFromISR(); | ||
516 | } | ||
517 | else | ||
518 | msg = chMBPostTimeout((mailbox_t *)queue_id, (msg_t)info, timeout); | ||
519 | |||
520 | return msg == MSG_OK ? osOK : osEventTimeout; | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * @brief Get a message from the queue. | ||
525 | */ | ||
526 | osEvent osMessageGet(osMessageQId queue_id, | ||
527 | uint32_t millisec) { | ||
528 | msg_t msg; | ||
529 | osEvent event; | ||
530 | sysinterval_t timeout = (millisec == osWaitForever ? | ||
531 | TIME_INFINITE : (millisec == 0 ? TIME_IMMEDIATE : | ||
532 | TIME_MS2I(millisec))); | ||
533 | |||
534 | event.def.message_id = queue_id; | ||
535 | |||
536 | if (port_is_isr_context()) { | ||
537 | |||
538 | /* Waiting makes no sense in ISRs so any value except "immediate" | ||
539 | makes no sense.*/ | ||
540 | if (millisec != 0) { | ||
541 | event.status = osErrorValue; | ||
542 | return event; | ||
543 | } | ||
544 | |||
545 | chSysLockFromISR(); | ||
546 | msg = chMBFetchI((mailbox_t *)queue_id, (msg_t*)&event.value.v); | ||
547 | chSysUnlockFromISR(); | ||
548 | } | ||
549 | else { | ||
550 | msg = chMBFetchTimeout((mailbox_t *)queue_id, (msg_t*)&event.value.v, timeout); | ||
551 | } | ||
552 | |||
553 | /* Returned event type.*/ | ||
554 | event.status = msg == MSG_OK ? osEventMessage : osEventTimeout; | ||
555 | return event; | ||
556 | } | ||
557 | |||
558 | /** @} */ | ||
diff --git a/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.h b/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.h new file mode 100644 index 000000000..dafe3e398 --- /dev/null +++ b/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.h | |||
@@ -0,0 +1,522 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | ||
3 | 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | ||
4 | |||
5 | This file is part of ChibiOS. | ||
6 | |||
7 | ChibiOS is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation version 3 of the License. | ||
10 | |||
11 | ChibiOS is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | /* | ||
20 | Concepts and parts of this file have been contributed by Andre R. | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * @file cmsis_os.h | ||
25 | * @brief CMSIS RTOS module macros and structures. | ||
26 | * | ||
27 | * @addtogroup CMSIS_OS | ||
28 | * @{ | ||
29 | */ | ||
30 | |||
31 | #ifndef CMSIS_OS_H | ||
32 | #define CMSIS_OS_H | ||
33 | |||
34 | #include "ch.h" | ||
35 | |||
36 | /*===========================================================================*/ | ||
37 | /* Module constants. */ | ||
38 | /*===========================================================================*/ | ||
39 | |||
40 | /** | ||
41 | * @brief API version. | ||
42 | */ | ||
43 | #define osCMSIS 0x10002 | ||
44 | |||
45 | /** | ||
46 | * @brief Kernel version. | ||
47 | */ | ||
48 | #define osKernelSystemId "KERNEL V1.00" | ||
49 | |||
50 | /** | ||
51 | * @brief ChibiOS/RT version encoded for CMSIS. | ||
52 | */ | ||
53 | #define osCMSIS_KERNEL ((CH_KERNEL_MAJOR << 16) | \ | ||
54 | (CH_KERNEL_MINOR << 8) | \ | ||
55 | (CH_KERNEL_PATCH)) | ||
56 | |||
57 | /** | ||
58 | * @name CMSIS Capabilities | ||
59 | * @{ | ||
60 | */ | ||
61 | #define osFeature_MainThread 1 | ||
62 | #define osFeature_Pool 1 | ||
63 | #define osFeature_MailQ 0 | ||
64 | #define osFeature_MessageQ 1 | ||
65 | #define osFeature_Signals 24 | ||
66 | #define osFeature_Semaphore ((1U << 31) - 1U) | ||
67 | #define osFeature_Wait 0 | ||
68 | #define osFeature_SysTick 1 | ||
69 | /**< @} */ | ||
70 | |||
71 | /** | ||
72 | * @brief Wait forever specification for timeouts. | ||
73 | */ | ||
74 | #define osWaitForever ((uint32_t)-1) | ||
75 | |||
76 | /** | ||
77 | * @brief System tick frequency. | ||
78 | */ | ||
79 | #define osKernelSysTickFrequency CH_CFG_ST_FREQUENCY | ||
80 | |||
81 | /*===========================================================================*/ | ||
82 | /* Module pre-compile time settings. */ | ||
83 | /*===========================================================================*/ | ||
84 | |||
85 | /** | ||
86 | * @brief Number of pre-allocated static semaphores/mutexes. | ||
87 | */ | ||
88 | #if !defined(CMSIS_CFG_DEFAULT_STACK) | ||
89 | #define CMSIS_CFG_DEFAULT_STACK 256 | ||
90 | #endif | ||
91 | |||
92 | /** | ||
93 | * @brief Number of pre-allocated static semaphores/mutexes. | ||
94 | */ | ||
95 | #if !defined(CMSIS_CFG_NUM_SEMAPHORES) | ||
96 | #define CMSIS_CFG_NUM_SEMAPHORES 4 | ||
97 | #endif | ||
98 | |||
99 | /** | ||
100 | * @brief Number of pre-allocated static timers. | ||
101 | */ | ||
102 | #if !defined(CMSIS_CFG_NUM_TIMERS) | ||
103 | #define CMSIS_CFG_NUM_TIMERS 4 | ||
104 | #endif | ||
105 | |||
106 | /*===========================================================================*/ | ||
107 | /* Derived constants and error checks. */ | ||
108 | /*===========================================================================*/ | ||
109 | |||
110 | #if !CH_CFG_USE_MEMPOOLS | ||
111 | #error "CMSIS RTOS requires CH_CFG_USE_MEMPOOLS" | ||
112 | #endif | ||
113 | |||
114 | #if !CH_CFG_USE_EVENTS | ||
115 | #error "CMSIS RTOS requires CH_CFG_USE_EVENTS" | ||
116 | #endif | ||
117 | |||
118 | #if !CH_CFG_USE_EVENTS_TIMEOUT | ||
119 | #error "CMSIS RTOS requires CH_CFG_USE_EVENTS_TIMEOUT" | ||
120 | #endif | ||
121 | |||
122 | #if !CH_CFG_USE_SEMAPHORES | ||
123 | #error "CMSIS RTOS requires CH_CFG_USE_SEMAPHORES" | ||
124 | #endif | ||
125 | |||
126 | #if !CH_CFG_USE_DYNAMIC | ||
127 | #error "CMSIS RTOS requires CH_CFG_USE_DYNAMIC" | ||
128 | #endif | ||
129 | |||
130 | /*===========================================================================*/ | ||
131 | /* Module data structures and types. */ | ||
132 | /*===========================================================================*/ | ||
133 | |||
134 | /** | ||
135 | * @brief Type of priority levels. | ||
136 | */ | ||
137 | typedef enum { | ||
138 | osPriorityIdle = -3, | ||
139 | osPriorityLow = -2, | ||
140 | osPriorityBelowNormal = -1, | ||
141 | osPriorityNormal = 0, | ||
142 | osPriorityAboveNormal = +1, | ||
143 | osPriorityHigh = +2, | ||
144 | osPriorityRealtime = +3, | ||
145 | osPriorityError = 0x84 | ||
146 | } osPriority; | ||
147 | |||
148 | /** | ||
149 | * @brief Type of error codes. | ||
150 | */ | ||
151 | typedef enum { | ||
152 | osOK = 0, | ||
153 | osEventSignal = 0x08, | ||
154 | osEventMessage = 0x10, | ||
155 | osEventMail = 0x20, | ||
156 | osEventTimeout = 0x40, | ||
157 | osErrorParameter = 0x80, | ||
158 | osErrorResource = 0x81, | ||
159 | osErrorTimeoutResource = 0xC1, | ||
160 | osErrorISR = 0x82, | ||
161 | osErrorISRRecursive = 0x83, | ||
162 | osErrorPriority = 0x84, | ||
163 | osErrorNoMemory = 0x85, | ||
164 | osErrorValue = 0x86, | ||
165 | osErrorOS = 0xFF, | ||
166 | os_status_reserved = 0x7FFFFFFF | ||
167 | } osStatus; | ||
168 | |||
169 | /** | ||
170 | * @brief Type of a timer mode. | ||
171 | */ | ||
172 | typedef enum { | ||
173 | osTimerOnce = 0, | ||
174 | osTimerPeriodic = 1 | ||
175 | } os_timer_type; | ||
176 | |||
177 | /** | ||
178 | * @brief Type of thread functions. | ||
179 | */ | ||
180 | typedef void (*os_pthread) (void const *argument); | ||
181 | |||
182 | /** | ||
183 | * @brief Type of timer callback. | ||
184 | */ | ||
185 | typedef void (*os_ptimer) (void const *argument); | ||
186 | |||
187 | /** | ||
188 | * @brief Type of pointer to thread control block. | ||
189 | */ | ||
190 | typedef thread_t *osThreadId; | ||
191 | |||
192 | /** | ||
193 | * @brief Type of pointer to timer control block. | ||
194 | */ | ||
195 | typedef struct os_timer_cb { | ||
196 | virtual_timer_t vt; | ||
197 | os_timer_type type; | ||
198 | os_ptimer ptimer; | ||
199 | void *argument; | ||
200 | uint32_t millisec; | ||
201 | } *osTimerId; | ||
202 | |||
203 | /** | ||
204 | * @brief Type of pointer to mutex control block. | ||
205 | */ | ||
206 | typedef binary_semaphore_t *osMutexId; | ||
207 | |||
208 | /** | ||
209 | * @brief Type of pointer to semaphore control block. | ||
210 | */ | ||
211 | typedef semaphore_t *osSemaphoreId; | ||
212 | |||
213 | /** | ||
214 | * @brief Type of pointer to memory pool control block. | ||
215 | */ | ||
216 | typedef memory_pool_t *osPoolId; | ||
217 | |||
218 | /** | ||
219 | * @brief Type of pointer to message queue control block. | ||
220 | */ | ||
221 | typedef struct mailbox *osMessageQId; | ||
222 | |||
223 | /** | ||
224 | * @brief Type of an event. | ||
225 | */ | ||
226 | typedef struct { | ||
227 | osStatus status; | ||
228 | union { | ||
229 | uint32_t v; | ||
230 | void *p; | ||
231 | int32_t signals; | ||
232 | } value; | ||
233 | union { | ||
234 | /* osMailQId mail_id;*/ | ||
235 | osMessageQId message_id; | ||
236 | } def; | ||
237 | } osEvent; | ||
238 | |||
239 | /** | ||
240 | * @brief Type of a thread definition block. | ||
241 | */ | ||
242 | typedef struct os_thread_def { | ||
243 | os_pthread pthread; | ||
244 | osPriority tpriority; | ||
245 | uint32_t stacksize; | ||
246 | const char *name; | ||
247 | } osThreadDef_t; | ||
248 | |||
249 | /** | ||
250 | * @brief Type of a timer definition block. | ||
251 | */ | ||
252 | typedef struct os_timer_def { | ||
253 | os_ptimer ptimer; | ||
254 | } osTimerDef_t; | ||
255 | |||
256 | /** | ||
257 | * @brief Type of a mutex definition block. | ||
258 | */ | ||
259 | typedef struct os_mutex_def { | ||
260 | uint32_t dummy; | ||
261 | } osMutexDef_t; | ||
262 | |||
263 | /** | ||
264 | * @brief Type of a semaphore definition block. | ||
265 | */ | ||
266 | typedef struct os_semaphore_def { | ||
267 | uint32_t dummy; | ||
268 | } osSemaphoreDef_t; | ||
269 | |||
270 | /** | ||
271 | * @brief Type of a memory pool definition block. | ||
272 | */ | ||
273 | typedef struct os_pool_def { | ||
274 | uint32_t pool_sz; | ||
275 | uint32_t item_sz; | ||
276 | memory_pool_t *pool; | ||
277 | void *items; | ||
278 | } osPoolDef_t; | ||
279 | |||
280 | /** | ||
281 | * @brief Type of a message queue definition block. | ||
282 | */ | ||
283 | typedef struct os_messageQ_def { | ||
284 | uint32_t queue_sz; | ||
285 | uint32_t item_sz; | ||
286 | mailbox_t *mailbox; | ||
287 | void *items; | ||
288 | } osMessageQDef_t; | ||
289 | |||
290 | /*===========================================================================*/ | ||
291 | /* Module macros. */ | ||
292 | /*===========================================================================*/ | ||
293 | |||
294 | /** | ||
295 | * @brief Convert a microseconds value to a RTOS kernel system timer value. | ||
296 | */ | ||
297 | #define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * \ | ||
298 | (osKernelSysTickFrequency)) / \ | ||
299 | 1000000) | ||
300 | |||
301 | /** | ||
302 | * @brief Create a Thread definition. | ||
303 | */ | ||
304 | #if defined(osObjectsExternal) | ||
305 | #define osThreadDef(thd, priority, stacksz, name) \ | ||
306 | extern const osThreadDef_t os_thread_def_##thd | ||
307 | #else | ||
308 | #define osThreadDef(thd, priority, stacksz, name) \ | ||
309 | const osThreadDef_t os_thread_def_##thd = { \ | ||
310 | (thd), \ | ||
311 | (priority), \ | ||
312 | (stacksz), \ | ||
313 | (name) \ | ||
314 | } | ||
315 | #endif | ||
316 | |||
317 | /** | ||
318 | * @brief Access a Thread definition. | ||
319 | */ | ||
320 | #define osThread(name) &os_thread_def_##name | ||
321 | |||
322 | /** | ||
323 | * @brief Define a Timer object. | ||
324 | */ | ||
325 | #if defined(osObjectsExternal) | ||
326 | #define osTimerDef(name, function) \ | ||
327 | extern const osTimerDef_t os_timer_def_##name | ||
328 | #else | ||
329 | #define osTimerDef(name, function) \ | ||
330 | const osTimerDef_t os_timer_def_##name = { \ | ||
331 | (function) \ | ||
332 | } | ||
333 | #endif | ||
334 | |||
335 | /** | ||
336 | * @brief Access a Timer definition. | ||
337 | */ | ||
338 | #define osTimer(name) &os_timer_def_##name | ||
339 | |||
340 | /** | ||
341 | * @brief Define a Mutex. | ||
342 | */ | ||
343 | #if defined(osObjectsExternal) | ||
344 | #define osMutexDef(name) extern const osMutexDef_t os_mutex_def_##name | ||
345 | #else | ||
346 | #define osMutexDef(name) const osMutexDef_t os_mutex_def_##name = {0} | ||
347 | #endif | ||
348 | |||
349 | /** | ||
350 | * @brief Access a Mutex definition. | ||
351 | */ | ||
352 | #define osMutex(name) &os_mutex_def_##name | ||
353 | |||
354 | /** | ||
355 | * @brief Define a Semaphore. | ||
356 | */ | ||
357 | #if defined(osObjectsExternal) | ||
358 | #define osSemaphoreDef(name) \ | ||
359 | extern const osSemaphoreDef_t os_semaphore_def_##name | ||
360 | #else // define the object | ||
361 | #define osSemaphoreDef(name) \ | ||
362 | const osSemaphoreDef_t os_semaphore_def_##name = {0} | ||
363 | #endif | ||
364 | |||
365 | /** | ||
366 | * @brief Access a Semaphore definition. | ||
367 | */ | ||
368 | #define osSemaphore(name) &os_semaphore_def_##name | ||
369 | |||
370 | /** | ||
371 | * @brief Define a Memory Pool. | ||
372 | */ | ||
373 | #if defined(osObjectsExternal) | ||
374 | #define osPoolDef(name, no, type) \ | ||
375 | extern const osPoolDef_t os_pool_def_##name | ||
376 | #else | ||
377 | #define osPoolDef(name, no, type) \ | ||
378 | static const type os_pool_buf_##name[no]; \ | ||
379 | static memory_pool_t os_pool_obj_##name; \ | ||
380 | const osPoolDef_t os_pool_def_##name = { \ | ||
381 | (no), \ | ||
382 | sizeof (type), \ | ||
383 | (void *)&os_pool_obj_##name, \ | ||
384 | (void *)&os_pool_buf_##name[0] \ | ||
385 | } | ||
386 | #endif | ||
387 | |||
388 | /** | ||
389 | * @brief Access a Memory Pool definition. | ||
390 | */ | ||
391 | #define osPool(name) &os_pool_def_##name | ||
392 | |||
393 | /** | ||
394 | * @brief Define a Message Queue. | ||
395 | */ | ||
396 | #if defined(osObjectsExternal) | ||
397 | #define osMessageQDef(name, queue_sz, type) \ | ||
398 | extern const osMessageQDef_t os_messageQ_def_##name | ||
399 | #else | ||
400 | #define osMessageQDef(name, queue_sz, type) \ | ||
401 | static const msg_t os_messageQ_buf_##name[queue_sz]; \ | ||
402 | static mailbox_t os_messageQ_obj_##name; \ | ||
403 | const osMessageQDef_t os_messageQ_def_##name = { \ | ||
404 | (queue_sz), \ | ||
405 | sizeof (type), \ | ||
406 | (void *)&os_messageQ_obj_##name, \ | ||
407 | (void *)&os_messageQ_buf_##name[0] \ | ||
408 | } | ||
409 | #endif | ||
410 | |||
411 | /** | ||
412 | * @brief Access a Message Queue definition. | ||
413 | */ | ||
414 | #define osMessageQ(name) &os_messageQ_def_##name | ||
415 | |||
416 | /*===========================================================================*/ | ||
417 | /* External declarations. */ | ||
418 | /*===========================================================================*/ | ||
419 | |||
420 | extern int32_t cmsis_os_started; | ||
421 | |||
422 | #ifdef __cplusplus | ||
423 | extern "C" { | ||
424 | #endif | ||
425 | osStatus osKernelInitialize(void); | ||
426 | osStatus osKernelStart(void); | ||
427 | osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument); | ||
428 | osStatus osThreadTerminate(osThreadId thread_id); | ||
429 | osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio); | ||
430 | /*osEvent osWait(uint32_t millisec);*/ | ||
431 | osTimerId osTimerCreate(const osTimerDef_t *timer_def, | ||
432 | os_timer_type type, | ||
433 | void *argument); | ||
434 | osStatus osTimerStart(osTimerId timer_id, uint32_t millisec); | ||
435 | osStatus osTimerStop(osTimerId timer_id); | ||
436 | osStatus osTimerDelete(osTimerId timer_id); | ||
437 | int32_t osSignalSet(osThreadId thread_id, int32_t signals); | ||
438 | int32_t osSignalClear(osThreadId thread_id, int32_t signals); | ||
439 | osEvent osSignalWait(int32_t signals, uint32_t millisec); | ||
440 | osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, | ||
441 | int32_t count); | ||
442 | int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec); | ||
443 | osStatus osSemaphoreRelease(osSemaphoreId semaphore_id); | ||
444 | osStatus osSemaphoreDelete(osSemaphoreId semaphore_id); | ||
445 | osMutexId osMutexCreate(const osMutexDef_t *mutex_def); | ||
446 | osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec); | ||
447 | osStatus osMutexRelease(osMutexId mutex_id); | ||
448 | osStatus osMutexDelete(osMutexId mutex_id); | ||
449 | osPoolId osPoolCreate(const osPoolDef_t *pool_def); | ||
450 | void *osPoolAlloc(osPoolId pool_id); | ||
451 | void *osPoolCAlloc(osPoolId pool_id); | ||
452 | osStatus osPoolFree(osPoolId pool_id, void *block); | ||
453 | osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, | ||
454 | osThreadId thread_id); | ||
455 | osStatus osMessagePut(osMessageQId queue_id, | ||
456 | uint32_t info, | ||
457 | uint32_t millisec); | ||
458 | osEvent osMessageGet(osMessageQId queue_id, | ||
459 | uint32_t millisec); | ||
460 | #ifdef __cplusplus | ||
461 | } | ||
462 | #endif | ||
463 | |||
464 | /*===========================================================================*/ | ||
465 | /* Module inline functions. */ | ||
466 | /*===========================================================================*/ | ||
467 | |||
468 | /** | ||
469 | * @brief To be or not to be. | ||
470 | */ | ||
471 | static inline int32_t osKernelRunning(void) { | ||
472 | |||
473 | return cmsis_os_started; | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * @brief System ticks since start. | ||
478 | */ | ||
479 | static inline uint32_t osKernelSysTick(void) { | ||
480 | |||
481 | return (uint32_t)chVTGetSystemTimeX(); | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * @brief Returns the current thread. | ||
486 | */ | ||
487 | static inline osThreadId osThreadGetId(void) { | ||
488 | |||
489 | return (osThreadId)chThdGetSelfX(); | ||
490 | } | ||
491 | |||
492 | /** | ||
493 | * @brief Thread time slice yield. | ||
494 | */ | ||
495 | static inline osStatus osThreadYield(void) { | ||
496 | |||
497 | chThdYield(); | ||
498 | |||
499 | return osOK; | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * @brief Returns priority of a thread. | ||
504 | */ | ||
505 | static inline osPriority osThreadGetPriority(osThreadId thread_id) { | ||
506 | |||
507 | return (osPriority)(NORMALPRIO - thread_id->hdr.pqueue.prio); | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * @brief Thread delay in milliseconds. | ||
512 | */ | ||
513 | static inline osStatus osDelay(uint32_t millisec) { | ||
514 | |||
515 | chThdSleepMilliseconds(millisec); | ||
516 | |||
517 | return osOK; | ||
518 | } | ||
519 | |||
520 | #endif /* CMSIS_OS_H */ | ||
521 | |||
522 | /** @} */ | ||
diff --git a/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.mk b/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.mk new file mode 100644 index 000000000..343f6df40 --- /dev/null +++ b/lib/chibios/os/common/abstractions/cmsis_os/cmsis_os.mk | |||
@@ -0,0 +1,8 @@ | |||
1 | # List of the ChibiOS/RT CMSIS RTOS wrapper. | ||
2 | CMSISRTOSSRC = ${CHIBIOS}/os/common/abstractions/cmsis_os/cmsis_os.c | ||
3 | |||
4 | CMSISRTOSINC = ${CHIBIOS}/os/common/abstractions/cmsis_os | ||
5 | |||
6 | # Shared variables | ||
7 | ALLCSRC += $(CMSISRTOSSRC) | ||
8 | ALLINC += $(CMSISRTOSINC) | ||