1 /*----------------------------------------------------------------------------
3 *----------------------------------------------------------------------------
5 * Purpose: CMSIS RTOS API
7 *----------------------------------------------------------------------------
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.
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 *---------------------------------------------------------------------------*/
35 #define __CMSIS_GENERIC
37 #if defined (__CORTEX_M4) || defined (__CORTEX_M4F)
39 #elif defined (__CORTEX_M3)
41 #elif defined (__CORTEX_M0)
43 #elif defined (__CORTEX_A9)
46 #error "Missing __CORTEX_xx definition"
49 #include "rt_TypeDef.h"
50 #include "RTX_Config.h"
51 #include "rt_System.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"
63 #define os_thread_cb OS_TCB
67 #if (osFeature_Signals != 16)
68 #error Invalid "osFeature_Signals" value!
70 #if (osFeature_Semaphore > 65535)
71 #error Invalid "osFeature_Semaphore" value!
73 #if (osFeature_Wait != 0)
74 #error osWait not supported!
78 // ==== Enumeration, structures, defines ====
80 // Service Calls defines
82 #if defined (__CC_ARM) /* ARM Compiler */
84 #define __NO_RETURN __declspec(noreturn)
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
92 #define osCallback_type osCallback
93 #define osCallback_ret ret
95 #define SVC_0_1(f,t,...) \
96 __svc_indirect(0) t _##f (t(*)()); \
98 __attribute__((always_inline)) \
99 static __inline t __##f (void) { \
103 #define SVC_1_1(f,t,t1,...) \
104 __svc_indirect(0) t _##f (t(*)(t1),t1); \
106 __attribute__((always_inline)) \
107 static __inline t __##f (t1 a1) { \
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); \
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); \
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); \
135 #define SVC_1_2 SVC_1_1
136 #define SVC_1_3 SVC_1_1
137 #define SVC_2_3 SVC_2_1
139 #elif defined (__GNUC__) /* GNU Compiler */
141 #define __NO_RETURN __attribute__((noreturn))
143 typedef uint32_t __attribute__((vector_size(8))) ret64
;
144 typedef uint32_t __attribute__((vector_size(16))) ret128
;
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}
154 #if defined (__ARM_PCS_VFP)
156 #define osEvent_type void
157 #define osEvent_ret_status { __asm ("MOV r0, %0;" \
163 #define osEvent_ret_value { __asm ("MOV r1, %0;" \
166 : "r"(ret.value.v), \
171 #define osEvent_ret_msg { __asm ("MOV r2, %0;" \
175 : "r"(ret.def.message_id), \
178 : "r0", "r1" , "r2" \
182 #define osEvent_ret_mail { __asm ("MOV r2, %0;" \
186 : "r"(ret.def.mail_id), \
189 : "r0", "r1" , "r2" \
193 #define osCallback_type void
194 #define osCallback_ret { __asm ("MOV r1, %0;" \
203 #else /* defined (__ARM_PCS_VFP) */
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}
211 #define osCallback_type ret64
212 #define osCallback_ret (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg}
214 #endif /* defined (__ARM_PCS_VFP) */
216 #define SVC_ArgN(n) \
217 register int __r##n __asm("r"#n);
219 #define SVC_ArgR(n,t,a) \
220 register t __r##n __asm("r"#n) = a;
228 #define SVC_Arg1(t1) \
234 #define SVC_Arg2(t1,t2) \
240 #define SVC_Arg3(t1,t2,t3) \
246 #define SVC_Arg4(t1,t2,t3,t4) \
252 #if (defined (__CORTEX_M0))
253 #define SVC_Call(f) \
259 : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
260 : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
261 : "r7", "r12", "lr", "cc" \
264 #define SVC_Call(f) \
267 "ldr r12,="#f"\n\t" \
269 : "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3) \
270 : "r" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) \
271 : "r12", "lr", "cc" \
275 #define SVC_0_1(f,t,rv) \
276 __attribute__((always_inline)) \
277 static inline t __##f (void) { \
283 #define SVC_1_1(f,t,t1,rv) \
284 __attribute__((always_inline)) \
285 static inline t __##f (t1 a1) { \
291 #define SVC_2_1(f,t,t1,t2,rv) \
292 __attribute__((always_inline)) \
293 static inline t __##f (t1 a1, t2 a2) { \
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); \
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); \
315 #define SVC_1_2 SVC_1_1
316 #define SVC_1_3 SVC_1_1
317 #define SVC_2_3 SVC_2_1
319 #elif defined (__ICCARM__) /* IAR Compiler */
321 #define __NO_RETURN __noreturn
323 #define RET_osEvent "=r"(ret.status), "=r"(ret.value), "=r"(ret.def)
324 #define RET_osCallback "=r"(ret.fp), "=r"(ret.arg)
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
332 #define osCallback_type uint64_t
333 #define osCallback_ret ((uint64_t)ret.fp | ((uint64_t)ret.arg)<<32)
335 #define SVC_Setup(f) \
348 #define SVC_0_1(f,t,...) \
350 _Pragma("swi_number=0") __swi t _##f (void); \
351 static inline t __##f (void) { \
356 #define SVC_1_1(f,t,t1,...) \
358 _Pragma("swi_number=0") __swi t _##f (t1 a1); \
359 static inline t __##f (t1 a1) { \
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) { \
369 return _##f(a1,a2); \
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) { \
377 return _##f(a1,a2,a3); \
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) { \
385 return _##f(a1,a2,a3,a4); \
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) { \
395 __asm("" : rr : :); \
399 #define SVC_1_3(f,t,t1,rr) \
401 void f##_ (t1 a1) { \
405 _Pragma("swi_number=0") __swi void _##f (t1 a1); \
406 static inline t __##f (t1 a1) { \
410 __asm("" : rr : :); \
414 #define SVC_2_3(f,t,t1,t2,rr) \
415 t f (t1 a1, t2 a2); \
416 void f##_ (t1 a1, t2 a2) { \
420 _Pragma("swi_number=0") __swi void _##f (t1 a1, t2 a2); \
421 static inline t __##f (t1 a1, t2 a2) { \
425 __asm("" : rr : :); \
432 // Callback structure
434 void *fp
; // Function pointer
435 void *arg
; // Function argument
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
;
445 // OS Stack Memory for Threads definitions
446 extern uint64_t os_stack_mem
[];
447 extern const uint32_t os_stack_sz
;
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
;
455 extern U32 IRQNestLevel
; /* Indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR. */
458 // ==== Helper Functions ====
460 /// Convert timeout in millisec to system ticks
461 static uint32_t rt_ms2tick (uint32_t millisec
) {
464 if (millisec
== osWaitForever
) return 0xFFFF; // Indefinite timeout
465 if (millisec
> 4000000) return 0xFFFE; // Max ticks supported
467 tick
= ((1000 * millisec
) + os_clockrate
- 1) / os_clockrate
;
468 if (tick
> 0xFFFE) return 0xFFFE;
473 /// Convert Thread ID to TCB pointer
474 static P_TCB
rt_tid2ptcb (osThreadId thread_id
) {
477 if (thread_id
== NULL
) return NULL
;
479 if ((uint32_t)thread_id
& 3) return NULL
;
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
;
490 if (ptcb
->cb_type
!= TCB
) return NULL
;
495 /// Convert ID pointer to Object pointer
496 static void *rt_id2obj (void *id
) {
498 if ((uint32_t)id
& 3) return NULL
;
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
;
510 // === Helper functions for system call interface ===
512 static __inline
char __get_mode(void) {
513 return (char)(__get_CPSR() & 0x1f);
516 static __inline
char __exceptional_mode(void) {
517 switch(__get_mode()) {
522 if (IRQNestLevel
== 0)
523 return 0; /* handling a regular service call */
525 return 1; /* handling an ISR in SVC mode */
531 // ==== Kernel Control ====
533 uint8_t os_initialized
; // Kernel Initialized flag
534 uint8_t os_running
; // Kernel Running flag
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
)
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
);
545 // Kernel Control Service Calls
547 /// Initialize the RTOS Kernel for creating objects
548 osStatus
svcKernelInitialize (void) {
551 if (!os_initialized
) {
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
;
558 rt_sys_init(); // RTX System Initialization
561 os_tsk
.run
->prio
= 255; // Highest priority
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
);
569 sysThreadError(osOK
);
576 /// Start the RTOS Kernel
577 osStatus
svcKernelStart (void) {
579 if (os_running
) return osOK
;
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
592 /// Check if the RTOS kernel is already started
593 int32_t svcKernelRunning(void) {
597 // Kernel Control Public API
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();
605 return __svcKernelInitialize();
609 /// Start the RTOS Kernel
610 osStatus
osKernelStart (void) {
611 char mode
= __get_mode();
615 if (os_flags
& 1) return osErrorOS
; // Privileged Thread mode requested from Unprivileged
618 if (!(os_flags
& 1)) {
623 return osErrorISR
; // Not allowed in ISR
625 return __svcKernelStart();
628 /// Check if the RTOS kernel is already started
629 int32_t osKernelRunning(void) {
630 if(__get_mode() != MODE_USR
) {
633 return __svcKernelRunning();
638 // ==== Thread Management ====
640 /// Set Thread Error (for Create functions which return IDs)
641 static void sysThreadError (osStatus status
) {
645 __NO_RETURN
void osThreadExit (void);
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
)
655 // Thread Service Calls
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
) {
663 if ((thread_def
== NULL
) ||
664 (thread_def
->pthread
== NULL
) ||
665 (thread_def
->tpriority
< osPriorityIdle
) ||
666 (thread_def
->tpriority
> osPriorityRealtime
)) {
667 sysThreadError(osErrorParameter
);
671 if (thread_def
->stacksize
!= 0) { // Custom stack size
672 stk
= rt_alloc_mem( // Allocate stack
674 thread_def
->stacksize
677 sysThreadError(osErrorNoMemory
); // Out of memory
680 } else { // Default stack size
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
692 if (tsk
== 0) { // Invalid task ID
694 rt_free_mem(os_stack_mem
, stk
); // Free allocated stack
696 sysThreadError(osErrorNoMemory
); // Create task failed (Out of memory)
700 ptcb
= (P_TCB
)os_active_TCB
[tsk
- 1]; // TCB pointer
702 *((uint32_t *)ptcb
->tsk_stack
+ 13) = (uint32_t)osThreadExit
;
707 /// Return the thread ID of the current running thread
708 osThreadId
svcThreadGetId (void) {
712 if (tsk
== 0) return NULL
;
713 return (P_TCB
)os_active_TCB
[tsk
- 1];
716 /// Terminate execution of a thread and remove it from ActiveThreads
717 osStatus
svcThreadTerminate (osThreadId thread_id
) {
722 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
723 if (ptcb
== NULL
) return osErrorParameter
;
725 stk
= ptcb
->priv_stack
? ptcb
->stack
: NULL
; // Private stack
727 res
= rt_tsk_delete(ptcb
->task_id
); // Delete task
729 if (res
== OS_R_NOK
) return osErrorResource
; // Delete task failed
732 rt_free_mem(os_stack_mem
, stk
); // Free private stack
738 /// Pass control to next thread that is in state READY
739 osStatus
svcThreadYield (void) {
740 rt_tsk_pass(); // Pass control to next task
744 /// Change priority of an active thread
745 osStatus
svcThreadSetPriority (osThreadId thread_id
, osPriority priority
) {
749 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
750 if (ptcb
== NULL
) return osErrorParameter
;
752 if ((priority
< osPriorityIdle
) || (priority
> osPriorityRealtime
)) {
756 res
= rt_tsk_prio( // Change task priority
757 ptcb
->task_id
, // Task ID
758 priority
- osPriorityIdle
+ 1 // New task priority
761 if (res
== OS_R_NOK
) return osErrorResource
; // Change task priority failed
766 /// Get current priority of an active thread
767 osPriority
svcThreadGetPriority (osThreadId thread_id
) {
770 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
771 if (ptcb
== NULL
) return osPriorityError
;
773 return (osPriority
)(ptcb
->prio
- 1 + osPriorityIdle
);
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
);
786 return __svcThreadCreate(thread_def
, argument
);
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();
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
);
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();
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
);
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
);
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
827 #ifdef __MBED_CMSIS_RTOS_CA9
828 /// Get current thread state
829 uint8_t osThreadGetState (osThreadId thread_id
) {
832 if (__exceptional_mode()) return osErrorISR
; // Not allowed in ISR
834 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
835 if (ptcb
== NULL
) return osErrorParameter
;
841 // ==== Generic Wait Functions ====
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
)
849 // Generic Wait Service Calls
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
;
858 /// Wait for Signal, Message, Mail, or Timeout
859 #if osFeature_Wait != 0
860 os_InRegs osEvent_type
svcWait (uint32_t millisec
) {
865 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
869 return osEvent_ret_status
;
873 /* To Do: osEventSignal, osEventMessage, osEventMail */
874 rt_dly_wait(rt_ms2tick(millisec
));
875 ret
.status
= osEventTimeout
;
877 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
881 return osEvent_ret_status
;
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
);
895 /// Wait for Signal, Message, Mail, or Timeout
896 os_InRegs osEvent
osWait (uint32_t millisec
) {
899 #if osFeature_Wait == 0
900 ret
.status
= osErrorOS
;
903 if (__exceptional_mode()) { // Not allowed in ISR
904 ret
.status
= osErrorISR
;
907 return __svcWait(millisec
);
912 // ==== Timer Management ====
915 #define osTimerInvalid 0
916 #define osTimerStopped 1
917 #define osTimerRunning 2
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
933 os_timer_cb
*os_timer_head
; // Pointer to first active Timer
936 // Timer Helper Functions
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
;
945 if (tcnt
< p
->tcnt
) break;
951 pt
->tcnt
= (uint16_t)tcnt
;
962 // Remove Timer from the list
963 static int rt_timer_remove (os_timer_cb
*pt
) {
964 os_timer_cb
*p
, *prev
;
973 if (p
== NULL
) return -1;
975 prev
->next
= pt
->next
;
977 os_timer_head
= pt
->next
;
979 if (pt
->next
!= NULL
) {
980 pt
->next
->tcnt
+= pt
->tcnt
;
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
)
994 // Timer Management Service Calls
997 osTimerId
svcTimerCreate (const osTimerDef_t
*timer_def
, os_timer_type type
, void *argument
) {
1000 if ((timer_def
== NULL
) || (timer_def
->ptimer
== NULL
)) {
1001 sysThreadError(osErrorParameter
);
1005 pt
= timer_def
->timer
;
1007 sysThreadError(osErrorParameter
);
1011 if ((type
!= osTimerOnce
) && (type
!= osTimerPeriodic
)) {
1012 sysThreadError(osErrorValue
);
1016 if (osThreadId_osTimerThread
== NULL
) {
1017 sysThreadError(osErrorResource
);
1021 if (pt
->state
!= osTimerInvalid
){
1022 sysThreadError(osErrorResource
);
1026 pt
->state
= osTimerStopped
;
1027 pt
->type
= (uint8_t)type
;
1029 pt
->timer
= timer_def
;
1031 return (osTimerId
)pt
;
1034 /// Start or restart timer
1035 osStatus
svcTimerStart (osTimerId timer_id
, uint32_t millisec
) {
1039 pt
= rt_id2obj(timer_id
);
1040 if (pt
== NULL
) return osErrorParameter
;
1042 tcnt
= rt_ms2tick(millisec
);
1043 if (tcnt
== 0) return osErrorValue
;
1045 switch (pt
->state
) {
1046 case osTimerRunning
:
1047 if (rt_timer_remove(pt
) != 0) {
1048 return osErrorResource
;
1051 case osTimerStopped
:
1052 pt
->state
= osTimerRunning
;
1053 pt
->icnt
= (uint16_t)tcnt
;
1056 return osErrorResource
;
1059 rt_timer_insert(pt
, tcnt
);
1065 osStatus
svcTimerStop (osTimerId timer_id
) {
1068 pt
= rt_id2obj(timer_id
);
1069 if (pt
== NULL
) return osErrorParameter
;
1071 if (pt
->state
!= osTimerRunning
) return osErrorResource
;
1073 pt
->state
= osTimerStopped
;
1075 if (rt_timer_remove(pt
) != 0) {
1076 return osErrorResource
;
1083 osStatus
svcTimerDelete (osTimerId timer_id
) {
1086 pt
= rt_id2obj(timer_id
);
1087 if (pt
== NULL
) return osErrorParameter
;
1089 switch (pt
->state
) {
1090 case osTimerRunning
:
1091 rt_timer_remove(pt
);
1093 case osTimerStopped
:
1096 return osErrorResource
;
1099 pt
->state
= osTimerInvalid
;
1104 /// Get timer callback parameters
1105 os_InRegs osCallback_type
svcTimerCall (osTimerId timer_id
) {
1109 pt
= rt_id2obj(timer_id
);
1113 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1117 return osCallback_ret
;
1121 ret
.fp
= (void *)pt
->timer
->ptimer
;
1124 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1128 return osCallback_ret
;
1132 static __INLINE osStatus
isrMessagePut (osMessageQId queue_id
, uint32_t info
, uint32_t millisec
);
1134 /// Timer Tick (called each SysTick)
1135 void sysTimerTick (void) {
1136 os_timer_cb
*pt
, *p
;
1139 if (p
== NULL
) return;
1142 while ((p
!= NULL
) && (p
->tcnt
== 0)) {
1146 isrMessagePut(osMessageQId_osTimerMessageQ
, (uint32_t)pt
, 0);
1147 if (pt
->type
== osTimerPeriodic
) {
1148 rt_timer_insert(pt
, pt
->icnt
);
1150 pt
->state
= osTimerStopped
;
1156 // Timer Management Public API
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
);
1165 return __svcTimerCreate(timer_def
, type
, argument
);
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
);
1176 osStatus
osTimerStop (osTimerId timer_id
) {
1177 if (__exceptional_mode()) return osErrorISR
; // Not allowed in ISR
1178 return __svcTimerStop(timer_id
);
1182 osStatus
osTimerDelete (osTimerId timer_id
) {
1183 if (__exceptional_mode()) return osErrorISR
; // Not allowed in ISR
1184 return __svcTimerDelete(timer_id
);
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
);
1195 __NO_RETURN
void osTimerThread (void const *argument
) {
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
);
1211 // ==== Signal Management ====
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
)
1219 // Signal Service Calls
1221 /// Set the specified Signal Flags of an active thread
1222 int32_t svcSignalSet (osThreadId thread_id
, int32_t signals
) {
1226 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
1227 if (ptcb
== NULL
) return 0x80000000;
1229 if (signals
& (0xFFFFFFFF << osFeature_Signals
)) return 0x80000000;
1231 sig
= ptcb
->events
; // Previous signal flags
1233 rt_evt_set(signals
, ptcb
->task_id
); // Set event flags
1238 /// Clear the specified Signal Flags of an active thread
1239 int32_t svcSignalClear (osThreadId thread_id
, int32_t signals
) {
1243 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
1244 if (ptcb
== NULL
) return 0x80000000;
1246 if (signals
& (0xFFFFFFFF << osFeature_Signals
)) return 0x80000000;
1248 sig
= ptcb
->events
; // Previous signal flags
1250 rt_evt_clr(signals
, ptcb
->task_id
); // Clear event flags
1255 /// Get Signal Flags status of an active thread
1256 int32_t svcSignalGet (osThreadId thread_id
) {
1259 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
1260 if (ptcb
== NULL
) return 0x80000000;
1262 return ptcb
->events
; // Return event flags
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
) {
1270 if (signals
& (0xFFFFFFFF << osFeature_Signals
)) {
1271 ret
.status
= osErrorValue
;
1272 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1276 return osEvent_ret_status
;
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
);
1286 if (res
== OS_R_EVT
) {
1287 ret
.status
= osEventSignal
;
1288 ret
.value
.signals
= signals
? signals
: os_tsk
.run
->waits
;
1290 ret
.status
= millisec
? osEventTimeout
: osOK
;
1291 ret
.value
.signals
= 0;
1294 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1298 return osEvent_ret_value
;
1305 /// Set the specified Signal Flags of an active thread
1306 static __INLINE
int32_t isrSignalSet (osThreadId thread_id
, int32_t signals
) {
1310 ptcb
= rt_tid2ptcb(thread_id
); // Get TCB pointer
1311 if (ptcb
== NULL
) return 0x80000000;
1313 if (signals
& (0xFFFFFFFF << osFeature_Signals
)) return 0x80000000;
1315 sig
= ptcb
->events
; // Previous signal flags
1317 isr_evt_set(signals
, ptcb
->task_id
); // Set event flags
1323 // Signal Public API
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
);
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
);
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
);
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
) {
1350 if (__exceptional_mode()) { // Not allowed in ISR
1351 ret
.status
= osErrorISR
;
1354 return __svcSignalWait(signals
, millisec
);
1358 // ==== Mutex Management ====
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
)
1366 // Mutex Service Calls
1368 /// Create and Initialize a Mutex object
1369 osMutexId
svcMutexCreate (const osMutexDef_t
*mutex_def
) {
1372 if (mutex_def
== NULL
) {
1373 sysThreadError(osErrorParameter
);
1377 mut
= mutex_def
->mutex
;
1379 sysThreadError(osErrorParameter
);
1383 if (((P_MUCB
)mut
)->cb_type
!= 0) {
1384 sysThreadError(osErrorParameter
);
1388 rt_mut_init(mut
); // Initialize Mutex
1393 /// Wait until a Mutex becomes available
1394 osStatus
svcMutexWait (osMutexId mutex_id
, uint32_t millisec
) {
1398 mut
= rt_id2obj(mutex_id
);
1399 if (mut
== NULL
) return osErrorParameter
;
1401 if (((P_MUCB
)mut
)->cb_type
!= MUCB
) return osErrorParameter
;
1403 res
= rt_mut_wait(mut
, rt_ms2tick(millisec
)); // Wait for Mutex
1405 if (res
== OS_R_TMO
) {
1406 return (millisec
? osErrorTimeoutResource
: osErrorResource
);
1412 /// Release a Mutex that was obtained with osMutexWait
1413 osStatus
svcMutexRelease (osMutexId mutex_id
) {
1417 mut
= rt_id2obj(mutex_id
);
1418 if (mut
== NULL
) return osErrorParameter
;
1420 if (((P_MUCB
)mut
)->cb_type
!= MUCB
) return osErrorParameter
;
1422 res
= rt_mut_release(mut
); // Release Mutex
1424 if (res
== OS_R_NOK
) return osErrorResource
; // Thread not owner or Zero Counter
1429 /// Delete a Mutex that was created by osMutexCreate
1430 osStatus
svcMutexDelete (osMutexId mutex_id
) {
1433 mut
= rt_id2obj(mutex_id
);
1434 if (mut
== NULL
) return osErrorParameter
;
1436 if (((P_MUCB
)mut
)->cb_type
!= MUCB
) return osErrorParameter
;
1438 rt_mut_delete(mut
); // Release Mutex
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
);
1453 return __svcMutexCreate(mutex_def
);
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
);
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
);
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
);
1476 // ==== Semaphore Management ====
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
)
1484 // Semaphore Service Calls
1486 /// Create and Initialize a Semaphore object
1487 osSemaphoreId
svcSemaphoreCreate (const osSemaphoreDef_t
*semaphore_def
, int32_t count
) {
1490 if (semaphore_def
== NULL
) {
1491 sysThreadError(osErrorParameter
);
1495 sem
= semaphore_def
->semaphore
;
1497 sysThreadError(osErrorParameter
);
1501 if (((P_SCB
)sem
)->cb_type
!= 0) {
1502 sysThreadError(osErrorParameter
);
1506 if (count
> osFeature_Semaphore
) {
1507 sysThreadError(osErrorValue
);
1511 rt_sem_init(sem
, count
); // Initialize Semaphore
1516 /// Wait until a Semaphore becomes available
1517 int32_t svcSemaphoreWait (osSemaphoreId semaphore_id
, uint32_t millisec
) {
1521 sem
= rt_id2obj(semaphore_id
);
1522 if (sem
== NULL
) return -1;
1524 if (((P_SCB
)sem
)->cb_type
!= SCB
) return -1;
1526 res
= rt_sem_wait(sem
, rt_ms2tick(millisec
)); // Wait for Semaphore
1528 if (res
== OS_R_TMO
) return 0; // Timeout
1530 return (((P_SCB
)sem
)->tokens
+ 1);
1533 /// Release a Semaphore
1534 osStatus
svcSemaphoreRelease (osSemaphoreId semaphore_id
) {
1537 sem
= rt_id2obj(semaphore_id
);
1538 if (sem
== NULL
) return osErrorParameter
;
1540 if (((P_SCB
)sem
)->cb_type
!= SCB
) return osErrorParameter
;
1542 if (((P_SCB
)sem
)->tokens
== osFeature_Semaphore
) return osErrorResource
;
1544 rt_sem_send(sem
); // Release Semaphore
1549 /// Delete a Semaphore that was created by osSemaphoreCreate
1550 osStatus
svcSemaphoreDelete (osSemaphoreId semaphore_id
) {
1553 sem
= rt_id2obj(semaphore_id
);
1554 if (sem
== NULL
) return osErrorParameter
;
1556 if (((P_SCB
)sem
)->cb_type
!= SCB
) return osErrorParameter
;
1558 rt_sem_delete(sem
); // Delete Semaphore
1564 // Semaphore ISR Calls
1566 /// Release a Semaphore
1567 static __INLINE osStatus
isrSemaphoreRelease (osSemaphoreId semaphore_id
) {
1570 sem
= rt_id2obj(semaphore_id
);
1571 if (sem
== NULL
) return osErrorParameter
;
1573 if (((P_SCB
)sem
)->cb_type
!= SCB
) return osErrorParameter
;
1575 if (((P_SCB
)sem
)->tokens
== osFeature_Semaphore
) return osErrorResource
;
1577 isr_sem_send(sem
); // Release Semaphore
1583 // Semaphore Public API
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
);
1592 return __svcSemaphoreCreate(semaphore_def
, count
);
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
);
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
);
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
);
1618 // ==== Memory Management Functions ====
1620 // Memory Management Helper Functions
1622 // Clear Memory Box (Zero init)
1623 static void rt_clr_box (void *box_mem
, void *box
) {
1628 for (n
= ((P_BM
)box_mem
)->blk_size
; n
; n
-= 4) {
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
)
1639 // Memory Management Service & ISR Calls
1641 /// Create and Initialize memory pool
1642 osPoolId
svcPoolCreate (const osPoolDef_t
*pool_def
) {
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
);
1653 blk_sz
= (pool_def
->item_sz
+ 3) & ~3;
1655 _init_box(pool_def
->pool
, sizeof(struct OS_BM
) + pool_def
->pool_sz
* blk_sz
, blk_sz
);
1657 return pool_def
->pool
;
1660 /// Allocate a memory block from a memory pool
1661 void *sysPoolAlloc (osPoolId pool_id
, uint32_t clr
) {
1664 if (pool_id
== NULL
) return NULL
;
1666 ptr
= rt_alloc_box(pool_id
);
1668 rt_clr_box(pool_id
, ptr
);
1674 /// Return an allocated memory block back to a specific memory pool
1675 osStatus
sysPoolFree (osPoolId pool_id
, void *block
) {
1678 if (pool_id
== NULL
) return osErrorParameter
;
1680 res
= rt_free_box(pool_id
, block
);
1681 if (res
!= 0) return osErrorValue
;
1687 // Memory Management Public API
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
);
1696 return __svcPoolCreate(pool_def
);
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);
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);
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
);
1728 // ==== Message Queue Management Functions ====
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
)
1735 // Message Queue Service Calls
1737 /// Create and Initialize Message Queue
1738 osMessageQId
svcMessageCreate (const osMessageQDef_t
*queue_def
, osThreadId thread_id
) {
1740 if ((queue_def
== NULL
) ||
1741 (queue_def
->queue_sz
== 0) ||
1742 (queue_def
->pool
== NULL
)) {
1743 sysThreadError(osErrorParameter
);
1747 if (((P_MCB
)queue_def
->pool
)->cb_type
!= 0) {
1748 sysThreadError(osErrorParameter
);
1752 rt_mbx_init(queue_def
->pool
, 4*(queue_def
->queue_sz
+ 4));
1754 return queue_def
->pool
;
1757 /// Put a Message to a Queue
1758 osStatus
svcMessagePut (osMessageQId queue_id
, uint32_t info
, uint32_t millisec
) {
1761 if (queue_id
== NULL
) return osErrorParameter
;
1763 if (((P_MCB
)queue_id
)->cb_type
!= MCB
) return osErrorParameter
;
1765 res
= rt_mbx_send(queue_id
, (void *)info
, rt_ms2tick(millisec
));
1767 if (res
== OS_R_TMO
) {
1768 return (millisec
? osErrorTimeoutResource
: osErrorResource
);
1774 /// Get a Message or Wait for a Message from a Queue
1775 os_InRegs osEvent_type
svcMessageGet (osMessageQId queue_id
, uint32_t millisec
) {
1779 if (queue_id
== NULL
) {
1780 ret
.status
= osErrorParameter
;
1781 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1785 return osEvent_ret_status
;
1789 if (((P_MCB
)queue_id
)->cb_type
!= MCB
) {
1790 ret
.status
= osErrorParameter
;
1791 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1795 return osEvent_ret_status
;
1799 res
= rt_mbx_wait(queue_id
, &ret
.value
.p
, rt_ms2tick(millisec
));
1801 if (res
== OS_R_TMO
) {
1802 ret
.status
= millisec
? osEventTimeout
: osOK
;
1803 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1807 return osEvent_ret_value
;
1811 ret
.status
= osEventMessage
;
1813 #if defined (__GNUC__) && defined (__ARM_PCS_VFP)
1817 return osEvent_ret_value
;
1822 // Message Queue ISR Calls
1824 /// Put a Message to a Queue
1825 static __INLINE osStatus
isrMessagePut (osMessageQId queue_id
, uint32_t info
, uint32_t millisec
) {
1827 if ((queue_id
== NULL
) || (millisec
!= 0)) {
1828 return osErrorParameter
;
1831 if (((P_MCB
)queue_id
)->cb_type
!= MCB
) return osErrorParameter
;
1833 if (rt_mbx_check(queue_id
) == 0) { // Check if Queue is full
1834 return osErrorResource
;
1837 isr_mbx_send(queue_id
, (void *)info
);
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
) {
1847 if ((queue_id
== NULL
) || (millisec
!= 0)) {
1848 ret
.status
= osErrorParameter
;
1852 if (((P_MCB
)queue_id
)->cb_type
!= MCB
) {
1853 ret
.status
= osErrorParameter
;
1857 res
= isr_mbx_receive(queue_id
, &ret
.value
.p
);
1859 if (res
!= OS_R_MBX
) {
1864 ret
.status
= osEventMessage
;
1870 // Message Queue Management Public API
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
);
1879 return __svcMessageCreate(queue_def
, thread_id
);
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
);
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
);
1902 // ==== Mail Queue Management Functions ====
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
)
1909 // Mail Queue Management Service & ISR Calls
1911 /// Create and Initialize mail queue
1912 osMailQId
svcMailCreate (const osMailQDef_t
*queue_def
, osThreadId thread_id
) {
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
);
1925 pmcb
= *(((void **)queue_def
->pool
) + 0);
1926 pool
= *(((void **)queue_def
->pool
) + 1);
1928 if ((pool
== NULL
) || (pmcb
== NULL
) || (pmcb
->cb_type
!= 0)) {
1929 sysThreadError(osErrorParameter
);
1933 blk_sz
= (queue_def
->item_sz
+ 3) & ~3;
1935 _init_box(pool
, sizeof(struct OS_BM
) + queue_def
->queue_sz
* blk_sz
, blk_sz
);
1937 rt_mbx_init(pmcb
, 4*(queue_def
->queue_sz
+ 4));
1940 return queue_def
->pool
;
1943 /// Allocate a memory block from a mail
1944 void *sysMailAlloc (osMailQId queue_id
, uint32_t millisec
, uint32_t isr
, uint32_t clr
) {
1949 if (queue_id
== NULL
) return NULL
;
1951 pmcb
= *(((void **)queue_id
) + 0);
1952 pool
= *(((void **)queue_id
) + 1);
1954 if ((pool
== NULL
) || (pmcb
== NULL
)) return NULL
;
1956 if (isr
&& (millisec
!= 0)) return NULL
;
1958 mem
= rt_alloc_box(pool
);
1960 rt_clr_box(pool
, mem
);
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
);
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
1974 rt_block(rt_ms2tick(millisec
), WAIT_MBX
);
1980 /// Free a memory block from a mail
1981 osStatus
sysMailFree (osMailQId queue_id
, void *mail
, uint32_t isr
) {
1988 if (queue_id
== NULL
) return osErrorParameter
;
1990 pmcb
= *(((void **)queue_id
) + 0);
1991 pool
= *(((void **)queue_id
) + 1);
1993 if ((pmcb
== NULL
) || (pool
== NULL
)) return osErrorParameter
;
1995 res
= rt_free_box(pool
, mail
);
1997 if (res
!= 0) return osErrorValue
;
1999 if (pmcb
->state
== 3) {
2000 // Task is waiting to allocate a message
2002 rt_psq_enq (pmcb
, (U32
)pool
);
2005 mem
= rt_alloc_box(pool
);
2007 ptcb
= rt_get_first((P_XCB
)pmcb
);
2008 if (pmcb
->p_lnk
== NULL
) {
2011 rt_ret_val(ptcb
, (U32
)mem
);
2022 // Mail Queue Management Public API
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
);
2031 return __svcMailCreate(queue_def
, thread_id
);
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);
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);
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);
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);
2073 /// Get a mail from a queue
2074 os_InRegs osEvent
osMailGet (osMailQId queue_id
, uint32_t millisec
) {
2077 if (queue_id
== NULL
) {
2078 ret
.status
= osErrorParameter
;
2082 ret
= osMessageGet(*((void **)queue_id
), millisec
);
2083 if (ret
.status
== osEventMessage
) ret
.status
= osEventMail
;