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;