]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / rtos / rtx / TARGET_CORTEX_A / rt_CMSIS.c
1 /*----------------------------------------------------------------------------
2 * RL-ARM - RTX
3 *----------------------------------------------------------------------------
4 * Name: rt_CMSIS.c
5 * Purpose: CMSIS RTOS API
6 * Rev.: V4.60
7 *----------------------------------------------------------------------------
8 *
9 * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
10 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * - Neither the name of ARM nor the names of its contributors may be used
19 * to endorse or promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *---------------------------------------------------------------------------*/
34
35 #define __CMSIS_GENERIC
36
37 #if defined (__CORTEX_M4) || defined (__CORTEX_M4F)
38 #include "core_cm4.h"
39 #elif defined (__CORTEX_M3)
40 #include "core_cm3.h"
41 #elif defined (__CORTEX_M0)
42 #include "core_cm0.h"
43 #elif defined (__CORTEX_A9)
44 #include "core_ca9.h"
45 #else
46 #error "Missing __CORTEX_xx definition"
47 #endif
48
49 #include "rt_TypeDef.h"
50 #include "RTX_Config.h"
51 #include "rt_System.h"
52 #include "rt_Task.h"
53 #include "rt_Event.h"
54 #include "rt_List.h"
55 #include "rt_Time.h"
56 #include "rt_Mutex.h"
57 #include "rt_Semaphore.h"
58 #include "rt_Mailbox.h"
59 #include "rt_MemBox.h"
60 #include "rt_Memory.h"
61 #include "rt_HAL_CM.h"
62
63 #define os_thread_cb OS_TCB
64
65 #include "cmsis_os.h"
66
67 #if (osFeature_Signals != 16)
68 #error Invalid "osFeature_Signals" value!
69 #endif
70 #if (osFeature_Semaphore > 65535)
71 #error Invalid "osFeature_Semaphore" value!
72 #endif
73 #if (osFeature_Wait != 0)
74 #error osWait not supported!
75 #endif
76
77
78 // ==== Enumeration, structures, defines ====
79
80 // Service Calls defines
81
82 #if defined (__CC_ARM) /* ARM Compiler */
83
84 #define __NO_RETURN __declspec(noreturn)
85
86 #define osEvent_type osEvent
87 #define osEvent_ret_status ret
88 #define osEvent_ret_value ret
89 #define osEvent_ret_msg ret
90 #define osEvent_ret_mail ret
91
92 #define osCallback_type osCallback
93 #define osCallback_ret ret
94
95 #define SVC_0_1(f,t,...) \
96 __svc_indirect(0) t _##f (t(*)()); \
97 t f (void); \
98 __attribute__((always_inline)) \
99 static __inline t __##f (void) { \
100 return _##f(f); \
101 }
102
103 #define SVC_1_1(f,t,t1,...) \
104 __svc_indirect(0) t _##f (t(*)(t1),t1); \
105 t f (t1 a1); \
106 __attribute__((always_inline)) \
107 static __inline t __##f (t1 a1) { \
108 return _##f(f,a1); \
109 }
110
111 #define SVC_2_1(f,t,t1,t2,...) \
112 __svc_indirect(0) t _##f (t(*)(t1,t2),t1,t2); \
113 t f (t1 a1, t2 a2); \
114 __attribute__((always_inline)) \
115 static __inline t __##f (t1 a1, t2 a2) { \
116 return _##f(f,a1,a2); \
117 }
118
119 #define SVC_3_1(f,t,t1,t2,t3,...) \
120 __svc_indirect(0) t _##f (t(*)(t1,t2,t3),t1,t2,t3); \
121 t f (t1 a1, t2 a2, t3 a3); \
122 __attribute__((always_inline)) \
123 static __inline t __##f (t1 a1, t2 a2, t3 a3) { \
124 return _##f(f,a1,a2,a3); \
125 }
126
127 #define SVC_4_1(f,t,t1,t2,t3,t4,...) \
128 __svc_indirect(0) t _##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4); \
129 t f (t1 a1, t2 a2, t3 a3, t4 a4); \
130 __attribute__((always_inline)) \
131 static __inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
132 return _##f(f,a1,a2,a3,a4); \
133 }
134
135 #define SVC_1_2 SVC_1_1
136 #define SVC_1_3 SVC_1_1
137 #define SVC_2_3 SVC_2_1
138
139 #elif defined (__GNUC__) /* GNU Compiler */
140
141 #define __NO_RETURN __attribute__((noreturn))
142
143 typedef uint32_t __attribute__((vector_size(8))) ret64;
144 typedef uint32_t __attribute__((vector_size(16))) ret128;
145
146 #define RET_pointer __r0
147 #define RET_int32_t __r0
148 #define RET_uint32_t __r0
149 #define RET_osStatus __r0
150 #define RET_osPriority __r0
151 #define RET_osEvent {(osStatus)__r0, {(uint32_t)__r1}, {(void *)__r2}}
152 #define RET_osCallback {(void *)__r0, (void *)__r1}
153
154 #if defined (__ARM_PCS_VFP)
155
156 #define osEvent_type void
157 #define osEvent_ret_status { __asm ("MOV r0, %0;" \
158 : /* no outputs */ \
159 : "r"(ret.status) \
160 : "r0" \
161 ); \
162 }
163 #define osEvent_ret_value { __asm ("MOV r1, %0;" \
164 "MOV r0, %1;" \
165 : /* no outputs */ \
166 : "r"(ret.value.v), \
167 "r"(ret.status) \
168 : "r0", "r1" \
169 ); \
170 }
171 #define osEvent_ret_msg { __asm ("MOV r2, %0;" \
172 "MOV r1, %1;" \
173 "MOV r0, %2;" \
174 : /* no outputs */ \
175 : "r"(ret.def.message_id), \
176 "r"(ret.value.v), \
177 "r"(ret.status) \
178 : "r0", "r1" , "r2" \
179 ); \
180 }
181
182 #define osEvent_ret_mail { __asm ("MOV r2, %0;" \
183 "MOV r1, %1;" \
184 "MOV r0, %2;" \
185 : /* no outputs */ \
186 : "r"(ret.def.mail_id), \
187 "r"(ret.value.v), \
188 "r"(ret.status) \
189 : "r0", "r1" , "r2" \
190 ); \
191 }
192
193 #define osCallback_type void
194 #define osCallback_ret { __asm ("MOV r1, %0;" \
195 "MOV r0, %1;" \
196 : /* no outputs */ \
197 : "r"(ret.arg), \
198 "r"(ret.fp) \
199 : "r0", "r1" \
200 ); \
201 }
202
203 #else /* defined (__ARM_PCS_VFP) */
204
205 #define osEvent_type ret128
206 #define osEvent_ret_status (ret128){ret.status}
207 #define osEvent_ret_value (ret128){ret.status, ret.value.v}
208 #define osEvent_ret_msg (ret128){ret.status, ret.value.v, (uint32_t)ret.def.message_id}
209 #define osEvent_ret_mail (ret128){ret.status, ret.value.v, (uint32_t)ret.def.mail_id}
210
211 #define osCallback_type ret64
212 #define osCallback_ret (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg}
213
214 #endif /* defined (__ARM_PCS_VFP) */
215
216 #define SVC_ArgN(n) \
217 register int __r##n __asm("r"#n);
218
219 #define SVC_ArgR(n,t,a) \
220 register t __r##n __asm("r"#n) = a;
221
222 #define SVC_Arg0() \
223 SVC_ArgN(0) \
224 SVC_ArgN(1) \
225 SVC_ArgN(2) \
226 SVC_ArgN(3)
227
228 #define SVC_Arg1(t1) \
229 SVC_ArgR(0,t1,a1) \
230 SVC_ArgN(1) \
231 SVC_ArgN(2) \
232 SVC_ArgN(3)
233
234 #define SVC_Arg2(t1,t2) \
235 SVC_ArgR(0,t1,a1) \
236 SVC_ArgR(1,t2,a2) \
237 SVC_ArgN(2) \
238 SVC_ArgN(3)
239
240 #define SVC_Arg3(t1,t2,t3) \
241 SVC_ArgR(0,t1,a1) \
242 SVC_ArgR(1,t2,a2) \
243 SVC_ArgR(2,t3,a3) \
244 SVC_ArgN(3)
245
246 #define SVC_Arg4(t1,t2,t3,t4) \
247 SVC_ArgR(0,t1,a1) \
248 SVC_ArgR(1,t2,a2) \
249 SVC_ArgR(2,t3,a3) \
250 SVC_ArgR(3,t4,a4)
251
252 #if (defined (__CORTEX_M0))
253 #define SVC_Call(f) \
254 __asm volatile \
255 ( \
256 "ldr r7,="#f"\n\t" \
257 "mov r12,r7\n\t" \
258 "svc 0" \
259 : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
260 : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
261 : "r7", "r12", "lr", "cc" \
262 );
263 #else
264 #define SVC_Call(f) \
265 __asm volatile \
266 ( \
267 "ldr r12,="#f"\n\t" \
268 "svc 0" \
269 : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
270 : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
271 : "r12", "lr", "cc" \
272 );
273 #endif
274
275 #define SVC_0_1(f,t,rv) \
276 __attribute__((always_inline)) \
277 static inline t __##f (void) { \
278 SVC_Arg0(); \
279 SVC_Call(f); \
280 return (t) rv; \
281 }
282
283 #define SVC_1_1(f,t,t1,rv) \
284 __attribute__((always_inline)) \
285 static inline t __##f (t1 a1) { \
286 SVC_Arg1(t1); \
287 SVC_Call(f); \
288 return (t) rv; \
289 }
290
291 #define SVC_2_1(f,t,t1,t2,rv) \
292 __attribute__((always_inline)) \
293 static inline t __##f (t1 a1, t2 a2) { \
294 SVC_Arg2(t1,t2); \
295 SVC_Call(f); \
296 return (t) rv; \
297 }
298
299 #define SVC_3_1(f,t,t1,t2,t3,rv) \
300 __attribute__((always_inline)) \
301 static inline t __##f (t1 a1, t2 a2, t3 a3) { \
302 SVC_Arg3(t1,t2,t3); \
303 SVC_Call(f); \
304 return (t) rv; \
305 }
306
307 #define SVC_4_1(f,t,t1,t2,t3,t4,rv) \
308 __attribute__((always_inline)) \
309 static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
310 SVC_Arg4(t1,t2,t3,t4); \
311 SVC_Call(f); \
312 return (t) rv; \
313 }
314
315 #define SVC_1_2 SVC_1_1
316 #define SVC_1_3 SVC_1_1
317 #define SVC_2_3 SVC_2_1
318
319 #elif defined (__ICCARM__) /* IAR Compiler */
320
321 #define __NO_RETURN __noreturn
322
323 #define RET_osEvent "=r"(ret.status), "=r"(ret.value), "=r"(ret.def)
324 #define RET_osCallback "=r"(ret.fp), "=r"(ret.arg)
325
326 #define osEvent_type osEvent
327 #define osEvent_ret_status ret
328 #define osEvent_ret_value ret
329 #define osEvent_ret_msg ret
330 #define osEvent_ret_mail ret
331
332 #define osCallback_type uint64_t
333 #define osCallback_ret ((uint64_t)ret.fp | ((uint64_t)ret.arg)<<32)
334
335 #define SVC_Setup(f) \
336 __asm( \
337 "mov r12,%0\n" \
338 :: "r"(&f): "r12" \
339 );
340
341 #define SVC_Ret3() \
342 __asm( \
343 "ldr r0,[sp,#0]\n" \
344 "ldr r1,[sp,#4]\n" \
345 "ldr r2,[sp,#8]\n" \
346 );
347
348 #define SVC_0_1(f,t,...) \
349 t f (void); \
350 _Pragma("swi_number=0") __swi t _##f (void); \
351 static inline t __##f (void) { \
352 SVC_Setup(f); \
353 return _##f(); \
354 }
355
356 #define SVC_1_1(f,t,t1,...) \
357 t f (t1 a1); \
358 _Pragma("swi_number=0") __swi t _##f (t1 a1); \
359 static inline t __##f (t1 a1) { \
360 SVC_Setup(f); \
361 return _##f(a1); \
362 }
363
364 #define SVC_2_1(f,t,t1,t2,...) \
365 t f (t1 a1, t2 a2); \
366 _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2); \
367 static inline t __##f (t1 a1, t2 a2) { \
368 SVC_Setup(f); \
369 return _##f(a1,a2); \
370 }
371
372 #define SVC_3_1(f,t,t1,t2,t3,...) \
373 t f (t1 a1, t2 a2, t3 a3); \
374 _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3); \
375 static inline t __##f (t1 a1, t2 a2, t3 a3) { \
376 SVC_Setup(f); \
377 return _##f(a1,a2,a3); \
378 }
379
380 #define SVC_4_1(f,t,t1,t2,t3,t4,...) \
381 t f (t1 a1, t2 a2, t3 a3, t4 a4); \
382 _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3, t4 a4); \
383 static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) { \
384 SVC_Setup(f); \
385 return _##f(a1,a2,a3,a4); \
386 }
387
388 #define SVC_1_2(f,t,t1,rr) \
389 uint64_t f (t1 a1); \
390 _Pragma("swi_number=0") __swi uint64_t _##f (t1 a1); \
391 static inline t __##f (t1 a1) { \
392 t ret; \
393 SVC_Setup(f); \
394 _##f(a1); \
395 __asm("" : rr : :); \
396 return ret; \
397 }
398
399 #define SVC_1_3(f,t,t1,rr) \
400 t f (t1 a1); \
401 void f##_ (t1 a1) { \
402 f(a1); \
403 SVC_Ret3(); \
404 } \
405 _Pragma("swi_number=0") __swi void _##f (t1 a1); \
406 static inline t __##f (t1 a1) { \
407 t ret; \
408 SVC_Setup(f##_); \
409 _##f(a1); \
410 __asm("" : rr : :); \
411 return ret; \
412 }
413
414 #define SVC_2_3(f,t,t1,t2,rr) \
415 t f (t1 a1, t2 a2); \
416 void f##_ (t1 a1, t2 a2) { \
417 f(a1,a2); \
418 SVC_Ret3(); \
419 } \
420 _Pragma("swi_number=0") __swi void _##f (t1 a1, t2 a2); \
421 static inline t __##f (t1 a1, t2 a2) { \
422 t ret; \
423 SVC_Setup(f##_); \
424 _##f(a1,a2); \
425 __asm("" : rr : :); \
426 return ret; \
427 }
428
429 #endif
430
431
432 // Callback structure
433 typedef struct {
434 void *fp; // Function pointer
435 void *arg; // Function argument
436 } osCallback;
437
438
439 // OS Section definitions
440 #ifdef OS_SECTIONS_LINK_INFO
441 extern const uint32_t os_section_id$$Base;
442 extern const uint32_t os_section_id$$Limit;
443 #endif
444
445 // OS Stack Memory for Threads definitions
446 extern uint64_t os_stack_mem[];
447 extern const uint32_t os_stack_sz;
448
449 // OS Timers external resources
450 extern const osThreadDef_t os_thread_def_osTimerThread;
451 extern osThreadId osThreadId_osTimerThread;
452 extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ;
453 extern osMessageQId osMessageQId_osTimerMessageQ;
454
455 extern U32 IRQNestLevel; /* Indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR. */
456
457
458 // ==== Helper Functions ====
459
460 /// Convert timeout in millisec to system ticks
461 static uint32_t rt_ms2tick (uint32_t millisec) {
462 uint32_t tick;
463
464 if (millisec == osWaitForever) return 0xFFFF; // Indefinite timeout
465 if (millisec > 4000000) return 0xFFFE; // Max ticks supported
466
467 tick = ((1000 * millisec) + os_clockrate - 1) / os_clockrate;
468 if (tick > 0xFFFE) return 0xFFFE;
469
470 return tick;
471 }
472
473 /// Convert Thread ID to TCB pointer
474 static P_TCB rt_tid2ptcb (osThreadId thread_id) {
475 P_TCB ptcb;
476
477 if (thread_id == NULL) return NULL;
478
479 if ((uint32_t)thread_id & 3) return NULL;
480
481 #ifdef OS_SECTIONS_LINK_INFO
482 if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) {
483 if (thread_id < (osThreadId)os_section_id$$Base) return NULL;
484 if (thread_id >= (osThreadId)os_section_id$$Limit) return NULL;
485 }
486 #endif
487
488 ptcb = thread_id;
489
490 if (ptcb->cb_type != TCB) return NULL;
491
492 return ptcb;
493 }
494
495 /// Convert ID pointer to Object pointer
496 static void *rt_id2obj (void *id) {
497
498 if ((uint32_t)id & 3) return NULL;
499
500 #ifdef OS_SECTIONS_LINK_INFO
501 if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) {
502 if (id < (void *)os_section_id$$Base) return NULL;
503 if (id >= (void *)os_section_id$$Limit) return NULL;
504 }
505 #endif
506
507 return id;
508 }
509
510 // === Helper functions for system call interface ===
511
512 static __inline char __get_mode(void) {
513 return (char)(__get_CPSR() & 0x1f);
514 }
515
516 static __inline char __exceptional_mode(void) {
517 switch(__get_mode()) {
518 case MODE_USR:
519 case MODE_SYS:
520 return 0;
521 case MODE_SVC:
522 if (IRQNestLevel == 0)
523 return 0; /* handling a regular service call */
524 else
525 return 1; /* handling an ISR in SVC mode */
526 default:
527 return 1;
528 }
529 }
530
531 // ==== Kernel Control ====
532
533 uint8_t os_initialized; // Kernel Initialized flag
534 uint8_t os_running; // Kernel Running flag
535
536 // Kernel Control Service Calls declarations
537 SVC_0_1(svcKernelInitialize, osStatus, RET_osStatus)
538 SVC_0_1(svcKernelStart, osStatus, RET_osStatus)
539 SVC_0_1(svcKernelRunning, int32_t, RET_int32_t)
540
541 static void sysThreadError (osStatus status);
542 osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument);
543 osMessageQId svcMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
544
545 // Kernel Control Service Calls
546
547 /// Initialize the RTOS Kernel for creating objects
548 osStatus svcKernelInitialize (void) {
549 int ret;
550
551 if (!os_initialized) {
552
553 // Init Thread Stack Memory (must be 8-byte aligned)
554 if ((uint32_t)os_stack_mem & 7) return osErrorNoMemory;
555 ret = rt_init_mem(os_stack_mem, os_stack_sz);
556 if (ret != 0) return osErrorNoMemory;
557
558 rt_sys_init(); // RTX System Initialization
559 }
560
561 os_tsk.run->prio = 255; // Highest priority
562
563 if (!os_initialized) {
564 // Create OS Timers resources (Message Queue & Thread)
565 osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
566 osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
567 }
568
569 sysThreadError(osOK);
570
571 os_initialized = 1;
572
573 return osOK;
574 }
575
576 /// Start the RTOS Kernel
577 osStatus svcKernelStart (void) {
578
579 if (os_running) return osOK;
580
581 rt_tsk_prio(0, 0); // Lowest priority
582 __set_PSP(os_tsk.run->tsk_stack + 8*4); // New context
583 os_tsk.run = NULL; // Force context switch
584
585 rt_sys_start();
586
587 os_running = 1;
588
589 return osOK;
590 }
591
592 /// Check if the RTOS kernel is already started
593 int32_t svcKernelRunning(void) {
594 return os_running;
595 }
596
597 // Kernel Control Public API
598
599 /// Initialize the RTOS Kernel for creating objects
600 osStatus osKernelInitialize (void) {
601 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
602 if (__get_mode() != MODE_USR) {
603 return svcKernelInitialize();
604 } else {
605 return __svcKernelInitialize();
606 }
607 }
608
609 /// Start the RTOS Kernel
610 osStatus osKernelStart (void) {
611 char mode = __get_mode();
612
613 switch(mode) {
614 case MODE_USR:
615 if (os_flags & 1) return osErrorOS; // Privileged Thread mode requested from Unprivileged
616 break;
617 case MODE_SYS:
618 if (!(os_flags & 1)) {
619 __set_CPS_USR();
620 }
621 break;
622 default:
623 return osErrorISR; // Not allowed in ISR
624 }
625 return __svcKernelStart();
626 }
627
628 /// Check if the RTOS kernel is already started
629 int32_t osKernelRunning(void) {
630 if(__get_mode() != MODE_USR) {
631 return os_running;
632 } else {
633 return __svcKernelRunning();
634 }
635 }
636
637
638 // ==== Thread Management ====
639
640 /// Set Thread Error (for Create functions which return IDs)
641 static void sysThreadError (osStatus status) {
642 // To Do
643 }
644
645 __NO_RETURN void osThreadExit (void);
646
647 // Thread Service Calls declarations
648 SVC_2_1(svcThreadCreate, osThreadId, const osThreadDef_t *, void *, RET_pointer)
649 SVC_0_1(svcThreadGetId, osThreadId, RET_pointer)
650 SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET_osStatus)
651 SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
652 SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus)
653 SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority)
654
655 // Thread Service Calls
656
657 /// Create a thread and add it to Active Threads and set it to state READY
658 osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument) {
659 P_TCB ptcb;
660 OS_TID tsk;
661 void *stk;
662
663 if ((thread_def == NULL) ||
664 (thread_def->pthread == NULL) ||
665 (thread_def->tpriority < osPriorityIdle) ||
666 (thread_def->tpriority > osPriorityRealtime)) {
667 sysThreadError(osErrorParameter);
668 return NULL;
669 }
670
671 if (thread_def->stacksize != 0) { // Custom stack size
672 stk = rt_alloc_mem( // Allocate stack
673 os_stack_mem,
674 thread_def->stacksize
675 );
676 if (stk == NULL) {
677 sysThreadError(osErrorNoMemory); // Out of memory
678 return NULL;
679 }
680 } else { // Default stack size
681 stk = NULL;
682 }
683
684 tsk = rt_tsk_create( // Create task
685 (FUNCP)thread_def->pthread, // Task function pointer
686 (thread_def->tpriority-osPriorityIdle+1) | // Task priority
687 (thread_def->stacksize << 8), // Task stack size in bytes
688 stk, // Pointer to task's stack
689 argument // Argument to the task
690 );
691
692 if (tsk == 0) { // Invalid task ID
693 if (stk != NULL) {
694 rt_free_mem(os_stack_mem, stk); // Free allocated stack
695 }
696 sysThreadError(osErrorNoMemory); // Create task failed (Out of memory)
697 return NULL;
698 }
699
700 ptcb = (P_TCB)os_active_TCB[tsk - 1]; // TCB pointer
701
702 *((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit;
703
704 return ptcb;
705 }
706
707 /// Return the thread ID of the current running thread
708 osThreadId svcThreadGetId (void) {
709 OS_TID tsk;
710
711 tsk = rt_tsk_self();
712 if (tsk == 0) return NULL;
713 return (P_TCB)os_active_TCB[tsk - 1];
714 }
715
716 /// Terminate execution of a thread and remove it from ActiveThreads
717 osStatus svcThreadTerminate (osThreadId thread_id) {
718 OS_RESULT res;
719 P_TCB ptcb;
720 void *stk;
721
722 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
723 if (ptcb == NULL) return osErrorParameter;
724
725 stk = ptcb->priv_stack ? ptcb->stack : NULL; // Private stack
726
727 res = rt_tsk_delete(ptcb->task_id); // Delete task
728
729 if (res == OS_R_NOK) return osErrorResource; // Delete task failed
730
731 if (stk != NULL) {
732 rt_free_mem(os_stack_mem, stk); // Free private stack
733 }
734
735 return osOK;
736 }
737
738 /// Pass control to next thread that is in state READY
739 osStatus svcThreadYield (void) {
740 rt_tsk_pass(); // Pass control to next task
741 return osOK;
742 }
743
744 /// Change priority of an active thread
745 osStatus svcThreadSetPriority (osThreadId thread_id, osPriority priority) {
746 OS_RESULT res;
747 P_TCB ptcb;
748
749 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
750 if (ptcb == NULL) return osErrorParameter;
751
752 if ((priority < osPriorityIdle) || (priority > osPriorityRealtime)) {
753 return osErrorValue;
754 }
755
756 res = rt_tsk_prio( // Change task priority
757 ptcb->task_id, // Task ID
758 priority - osPriorityIdle + 1 // New task priority
759 );
760
761 if (res == OS_R_NOK) return osErrorResource; // Change task priority failed
762
763 return osOK;
764 }
765
766 /// Get current priority of an active thread
767 osPriority svcThreadGetPriority (osThreadId thread_id) {
768 P_TCB ptcb;
769
770 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
771 if (ptcb == NULL) return osPriorityError;
772
773 return (osPriority)(ptcb->prio - 1 + osPriorityIdle);
774 }
775
776
777 // Thread Public API
778
779 /// Create a thread and add it to Active Threads and set it to state READY
780 osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
781 if (__exceptional_mode()) return NULL; // Not allowed in ISR
782 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
783 // Privileged and not running
784 return svcThreadCreate(thread_def, argument);
785 } else {
786 return __svcThreadCreate(thread_def, argument);
787 }
788 }
789
790 /// Return the thread ID of the current running thread
791 osThreadId osThreadGetId (void) {
792 if (__exceptional_mode()) return NULL; // Not allowed in ISR
793 return __svcThreadGetId();
794 }
795
796 /// Terminate execution of a thread and remove it from ActiveThreads
797 osStatus osThreadTerminate (osThreadId thread_id) {
798 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
799 return __svcThreadTerminate(thread_id);
800 }
801
802 /// Pass control to next thread that is in state READY
803 osStatus osThreadYield (void) {
804 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
805 return __svcThreadYield();
806 }
807
808 /// Change priority of an active thread
809 osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) {
810 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
811 return __svcThreadSetPriority(thread_id, priority);
812 }
813
814 /// Get current priority of an active thread
815 osPriority osThreadGetPriority (osThreadId thread_id) {
816 if (__exceptional_mode()) return osPriorityError;// Not allowed in ISR
817 return __svcThreadGetPriority(thread_id);
818 }
819
820 /// INTERNAL - Not Public
821 /// Auto Terminate Thread on exit (used implicitly when thread exists)
822 __NO_RETURN void osThreadExit (void) {
823 __svcThreadTerminate(__svcThreadGetId());
824 for (;;); // Should never come here
825 }
826
827 #ifdef __MBED_CMSIS_RTOS_CA9
828 /// Get current thread state
829 uint8_t osThreadGetState (osThreadId thread_id) {
830 P_TCB ptcb;
831
832 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
833
834 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
835 if (ptcb == NULL) return osErrorParameter;
836
837 return ptcb->state;
838 }
839 #endif
840
841 // ==== Generic Wait Functions ====
842
843 // Generic Wait Service Calls declarations
844 SVC_1_1(svcDelay, osStatus, uint32_t, RET_osStatus)
845 #if osFeature_Wait != 0
846 SVC_1_3(svcWait, os_InRegs osEvent, uint32_t, RET_osEvent)
847 #endif
848
849 // Generic Wait Service Calls
850
851 /// Wait for Timeout (Time Delay)
852 osStatus svcDelay (uint32_t millisec) {
853 if (millisec == 0) return osOK;
854 rt_dly_wait(rt_ms2tick(millisec));
855 return osEventTimeout;
856 }
857
858 /// Wait for Signal, Message, Mail, or Timeout
859 #if osFeature_Wait != 0
860 os_InRegs osEvent_type svcWait (uint32_t millisec) {
861 osEvent ret;
862
863 if (millisec == 0) {
864 ret.status = osOK;
865 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
866 osEvent_ret_status;
867 return;
868 #else
869 return osEvent_ret_status;
870 #endif
871 }
872
873 /* To Do: osEventSignal, osEventMessage, osEventMail */
874 rt_dly_wait(rt_ms2tick(millisec));
875 ret.status = osEventTimeout;
876
877 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
878 osEvent_ret_status;
879 return;
880 #else
881 return osEvent_ret_status;
882 #endif
883 }
884 #endif
885
886
887 // Generic Wait API
888
889 /// Wait for Timeout (Time Delay)
890 osStatus osDelay (uint32_t millisec) {
891 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
892 return __svcDelay(millisec);
893 }
894
895 /// Wait for Signal, Message, Mail, or Timeout
896 os_InRegs osEvent osWait (uint32_t millisec) {
897 osEvent ret;
898
899 #if osFeature_Wait == 0
900 ret.status = osErrorOS;
901 return ret;
902 #else
903 if (__exceptional_mode()) { // Not allowed in ISR
904 ret.status = osErrorISR;
905 return ret;
906 }
907 return __svcWait(millisec);
908 #endif
909 }
910
911
912 // ==== Timer Management ====
913
914 // Timer definitions
915 #define osTimerInvalid 0
916 #define osTimerStopped 1
917 #define osTimerRunning 2
918
919 // Timer structures
920
921 typedef struct os_timer_cb_ { // Timer Control Block
922 struct os_timer_cb_ *next; // Pointer to next active Timer
923 uint8_t state; // Timer State
924 uint8_t type; // Timer Type (Periodic/One-shot)
925 uint16_t reserved; // Reserved
926 uint16_t tcnt; // Timer Delay Count
927 uint16_t icnt; // Timer Initial Count
928 void *arg; // Timer Function Argument
929 const osTimerDef_t *timer; // Pointer to Timer definition
930 } os_timer_cb;
931
932 // Timer variables
933 os_timer_cb *os_timer_head; // Pointer to first active Timer
934
935
936 // Timer Helper Functions
937
938 // Insert Timer into the list sorted by time
939 static void rt_timer_insert (os_timer_cb *pt, uint32_t tcnt) {
940 os_timer_cb *p, *prev;
941
942 prev = NULL;
943 p = os_timer_head;
944 while (p != NULL) {
945 if (tcnt < p->tcnt) break;
946 tcnt -= p->tcnt;
947 prev = p;
948 p = p->next;
949 }
950 pt->next = p;
951 pt->tcnt = (uint16_t)tcnt;
952 if (p != NULL) {
953 p->tcnt -= pt->tcnt;
954 }
955 if (prev != NULL) {
956 prev->next = pt;
957 } else {
958 os_timer_head = pt;
959 }
960 }
961
962 // Remove Timer from the list
963 static int rt_timer_remove (os_timer_cb *pt) {
964 os_timer_cb *p, *prev;
965
966 prev = NULL;
967 p = os_timer_head;
968 while (p != NULL) {
969 if (p == pt) break;
970 prev = p;
971 p = p->next;
972 }
973 if (p == NULL) return -1;
974 if (prev != NULL) {
975 prev->next = pt->next;
976 } else {
977 os_timer_head = pt->next;
978 }
979 if (pt->next != NULL) {
980 pt->next->tcnt += pt->tcnt;
981 }
982
983 return 0;
984 }
985
986
987 // Timer Service Calls declarations
988 SVC_3_1(svcTimerCreate, osTimerId, const osTimerDef_t *, os_timer_type, void *, RET_pointer)
989 SVC_2_1(svcTimerStart, osStatus, osTimerId, uint32_t, RET_osStatus)
990 SVC_1_1(svcTimerStop, osStatus, osTimerId, RET_osStatus)
991 SVC_1_1(svcTimerDelete, osStatus, osTimerId, RET_osStatus)
992 SVC_1_2(svcTimerCall, os_InRegs osCallback, osTimerId, RET_osCallback)
993
994 // Timer Management Service Calls
995
996 /// Create timer
997 osTimerId svcTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
998 os_timer_cb *pt;
999
1000 if ((timer_def == NULL) || (timer_def->ptimer == NULL)) {
1001 sysThreadError(osErrorParameter);
1002 return NULL;
1003 }
1004
1005 pt = timer_def->timer;
1006 if (pt == NULL) {
1007 sysThreadError(osErrorParameter);
1008 return NULL;
1009 }
1010
1011 if ((type != osTimerOnce) && (type != osTimerPeriodic)) {
1012 sysThreadError(osErrorValue);
1013 return NULL;
1014 }
1015
1016 if (osThreadId_osTimerThread == NULL) {
1017 sysThreadError(osErrorResource);
1018 return NULL;
1019 }
1020
1021 if (pt->state != osTimerInvalid){
1022 sysThreadError(osErrorResource);
1023 return NULL;
1024 }
1025
1026 pt->state = osTimerStopped;
1027 pt->type = (uint8_t)type;
1028 pt->arg = argument;
1029 pt->timer = timer_def;
1030
1031 return (osTimerId)pt;
1032 }
1033
1034 /// Start or restart timer
1035 osStatus svcTimerStart (osTimerId timer_id, uint32_t millisec) {
1036 os_timer_cb *pt;
1037 uint32_t tcnt;
1038
1039 pt = rt_id2obj(timer_id);
1040 if (pt == NULL) return osErrorParameter;
1041
1042 tcnt = rt_ms2tick(millisec);
1043 if (tcnt == 0) return osErrorValue;
1044
1045 switch (pt->state) {
1046 case osTimerRunning:
1047 if (rt_timer_remove(pt) != 0) {
1048 return osErrorResource;
1049 }
1050 break;
1051 case osTimerStopped:
1052 pt->state = osTimerRunning;
1053 pt->icnt = (uint16_t)tcnt;
1054 break;
1055 default:
1056 return osErrorResource;
1057 }
1058
1059 rt_timer_insert(pt, tcnt);
1060
1061 return osOK;
1062 }
1063
1064 /// Stop timer
1065 osStatus svcTimerStop (osTimerId timer_id) {
1066 os_timer_cb *pt;
1067
1068 pt = rt_id2obj(timer_id);
1069 if (pt == NULL) return osErrorParameter;
1070
1071 if (pt->state != osTimerRunning) return osErrorResource;
1072
1073 pt->state = osTimerStopped;
1074
1075 if (rt_timer_remove(pt) != 0) {
1076 return osErrorResource;
1077 }
1078
1079 return osOK;
1080 }
1081
1082 /// Delete timer
1083 osStatus svcTimerDelete (osTimerId timer_id) {
1084 os_timer_cb *pt;
1085
1086 pt = rt_id2obj(timer_id);
1087 if (pt == NULL) return osErrorParameter;
1088
1089 switch (pt->state) {
1090 case osTimerRunning:
1091 rt_timer_remove(pt);
1092 break;
1093 case osTimerStopped:
1094 break;
1095 default:
1096 return osErrorResource;
1097 }
1098
1099 pt->state = osTimerInvalid;
1100
1101 return osOK;
1102 }
1103
1104 /// Get timer callback parameters
1105 os_InRegs osCallback_type svcTimerCall (osTimerId timer_id) {
1106 os_timer_cb *pt;
1107 osCallback ret;
1108
1109 pt = rt_id2obj(timer_id);
1110 if (pt == NULL) {
1111 ret.fp = NULL;
1112 ret.arg = NULL;
1113 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1114 osCallback_ret;
1115 return;
1116 #else
1117 return osCallback_ret;
1118 #endif
1119 }
1120
1121 ret.fp = (void *)pt->timer->ptimer;
1122 ret.arg = pt->arg;
1123
1124 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1125 osCallback_ret;
1126 return;
1127 #else
1128 return osCallback_ret;
1129 #endif
1130 }
1131
1132 static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
1133
1134 /// Timer Tick (called each SysTick)
1135 void sysTimerTick (void) {
1136 os_timer_cb *pt, *p;
1137
1138 p = os_timer_head;
1139 if (p == NULL) return;
1140
1141 p->tcnt--;
1142 while ((p != NULL) && (p->tcnt == 0)) {
1143 pt = p;
1144 p = p->next;
1145 os_timer_head = p;
1146 isrMessagePut(osMessageQId_osTimerMessageQ, (uint32_t)pt, 0);
1147 if (pt->type == osTimerPeriodic) {
1148 rt_timer_insert(pt, pt->icnt);
1149 } else {
1150 pt->state = osTimerStopped;
1151 }
1152 }
1153 }
1154
1155
1156 // Timer Management Public API
1157
1158 /// Create timer
1159 osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
1160 if (__exceptional_mode()) return NULL; // Not allowed in ISR
1161 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
1162 // Privileged and not running
1163 return svcTimerCreate(timer_def, type, argument);
1164 } else {
1165 return __svcTimerCreate(timer_def, type, argument);
1166 }
1167 }
1168
1169 /// Start or restart timer
1170 osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
1171 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1172 return __svcTimerStart(timer_id, millisec);
1173 }
1174
1175 /// Stop timer
1176 osStatus osTimerStop (osTimerId timer_id) {
1177 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1178 return __svcTimerStop(timer_id);
1179 }
1180
1181 /// Delete timer
1182 osStatus osTimerDelete (osTimerId timer_id) {
1183 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1184 return __svcTimerDelete(timer_id);
1185 }
1186
1187 /// INTERNAL - Not Public
1188 /// Get timer callback parameters (used by OS Timer Thread)
1189 os_InRegs osCallback osTimerCall (osTimerId timer_id) {
1190 return __svcTimerCall(timer_id);
1191 }
1192
1193
1194 // Timer Thread
1195 __NO_RETURN void osTimerThread (void const *argument) {
1196 osCallback cb;
1197 osEvent evt;
1198
1199 for (;;) {
1200 evt = osMessageGet(osMessageQId_osTimerMessageQ, osWaitForever);
1201 if (evt.status == osEventMessage) {
1202 cb = osTimerCall(evt.value.p);
1203 if (cb.fp != NULL) {
1204 (*(os_ptimer)cb.fp)(cb.arg);
1205 }
1206 }
1207 }
1208 }
1209
1210
1211 // ==== Signal Management ====
1212
1213 // Signal Service Calls declarations
1214 SVC_2_1(svcSignalSet, int32_t, osThreadId, int32_t, RET_int32_t)
1215 SVC_2_1(svcSignalClear, int32_t, osThreadId, int32_t, RET_int32_t)
1216 SVC_1_1(svcSignalGet, int32_t, osThreadId, RET_int32_t)
1217 SVC_2_3(svcSignalWait, os_InRegs osEvent, int32_t, uint32_t, RET_osEvent)
1218
1219 // Signal Service Calls
1220
1221 /// Set the specified Signal Flags of an active thread
1222 int32_t svcSignalSet (osThreadId thread_id, int32_t signals) {
1223 P_TCB ptcb;
1224 int32_t sig;
1225
1226 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
1227 if (ptcb == NULL) return 0x80000000;
1228
1229 if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
1230
1231 sig = ptcb->events; // Previous signal flags
1232
1233 rt_evt_set(signals, ptcb->task_id); // Set event flags
1234
1235 return sig;
1236 }
1237
1238 /// Clear the specified Signal Flags of an active thread
1239 int32_t svcSignalClear (osThreadId thread_id, int32_t signals) {
1240 P_TCB ptcb;
1241 int32_t sig;
1242
1243 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
1244 if (ptcb == NULL) return 0x80000000;
1245
1246 if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
1247
1248 sig = ptcb->events; // Previous signal flags
1249
1250 rt_evt_clr(signals, ptcb->task_id); // Clear event flags
1251
1252 return sig;
1253 }
1254
1255 /// Get Signal Flags status of an active thread
1256 int32_t svcSignalGet (osThreadId thread_id) {
1257 P_TCB ptcb;
1258
1259 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
1260 if (ptcb == NULL) return 0x80000000;
1261
1262 return ptcb->events; // Return event flags
1263 }
1264
1265 /// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
1266 os_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) {
1267 OS_RESULT res;
1268 osEvent ret;
1269
1270 if (signals & (0xFFFFFFFF << osFeature_Signals)) {
1271 ret.status = osErrorValue;
1272 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1273 osEvent_ret_status;
1274 return;
1275 #else
1276 return osEvent_ret_status;
1277 #endif
1278 }
1279
1280 if (signals != 0) { // Wait for all specified signals
1281 res = rt_evt_wait(signals, rt_ms2tick(millisec), __TRUE);
1282 } else { // Wait for any signal
1283 res = rt_evt_wait(0xFFFF, rt_ms2tick(millisec), __FALSE);
1284 }
1285
1286 if (res == OS_R_EVT) {
1287 ret.status = osEventSignal;
1288 ret.value.signals = signals ? signals : os_tsk.run->waits;
1289 } else {
1290 ret.status = millisec ? osEventTimeout : osOK;
1291 ret.value.signals = 0;
1292 }
1293
1294 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1295 osEvent_ret_value;
1296 return;
1297 #else
1298 return osEvent_ret_value;
1299 #endif
1300 }
1301
1302
1303 // Signal ISR Calls
1304
1305 /// Set the specified Signal Flags of an active thread
1306 static __INLINE int32_t isrSignalSet (osThreadId thread_id, int32_t signals) {
1307 P_TCB ptcb;
1308 int32_t sig;
1309
1310 ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
1311 if (ptcb == NULL) return 0x80000000;
1312
1313 if (signals & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
1314
1315 sig = ptcb->events; // Previous signal flags
1316
1317 isr_evt_set(signals, ptcb->task_id); // Set event flags
1318
1319 return sig;
1320 }
1321
1322
1323 // Signal Public API
1324
1325 /// Set the specified Signal Flags of an active thread
1326 int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
1327 if (__exceptional_mode()) { // in ISR
1328 return isrSignalSet(thread_id, signals);
1329 } else { // in Thread
1330 return __svcSignalSet(thread_id, signals);
1331 }
1332 }
1333
1334 /// Clear the specified Signal Flags of an active thread
1335 int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
1336 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1337 return __svcSignalClear(thread_id, signals);
1338 }
1339
1340 /// Get Signal Flags status of an active thread
1341 int32_t osSignalGet (osThreadId thread_id) {
1342 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1343 return __svcSignalGet(thread_id);
1344 }
1345
1346 /// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
1347 os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
1348 osEvent ret;
1349
1350 if (__exceptional_mode()) { // Not allowed in ISR
1351 ret.status = osErrorISR;
1352 return ret;
1353 }
1354 return __svcSignalWait(signals, millisec);
1355 }
1356
1357
1358 // ==== Mutex Management ====
1359
1360 // Mutex Service Calls declarations
1361 SVC_1_1(svcMutexCreate, osMutexId, const osMutexDef_t *, RET_pointer)
1362 SVC_2_1(svcMutexWait, osStatus, osMutexId, uint32_t, RET_osStatus)
1363 SVC_1_1(svcMutexRelease, osStatus, osMutexId, RET_osStatus)
1364 SVC_1_1(svcMutexDelete, osStatus, osMutexId, RET_osStatus)
1365
1366 // Mutex Service Calls
1367
1368 /// Create and Initialize a Mutex object
1369 osMutexId svcMutexCreate (const osMutexDef_t *mutex_def) {
1370 OS_ID mut;
1371
1372 if (mutex_def == NULL) {
1373 sysThreadError(osErrorParameter);
1374 return NULL;
1375 }
1376
1377 mut = mutex_def->mutex;
1378 if (mut == NULL) {
1379 sysThreadError(osErrorParameter);
1380 return NULL;
1381 }
1382
1383 if (((P_MUCB)mut)->cb_type != 0) {
1384 sysThreadError(osErrorParameter);
1385 return NULL;
1386 }
1387
1388 rt_mut_init(mut); // Initialize Mutex
1389
1390 return mut;
1391 }
1392
1393 /// Wait until a Mutex becomes available
1394 osStatus svcMutexWait (osMutexId mutex_id, uint32_t millisec) {
1395 OS_ID mut;
1396 OS_RESULT res;
1397
1398 mut = rt_id2obj(mutex_id);
1399 if (mut == NULL) return osErrorParameter;
1400
1401 if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
1402
1403 res = rt_mut_wait(mut, rt_ms2tick(millisec)); // Wait for Mutex
1404
1405 if (res == OS_R_TMO) {
1406 return (millisec ? osErrorTimeoutResource : osErrorResource);
1407 }
1408
1409 return osOK;
1410 }
1411
1412 /// Release a Mutex that was obtained with osMutexWait
1413 osStatus svcMutexRelease (osMutexId mutex_id) {
1414 OS_ID mut;
1415 OS_RESULT res;
1416
1417 mut = rt_id2obj(mutex_id);
1418 if (mut == NULL) return osErrorParameter;
1419
1420 if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
1421
1422 res = rt_mut_release(mut); // Release Mutex
1423
1424 if (res == OS_R_NOK) return osErrorResource; // Thread not owner or Zero Counter
1425
1426 return osOK;
1427 }
1428
1429 /// Delete a Mutex that was created by osMutexCreate
1430 osStatus svcMutexDelete (osMutexId mutex_id) {
1431 OS_ID mut;
1432
1433 mut = rt_id2obj(mutex_id);
1434 if (mut == NULL) return osErrorParameter;
1435
1436 if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
1437
1438 rt_mut_delete(mut); // Release Mutex
1439
1440 return osOK;
1441 }
1442
1443
1444 // Mutex Public API
1445
1446 /// Create and Initialize a Mutex object
1447 osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
1448 if (__exceptional_mode()) return NULL; // Not allowed in ISR
1449 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
1450 // Privileged and not running
1451 return svcMutexCreate(mutex_def);
1452 } else {
1453 return __svcMutexCreate(mutex_def);
1454 }
1455 }
1456
1457 /// Wait until a Mutex becomes available
1458 osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
1459 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1460 return __svcMutexWait(mutex_id, millisec);
1461 }
1462
1463 /// Release a Mutex that was obtained with osMutexWait
1464 osStatus osMutexRelease (osMutexId mutex_id) {
1465 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1466 return __svcMutexRelease(mutex_id);
1467 }
1468
1469 /// Delete a Mutex that was created by osMutexCreate
1470 osStatus osMutexDelete (osMutexId mutex_id) {
1471 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1472 return __svcMutexDelete(mutex_id);
1473 }
1474
1475
1476 // ==== Semaphore Management ====
1477
1478 // Semaphore Service Calls declarations
1479 SVC_2_1(svcSemaphoreCreate, osSemaphoreId, const osSemaphoreDef_t *, int32_t, RET_pointer)
1480 SVC_2_1(svcSemaphoreWait, int32_t, osSemaphoreId, uint32_t, RET_int32_t)
1481 SVC_1_1(svcSemaphoreRelease, osStatus, osSemaphoreId, RET_osStatus)
1482 SVC_1_1(svcSemaphoreDelete, osStatus, osSemaphoreId, RET_osStatus)
1483
1484 // Semaphore Service Calls
1485
1486 /// Create and Initialize a Semaphore object
1487 osSemaphoreId svcSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
1488 OS_ID sem;
1489
1490 if (semaphore_def == NULL) {
1491 sysThreadError(osErrorParameter);
1492 return NULL;
1493 }
1494
1495 sem = semaphore_def->semaphore;
1496 if (sem == NULL) {
1497 sysThreadError(osErrorParameter);
1498 return NULL;
1499 }
1500
1501 if (((P_SCB)sem)->cb_type != 0) {
1502 sysThreadError(osErrorParameter);
1503 return NULL;
1504 }
1505
1506 if (count > osFeature_Semaphore) {
1507 sysThreadError(osErrorValue);
1508 return NULL;
1509 }
1510
1511 rt_sem_init(sem, count); // Initialize Semaphore
1512
1513 return sem;
1514 }
1515
1516 /// Wait until a Semaphore becomes available
1517 int32_t svcSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
1518 OS_ID sem;
1519 OS_RESULT res;
1520
1521 sem = rt_id2obj(semaphore_id);
1522 if (sem == NULL) return -1;
1523
1524 if (((P_SCB)sem)->cb_type != SCB) return -1;
1525
1526 res = rt_sem_wait(sem, rt_ms2tick(millisec)); // Wait for Semaphore
1527
1528 if (res == OS_R_TMO) return 0; // Timeout
1529
1530 return (((P_SCB)sem)->tokens + 1);
1531 }
1532
1533 /// Release a Semaphore
1534 osStatus svcSemaphoreRelease (osSemaphoreId semaphore_id) {
1535 OS_ID sem;
1536
1537 sem = rt_id2obj(semaphore_id);
1538 if (sem == NULL) return osErrorParameter;
1539
1540 if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
1541
1542 if (((P_SCB)sem)->tokens == osFeature_Semaphore) return osErrorResource;
1543
1544 rt_sem_send(sem); // Release Semaphore
1545
1546 return osOK;
1547 }
1548
1549 /// Delete a Semaphore that was created by osSemaphoreCreate
1550 osStatus svcSemaphoreDelete (osSemaphoreId semaphore_id) {
1551 OS_ID sem;
1552
1553 sem = rt_id2obj(semaphore_id);
1554 if (sem == NULL) return osErrorParameter;
1555
1556 if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
1557
1558 rt_sem_delete(sem); // Delete Semaphore
1559
1560 return osOK;
1561 }
1562
1563
1564 // Semaphore ISR Calls
1565
1566 /// Release a Semaphore
1567 static __INLINE osStatus isrSemaphoreRelease (osSemaphoreId semaphore_id) {
1568 OS_ID sem;
1569
1570 sem = rt_id2obj(semaphore_id);
1571 if (sem == NULL) return osErrorParameter;
1572
1573 if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
1574
1575 if (((P_SCB)sem)->tokens == osFeature_Semaphore) return osErrorResource;
1576
1577 isr_sem_send(sem); // Release Semaphore
1578
1579 return osOK;
1580 }
1581
1582
1583 // Semaphore Public API
1584
1585 /// Create and Initialize a Semaphore object
1586 osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
1587 if (__exceptional_mode()) return NULL; // Not allowed in ISR
1588 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
1589 // Privileged and not running
1590 return svcSemaphoreCreate(semaphore_def, count);
1591 } else {
1592 return __svcSemaphoreCreate(semaphore_def, count);
1593 }
1594 }
1595
1596 /// Wait until a Semaphore becomes available
1597 int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
1598 if (__exceptional_mode()) return -1; // Not allowed in ISR
1599 return __svcSemaphoreWait(semaphore_id, millisec);
1600 }
1601
1602 /// Release a Semaphore
1603 osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
1604 if (__exceptional_mode()) { // in ISR
1605 return isrSemaphoreRelease(semaphore_id);
1606 } else { // in Thread
1607 return __svcSemaphoreRelease(semaphore_id);
1608 }
1609 }
1610
1611 /// Delete a Semaphore that was created by osSemaphoreCreate
1612 osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
1613 if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
1614 return __svcSemaphoreDelete(semaphore_id);
1615 }
1616
1617
1618 // ==== Memory Management Functions ====
1619
1620 // Memory Management Helper Functions
1621
1622 // Clear Memory Box (Zero init)
1623 static void rt_clr_box (void *box_mem, void *box) {
1624 uint32_t *p, n;
1625
1626 if (box) {
1627 p = box;
1628 for (n = ((P_BM)box_mem)->blk_size; n; n -= 4) {
1629 *p++ = 0;
1630 }
1631 }
1632 }
1633
1634 // Memory Management Service Calls declarations
1635 SVC_1_1(svcPoolCreate, osPoolId, const osPoolDef_t *, RET_pointer)
1636 SVC_2_1(sysPoolAlloc, void *, osPoolId, uint32_t, RET_pointer)
1637 SVC_2_1(sysPoolFree, osStatus, osPoolId, void *, RET_osStatus)
1638
1639 // Memory Management Service & ISR Calls
1640
1641 /// Create and Initialize memory pool
1642 osPoolId svcPoolCreate (const osPoolDef_t *pool_def) {
1643 uint32_t blk_sz;
1644
1645 if ((pool_def == NULL) ||
1646 (pool_def->pool_sz == 0) ||
1647 (pool_def->item_sz == 0) ||
1648 (pool_def->pool == NULL)) {
1649 sysThreadError(osErrorParameter);
1650 return NULL;
1651 }
1652
1653 blk_sz = (pool_def->item_sz + 3) & ~3;
1654
1655 _init_box(pool_def->pool, sizeof(struct OS_BM) + pool_def->pool_sz * blk_sz, blk_sz);
1656
1657 return pool_def->pool;
1658 }
1659
1660 /// Allocate a memory block from a memory pool
1661 void *sysPoolAlloc (osPoolId pool_id, uint32_t clr) {
1662 void *ptr;
1663
1664 if (pool_id == NULL) return NULL;
1665
1666 ptr = rt_alloc_box(pool_id);
1667 if (clr) {
1668 rt_clr_box(pool_id, ptr);
1669 }
1670
1671 return ptr;
1672 }
1673
1674 /// Return an allocated memory block back to a specific memory pool
1675 osStatus sysPoolFree (osPoolId pool_id, void *block) {
1676 int32_t res;
1677
1678 if (pool_id == NULL) return osErrorParameter;
1679
1680 res = rt_free_box(pool_id, block);
1681 if (res != 0) return osErrorValue;
1682
1683 return osOK;
1684 }
1685
1686
1687 // Memory Management Public API
1688
1689 /// Create and Initialize memory pool
1690 osPoolId osPoolCreate (const osPoolDef_t *pool_def) {
1691 if (__exceptional_mode()) return NULL; // Not allowed in ISR
1692 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
1693 // Privileged and not running
1694 return svcPoolCreate(pool_def);
1695 } else {
1696 return __svcPoolCreate(pool_def);
1697 }
1698 }
1699
1700 /// Allocate a memory block from a memory pool
1701 void *osPoolAlloc (osPoolId pool_id) {
1702 if (__get_mode() != MODE_USR) { // in ISR or Privileged
1703 return sysPoolAlloc(pool_id, 0);
1704 } else { // in Thread
1705 return __sysPoolAlloc(pool_id, 0);
1706 }
1707 }
1708
1709 /// Allocate a memory block from a memory pool and set memory block to zero
1710 void *osPoolCAlloc (osPoolId pool_id) {
1711 if (__get_mode() != MODE_USR) { // in ISR or Privileged
1712 return sysPoolAlloc(pool_id, 1);
1713 } else { // in Thread
1714 return __sysPoolAlloc(pool_id, 1);
1715 }
1716 }
1717
1718 /// Return an allocated memory block back to a specific memory pool
1719 osStatus osPoolFree (osPoolId pool_id, void *block) {
1720 if (__get_mode() != MODE_USR) { // in ISR or Privileged
1721 return sysPoolFree(pool_id, block);
1722 } else { // in Thread
1723 return __sysPoolFree(pool_id, block);
1724 }
1725 }
1726
1727
1728 // ==== Message Queue Management Functions ====
1729
1730 // Message Queue Management Service Calls declarations
1731 SVC_2_1(svcMessageCreate, osMessageQId, const osMessageQDef_t *, osThreadId, RET_pointer)
1732 SVC_3_1(svcMessagePut, osStatus, osMessageQId, uint32_t, uint32_t, RET_osStatus)
1733 SVC_2_3(svcMessageGet, os_InRegs osEvent, osMessageQId, uint32_t, RET_osEvent)
1734
1735 // Message Queue Service Calls
1736
1737 /// Create and Initialize Message Queue
1738 osMessageQId svcMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
1739
1740 if ((queue_def == NULL) ||
1741 (queue_def->queue_sz == 0) ||
1742 (queue_def->pool == NULL)) {
1743 sysThreadError(osErrorParameter);
1744 return NULL;
1745 }
1746
1747 if (((P_MCB)queue_def->pool)->cb_type != 0) {
1748 sysThreadError(osErrorParameter);
1749 return NULL;
1750 }
1751
1752 rt_mbx_init(queue_def->pool, 4*(queue_def->queue_sz + 4));
1753
1754 return queue_def->pool;
1755 }
1756
1757 /// Put a Message to a Queue
1758 osStatus svcMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
1759 OS_RESULT res;
1760
1761 if (queue_id == NULL) return osErrorParameter;
1762
1763 if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter;
1764
1765 res = rt_mbx_send(queue_id, (void *)info, rt_ms2tick(millisec));
1766
1767 if (res == OS_R_TMO) {
1768 return (millisec ? osErrorTimeoutResource : osErrorResource);
1769 }
1770
1771 return osOK;
1772 }
1773
1774 /// Get a Message or Wait for a Message from a Queue
1775 os_InRegs osEvent_type svcMessageGet (osMessageQId queue_id, uint32_t millisec) {
1776 OS_RESULT res;
1777 osEvent ret;
1778
1779 if (queue_id == NULL) {
1780 ret.status = osErrorParameter;
1781 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1782 osEvent_ret_status;
1783 return;
1784 #else
1785 return osEvent_ret_status;
1786 #endif
1787 }
1788
1789 if (((P_MCB)queue_id)->cb_type != MCB) {
1790 ret.status = osErrorParameter;
1791 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1792 osEvent_ret_status;
1793 return;
1794 #else
1795 return osEvent_ret_status;
1796 #endif
1797 }
1798
1799 res = rt_mbx_wait(queue_id, &ret.value.p, rt_ms2tick(millisec));
1800
1801 if (res == OS_R_TMO) {
1802 ret.status = millisec ? osEventTimeout : osOK;
1803 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1804 osEvent_ret_value;
1805 return;
1806 #else
1807 return osEvent_ret_value;
1808 #endif
1809 }
1810
1811 ret.status = osEventMessage;
1812
1813 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1814 osEvent_ret_value;
1815 return;
1816 #else
1817 return osEvent_ret_value;
1818 #endif
1819 }
1820
1821
1822 // Message Queue ISR Calls
1823
1824 /// Put a Message to a Queue
1825 static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
1826
1827 if ((queue_id == NULL) || (millisec != 0)) {
1828 return osErrorParameter;
1829 }
1830
1831 if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter;
1832
1833 if (rt_mbx_check(queue_id) == 0) { // Check if Queue is full
1834 return osErrorResource;
1835 }
1836
1837 isr_mbx_send(queue_id, (void *)info);
1838
1839 return osOK;
1840 }
1841
1842 /// Get a Message or Wait for a Message from a Queue
1843 static __INLINE os_InRegs osEvent isrMessageGet (osMessageQId queue_id, uint32_t millisec) {
1844 OS_RESULT res;
1845 osEvent ret;
1846
1847 if ((queue_id == NULL) || (millisec != 0)) {
1848 ret.status = osErrorParameter;
1849 return ret;
1850 }
1851
1852 if (((P_MCB)queue_id)->cb_type != MCB) {
1853 ret.status = osErrorParameter;
1854 return ret;
1855 }
1856
1857 res = isr_mbx_receive(queue_id, &ret.value.p);
1858
1859 if (res != OS_R_MBX) {
1860 ret.status = osOK;
1861 return ret;
1862 }
1863
1864 ret.status = osEventMessage;
1865
1866 return ret;
1867 }
1868
1869
1870 // Message Queue Management Public API
1871
1872 /// Create and Initialize Message Queue
1873 osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
1874 if (__exceptional_mode()) return NULL; // Not allowed in ISR
1875 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
1876 // Privileged and not running
1877 return svcMessageCreate(queue_def, thread_id);
1878 } else {
1879 return __svcMessageCreate(queue_def, thread_id);
1880 }
1881 }
1882
1883 /// Put a Message to a Queue
1884 osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
1885 if (__exceptional_mode()) { // in ISR
1886 return isrMessagePut(queue_id, info, millisec);
1887 } else { // in Thread
1888 return __svcMessagePut(queue_id, info, millisec);
1889 }
1890 }
1891
1892 /// Get a Message or Wait for a Message from a Queue
1893 os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
1894 if (__exceptional_mode()) { // in ISR
1895 return isrMessageGet(queue_id, millisec);
1896 } else { // in Thread
1897 return __svcMessageGet(queue_id, millisec);
1898 }
1899 }
1900
1901
1902 // ==== Mail Queue Management Functions ====
1903
1904 // Mail Queue Management Service Calls declarations
1905 SVC_2_1(svcMailCreate, osMailQId, const osMailQDef_t *, osThreadId, RET_pointer)
1906 SVC_4_1(sysMailAlloc, void *, osMailQId, uint32_t, uint32_t, uint32_t, RET_pointer)
1907 SVC_3_1(sysMailFree, osStatus, osMailQId, void *, uint32_t, RET_osStatus)
1908
1909 // Mail Queue Management Service & ISR Calls
1910
1911 /// Create and Initialize mail queue
1912 osMailQId svcMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
1913 uint32_t blk_sz;
1914 P_MCB pmcb;
1915 void *pool;
1916
1917 if ((queue_def == NULL) ||
1918 (queue_def->queue_sz == 0) ||
1919 (queue_def->item_sz == 0) ||
1920 (queue_def->pool == NULL)) {
1921 sysThreadError(osErrorParameter);
1922 return NULL;
1923 }
1924
1925 pmcb = *(((void **)queue_def->pool) + 0);
1926 pool = *(((void **)queue_def->pool) + 1);
1927
1928 if ((pool == NULL) || (pmcb == NULL) || (pmcb->cb_type != 0)) {
1929 sysThreadError(osErrorParameter);
1930 return NULL;
1931 }
1932
1933 blk_sz = (queue_def->item_sz + 3) & ~3;
1934
1935 _init_box(pool, sizeof(struct OS_BM) + queue_def->queue_sz * blk_sz, blk_sz);
1936
1937 rt_mbx_init(pmcb, 4*(queue_def->queue_sz + 4));
1938
1939
1940 return queue_def->pool;
1941 }
1942
1943 /// Allocate a memory block from a mail
1944 void *sysMailAlloc (osMailQId queue_id, uint32_t millisec, uint32_t isr, uint32_t clr) {
1945 P_MCB pmcb;
1946 void *pool;
1947 void *mem;
1948
1949 if (queue_id == NULL) return NULL;
1950
1951 pmcb = *(((void **)queue_id) + 0);
1952 pool = *(((void **)queue_id) + 1);
1953
1954 if ((pool == NULL) || (pmcb == NULL)) return NULL;
1955
1956 if (isr && (millisec != 0)) return NULL;
1957
1958 mem = rt_alloc_box(pool);
1959 if (clr) {
1960 rt_clr_box(pool, mem);
1961 }
1962
1963 if ((mem == NULL) && (millisec != 0)) {
1964 // Put Task to sleep when Memory not available
1965 if (pmcb->p_lnk != NULL) {
1966 rt_put_prio((P_XCB)pmcb, os_tsk.run);
1967 } else {
1968 pmcb->p_lnk = os_tsk.run;
1969 os_tsk.run->p_lnk = NULL;
1970 os_tsk.run->p_rlnk = (P_TCB)pmcb;
1971 // Task is waiting to allocate a message
1972 pmcb->state = 3;
1973 }
1974 rt_block(rt_ms2tick(millisec), WAIT_MBX);
1975 }
1976
1977 return mem;
1978 }
1979
1980 /// Free a memory block from a mail
1981 osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
1982 P_MCB pmcb;
1983 P_TCB ptcb;
1984 void *pool;
1985 void *mem;
1986 int32_t res;
1987
1988 if (queue_id == NULL) return osErrorParameter;
1989
1990 pmcb = *(((void **)queue_id) + 0);
1991 pool = *(((void **)queue_id) + 1);
1992
1993 if ((pmcb == NULL) || (pool == NULL)) return osErrorParameter;
1994
1995 res = rt_free_box(pool, mail);
1996
1997 if (res != 0) return osErrorValue;
1998
1999 if (pmcb->state == 3) {
2000 // Task is waiting to allocate a message
2001 if (isr) {
2002 rt_psq_enq (pmcb, (U32)pool);
2003 rt_psh_req ();
2004 } else {
2005 mem = rt_alloc_box(pool);
2006 if (mem != NULL) {
2007 ptcb = rt_get_first((P_XCB)pmcb);
2008 if (pmcb->p_lnk == NULL) {
2009 pmcb->state = 0;
2010 }
2011 rt_ret_val(ptcb, (U32)mem);
2012 rt_rmv_dly(ptcb);
2013 rt_dispatch(ptcb);
2014 }
2015 }
2016 }
2017
2018 return osOK;
2019 }
2020
2021
2022 // Mail Queue Management Public API
2023
2024 /// Create and Initialize mail queue
2025 osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
2026 if (__exceptional_mode()) return NULL; // Not allowed in ISR
2027 if ((__get_mode() != MODE_USR) && (os_running == 0)) {
2028 // Privileged and not running
2029 return svcMailCreate(queue_def, thread_id);
2030 } else {
2031 return __svcMailCreate(queue_def, thread_id);
2032 }
2033 }
2034
2035 /// Allocate a memory block from a mail
2036 void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
2037 if (__exceptional_mode()) { // in ISR
2038 return sysMailAlloc(queue_id, millisec, 1, 0);
2039 } else { // in Thread
2040 return __sysMailAlloc(queue_id, millisec, 0, 0);
2041 }
2042 }
2043
2044 /// Allocate a memory block from a mail and set memory block to zero
2045 void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
2046 if (__exceptional_mode()) { // in ISR
2047 return sysMailAlloc(queue_id, millisec, 1, 1);
2048 } else { // in Thread
2049 return __sysMailAlloc(queue_id, millisec, 0, 1);
2050 }
2051 }
2052
2053 /// Free a memory block from a mail
2054 osStatus osMailFree (osMailQId queue_id, void *mail) {
2055 if (__exceptional_mode()) { // in ISR
2056 return sysMailFree(queue_id, mail, 1);
2057 } else { // in Thread
2058 return __sysMailFree(queue_id, mail, 0);
2059 }
2060 }
2061
2062 /// Put a mail to a queue
2063 osStatus osMailPut (osMailQId queue_id, void *mail) {
2064 if (queue_id == NULL) return osErrorParameter;
2065 if (mail == NULL) return osErrorValue;
2066 return osMessagePut(*((void **)queue_id), (uint32_t)mail, 0);
2067 }
2068
2069 #ifdef __CC_ARM
2070 #pragma push
2071 #pragma Ospace
2072 #endif // __arm__
2073 /// Get a mail from a queue
2074 os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
2075 osEvent ret;
2076
2077 if (queue_id == NULL) {
2078 ret.status = osErrorParameter;
2079 return ret;
2080 }
2081
2082 ret = osMessageGet(*((void **)queue_id), millisec);
2083 if (ret.status == osEventMessage) ret.status = osEventMail;
2084
2085 return ret;
2086 }
2087 #ifdef __CC_ARM
2088 #pragma pop
2089 #endif // __arm__
Imprint / Impressum