Michael Kersh / Mbed 2 deprecated ECE4180EthernetTest

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rt_CMSIS.c Source File

rt_CMSIS.c

00001 /*----------------------------------------------------------------------------
00002  *      RL-ARM - RTX
00003  *----------------------------------------------------------------------------
00004  *      Name:    rt_CMSIS.c
00005  *      Purpose: CMSIS RTOS API
00006  *      Rev.:    V4.50
00007  *----------------------------------------------------------------------------
00008  *
00009  * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
00010  * All rights reserved.
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are met:
00013  *  - Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  *  - Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  *  - Neither the name of ARM  nor the names of its contributors may be used 
00019  *    to endorse or promote products derived from this software without 
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00023  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
00026  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00027  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00028  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00029  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00030  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  * POSSIBILITY OF SUCH DAMAGE.
00033  *---------------------------------------------------------------------------*/
00034 
00035 #define __CMSIS_GENERIC
00036 
00037 #if defined (__CORTEX_M4) || defined (__CORTEX_M4F)
00038   #include "core_cm4.h"
00039 #elif defined (__CORTEX_M3)
00040   #include "core_cm3.h"
00041 #elif defined (__CORTEX_M0)
00042   #include "core_cm0.h"
00043 #else
00044   #error "Missing __CORTEX_Mx definition"
00045 #endif
00046 
00047 #include "rt_TypeDef.h"
00048 #include "RTX_Config.h"
00049 #include "rt_System.h"
00050 #include "rt_Task.h"
00051 #include "rt_Event.h"
00052 #include "rt_List.h"
00053 #include "rt_Time.h"
00054 #include "rt_Mutex.h"
00055 #include "rt_Semaphore.h"
00056 #include "rt_Mailbox.h"
00057 #include "rt_MemBox.h"
00058 #include "rt_HAL_CM.h"
00059 
00060 #define os_thread_cb OS_TCB
00061 
00062 #include "cmsis_os.h"
00063 
00064 #if (osFeature_Signals != 16)
00065 #error Invalid "osFeature_Signals" value!
00066 #endif
00067 #if (osFeature_Semaphore != 8)
00068 #error Invalid "osFeature_Semaphore" value!
00069 #endif
00070 #if (osFeature_Wait != 0)
00071 #error osWait not supported!
00072 #endif
00073 
00074 
00075 // ==== Enumeration, structures, defines ====
00076 
00077 // Service Calls defines
00078 
00079 #if defined (__CC_ARM)          /* ARM Compiler */
00080 
00081 #define __NO_RETURN __declspec(noreturn)
00082 
00083 #define osEvent_type       osEvent
00084 #define osEvent_ret_status ret
00085 #define osEvent_ret_value  ret
00086 #define osEvent_ret_msg    ret
00087 #define osEvent_ret_mail   ret
00088 
00089 #define osCallback_type    osCallback
00090 #define osCallback_ret     ret
00091 
00092 #define SVC_0_1(f,t,...)                                                       \
00093 __svc_indirect(0) t  _##f (t(*)());                                            \
00094                   t     f (void);                                              \
00095 __attribute__((always_inline))                                                 \
00096 static __inline   t __##f (void) {                                             \
00097   return _##f(f);                                                              \
00098 }
00099 
00100 #define SVC_1_1(f,t,t1,...)                                                    \
00101 __svc_indirect(0) t  _##f (t(*)(t1),t1);                                       \
00102                   t     f (t1 a1);                                             \
00103 __attribute__((always_inline))                                                 \
00104 static __inline   t __##f (t1 a1) {                                            \
00105   return _##f(f,a1);                                                           \
00106 }
00107 
00108 #define SVC_2_1(f,t,t1,t2,...)                                                 \
00109 __svc_indirect(0) t  _##f (t(*)(t1,t2),t1,t2);                                 \
00110                   t     f (t1 a1, t2 a2);                                      \
00111 __attribute__((always_inline))                                                 \
00112 static __inline   t __##f (t1 a1, t2 a2) {                                     \
00113   return _##f(f,a1,a2);                                                        \
00114 }
00115 
00116 #define SVC_3_1(f,t,t1,t2,t3,...)                                              \
00117 __svc_indirect(0) t  _##f (t(*)(t1,t2,t3),t1,t2,t3);                           \
00118                   t     f (t1 a1, t2 a2, t3 a3);                               \
00119 __attribute__((always_inline))                                                 \
00120 static __inline   t __##f (t1 a1, t2 a2, t3 a3) {                              \
00121   return _##f(f,a1,a2,a3);                                                     \
00122 }
00123 
00124 #define SVC_4_1(f,t,t1,t2,t3,t4,...)                                           \
00125 __svc_indirect(0) t  _##f (t(*)(t1,t2,t3,t4),t1,t2,t3,t4);                     \
00126                   t     f (t1 a1, t2 a2, t3 a3, t4 a4);                        \
00127 __attribute__((always_inline))                                                 \
00128 static __inline   t __##f (t1 a1, t2 a2, t3 a3, t4 a4) {                       \
00129   return _##f(f,a1,a2,a3,a4);                                                  \
00130 }
00131 
00132 #define SVC_1_2 SVC_1_1 
00133 #define SVC_1_3 SVC_1_1 
00134 #define SVC_2_3 SVC_2_1 
00135 
00136 #elif defined (__GNUC__)        /* GNU Compiler */
00137 
00138 #define __NO_RETURN __attribute__((noreturn))
00139 
00140 typedef uint32_t __attribute__((vector_size(8)))  ret64;
00141 typedef uint32_t __attribute__((vector_size(16))) ret128;
00142 
00143 #define RET_pointer    __r0
00144 #define RET_int32_t    __r0
00145 #define RET_osStatus   __r0
00146 #define RET_osPriority __r0
00147 #define RET_osEvent    {(osStatus)__r0, {(uint32_t)__r1}, {(void *)__r2}}
00148 #define RET_osCallback {(void *)__r0, (void *)__r1}
00149 
00150 #define osEvent_type        ret128
00151 #define osEvent_ret_status (ret128){ret.status}
00152 #define osEvent_ret_value  (ret128){ret.status, ret.value.v}
00153 #define osEvent_ret_msg    (ret128){ret.status, ret.value.v, (uint32_t)ret.def.message_id}
00154 #define osEvent_ret_mail   (ret128){ret.status, ret.value.v, (uint32_t)ret.def.mail_id}
00155 
00156 #define osCallback_type     ret64
00157 #define osCallback_ret     (ret64) {(uint32_t)ret.fp, (uint32_t)ret.arg}
00158 
00159 #define SVC_ArgN(n) \
00160   register int __r##n __asm("r"#n);
00161 
00162 #define SVC_ArgR(n,t,a) \
00163   register t   __r##n __asm("r"#n) = a;
00164 
00165 #define SVC_Arg0()                                                             \
00166   SVC_ArgN(0)                                                                  \
00167   SVC_ArgN(1)                                                                  \
00168   SVC_ArgN(2)                                                                  \
00169   SVC_ArgN(3)
00170 
00171 #define SVC_Arg1(t1)                                                           \
00172   SVC_ArgR(0,t1,a1)                                                            \
00173   SVC_ArgN(1)                                                                  \
00174   SVC_ArgN(2)                                                                  \
00175   SVC_ArgN(3)
00176 
00177 #define SVC_Arg2(t1,t2)                                                        \
00178   SVC_ArgR(0,t1,a1)                                                            \
00179   SVC_ArgR(1,t2,a2)                                                            \
00180   SVC_ArgN(2)                                                                  \
00181   SVC_ArgN(3)
00182 
00183 #define SVC_Arg3(t1,t2,t3)                                                     \
00184   SVC_ArgR(0,t1,a1)                                                            \
00185   SVC_ArgR(1,t2,a2)                                                            \
00186   SVC_ArgR(2,t3,a3)                                                            \
00187   SVC_ArgN(3)
00188 
00189 #define SVC_Arg4(t1,t2,t3,t4)                                                  \
00190   SVC_ArgR(0,t1,a1)                                                            \
00191   SVC_ArgR(1,t2,a2)                                                            \
00192   SVC_ArgR(2,t3,a3)                                                            \
00193   SVC_ArgR(3,t4,a4)
00194 
00195 #if (defined (__CORTEX_M0))
00196 #define SVC_Call(f)                                                            \
00197   __asm volatile                                                                 \
00198   (                                                                            \
00199     "ldr r7,="#f"\n\t"                                                         \
00200     "mov r12,r7\n\t"                                                           \
00201     "svc 0"                                                                    \
00202     :               "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3)         \
00203     :                "r" (__r0),  "r" (__r1),  "r" (__r2),  "r" (__r3)         \
00204     : "r7", "r12", "lr", "cc"                                                  \
00205   );
00206 #else
00207 #define SVC_Call(f)                                                            \
00208   __asm volatile                                                                 \
00209   (                                                                            \
00210     "ldr r12,="#f"\n\t"                                                        \
00211     "svc 0"                                                                    \
00212     :               "=r" (__r0), "=r" (__r1), "=r" (__r2), "=r" (__r3)         \
00213     :                "r" (__r0),  "r" (__r1),  "r" (__r2),  "r" (__r3)         \
00214     : "r12", "lr", "cc"                                                        \
00215   );
00216 #endif
00217 
00218 #define SVC_0_1(f,t,rv)                                                        \
00219 __attribute__((always_inline))                                                 \
00220 static inline  t __##f (void) {                                                \
00221   SVC_Arg0();                                                                  \
00222   SVC_Call(f);                                                                 \
00223   return (t) rv;                                                               \
00224 }
00225 
00226 #define SVC_1_1(f,t,t1,rv)                                                     \
00227 __attribute__((always_inline))                                                 \
00228 static inline  t __##f (t1 a1) {                                               \
00229   SVC_Arg1(t1);                                                                \
00230   SVC_Call(f);                                                                 \
00231   return (t) rv;                                                               \
00232 }
00233 
00234 #define SVC_2_1(f,t,t1,t2,rv)                                                  \
00235 __attribute__((always_inline))                                                 \
00236 static inline  t __##f (t1 a1, t2 a2) {                                        \
00237   SVC_Arg2(t1,t2);                                                             \
00238   SVC_Call(f);                                                                 \
00239   return (t) rv;                                                               \
00240 }
00241 
00242 #define SVC_3_1(f,t,t1,t2,t3,rv)                                               \
00243 __attribute__((always_inline))                                                 \
00244 static inline  t __##f (t1 a1, t2 a2, t3 a3) {                                 \
00245   SVC_Arg3(t1,t2,t3);                                                          \
00246   SVC_Call(f);                                                                 \
00247   return (t) rv;                                                               \
00248 }
00249 
00250 #define SVC_4_1(f,t,t1,t2,t3,t4,rv)                                            \
00251 __attribute__((always_inline))                                                 \
00252 static inline  t __##f (t1 a1, t2 a2, t3 a3, t4 a4) {                          \
00253   SVC_Arg4(t1,t2,t3,t4);                                                       \
00254   SVC_Call(f);                                                                 \
00255   return (t) rv;                                                               \
00256 }
00257 
00258 #define SVC_1_2 SVC_1_1 
00259 #define SVC_1_3 SVC_1_1 
00260 #define SVC_2_3 SVC_2_1 
00261 
00262 #elif defined (__ICCARM__)      /* IAR Compiler */
00263 
00264 #define __NO_RETURN __noreturn
00265 
00266 #define RET_osEvent        "=r"(ret.status), "=r"(ret.value), "=r"(ret.def)
00267 #define RET_osCallback     "=r"(ret.fp), "=r"(ret.arg)
00268 
00269 #define osEvent_type       osEvent
00270 #define osEvent_ret_status ret
00271 #define osEvent_ret_value  ret
00272 #define osEvent_ret_msg    ret
00273 #define osEvent_ret_mail   ret
00274 
00275 #define osCallback_type    uint64_t
00276 #define osCallback_ret     ((uint64_t)ret.fp | ((uint64_t)ret.arg)<<32)
00277 
00278 #define SVC_Setup(f)                                                           \
00279   __asm(                                                                         \
00280     "mov r12,%0\n"                                                             \
00281     :: "r"(&f): "r12"                                                          \
00282   );
00283 
00284 #define SVC_Ret3()                                                             \
00285   __asm(                                                                         \
00286     "ldr r0,[sp,#0]\n"                                                         \
00287     "ldr r1,[sp,#4]\n"                                                         \
00288     "ldr r2,[sp,#8]\n"                                                         \
00289   );
00290 
00291 #define SVC_0_1(f,t,...)                                                       \
00292 t f (void);                                                                    \
00293 _Pragma("swi_number=0") __swi t _##f (void);                                   \
00294 static inline t __##f (void) {                                                 \
00295   SVC_Setup(f);                                                                \
00296   return _##f();                                                               \
00297 }
00298 
00299 #define SVC_1_1(f,t,t1,...)                                                    \
00300 t f (t1 a1);                                                                   \
00301 _Pragma("swi_number=0") __swi t _##f (t1 a1);                                  \
00302 static inline t __##f (t1 a1) {                                                \
00303   SVC_Setup(f);                                                                \
00304   return _##f(a1);                                                             \
00305 }
00306 
00307 #define SVC_2_1(f,t,t1,t2,...)                                                 \
00308 t f (t1 a1, t2 a2);                                                            \
00309 _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2);                           \
00310 static inline t __##f (t1 a1, t2 a2) {                                         \
00311   SVC_Setup(f);                                                                \
00312   return _##f(a1,a2);                                                          \
00313 }
00314 
00315 #define SVC_3_1(f,t,t1,t2,t3,...)                                              \
00316 t f (t1 a1, t2 a2, t3 a3);                                                     \
00317 _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3);                    \
00318 static inline t __##f (t1 a1, t2 a2, t3 a3) {                                  \
00319   SVC_Setup(f);                                                                \
00320   return _##f(a1,a2,a3);                                                       \
00321 }
00322 
00323 #define SVC_4_1(f,t,t1,t2,t3,t4,...)                                           \
00324 t f (t1 a1, t2 a2, t3 a3, t4 a4);                                              \
00325 _Pragma("swi_number=0") __swi t _##f (t1 a1, t2 a2, t3 a3, t4 a4);             \
00326 static inline t __##f (t1 a1, t2 a2, t3 a3, t4 a4) {                           \
00327   SVC_Setup(f);                                                                \
00328   return _##f(a1,a2,a3,a4);                                                    \
00329 }
00330 
00331 #define SVC_1_2(f,t,t1,rr)                                                     \
00332 uint64_t f (t1 a1);                                                            \
00333 _Pragma("swi_number=0") __swi uint64_t _##f (t1 a1);                           \
00334 static inline t __##f (t1 a1) {                                                \
00335   t ret;                                                                       \
00336   SVC_Setup(f);                                                                \
00337   _##f(a1);                                                                    \
00338   __asm("" : rr : :);                                                            \
00339   return ret;                                                                  \
00340 }
00341 
00342 #define SVC_1_3(f,t,t1,rr)                                                     \
00343 t f (t1 a1);                                                                   \
00344 void f##_ (t1 a1) {                                                            \
00345   f(a1);                                                                       \
00346   SVC_Ret3();                                                                  \
00347 }                                                                              \
00348 _Pragma("swi_number=0") __swi void _##f (t1 a1);                               \
00349 static inline t __##f (t1 a1) {                                                \
00350   t ret;                                                                       \
00351   SVC_Setup(f##_);                                                             \
00352   _##f(a1);                                                                    \
00353   __asm("" : rr : :);                                                            \
00354   return ret;                                                                  \
00355 }
00356 
00357 #define SVC_2_3(f,t,t1,t2,rr)                                                  \
00358 t f (t1 a1, t2 a2);                                                            \
00359 void f##_ (t1 a1, t2 a2) {                                                     \
00360   f(a1,a2);                                                                    \
00361   SVC_Ret3();                                                                  \
00362 }                                                                              \
00363 _Pragma("swi_number=0") __swi void _##f (t1 a1, t2 a2);                        \
00364 static inline t __##f (t1 a1, t2 a2) {                                         \
00365   t ret;                                                                       \
00366   SVC_Setup(f##_);                                                             \
00367   _##f(a1,a2);                                                                 \
00368   __asm("" : rr : :);                                                            \
00369   return ret;                                                                  \
00370 }
00371 
00372 #endif
00373 
00374 
00375 // Callback structure
00376 typedef struct {
00377   void *fp;             // Function pointer
00378   void *arg;            // Function argument
00379 } osCallback;
00380 
00381 
00382 // OS Section definitions
00383 #ifdef OS_SECTIONS_LINK_INFO
00384 extern const uint32_t  os_section_id$$Base;
00385 extern const uint32_t  os_section_id$$Limit;
00386 #endif
00387 
00388 // OS Timers external resources
00389 extern osThreadDef_t   os_thread_def_osTimerThread;
00390 extern osThreadId      osThreadId_osTimerThread;
00391 extern osMessageQDef_t os_messageQ_def_osTimerMessageQ;
00392 extern osMessageQId    osMessageQId_osTimerMessageQ;
00393 
00394 
00395 // ==== Helper Functions ====
00396 
00397 /// Convert timeout in millisec to system ticks
00398 static uint32_t rt_ms2tick (uint32_t millisec) {
00399   uint32_t tick;
00400 
00401   if (millisec == osWaitForever) return 0xFFFF; // Indefinite timeout
00402   if (millisec > 4000000) return 0xFFFE;        // Max ticks supported
00403 
00404   tick = ((1000 * millisec) + os_clockrate - 1)  / os_clockrate;
00405   if (tick > 0xFFFE) return 0xFFFE;
00406   
00407   return tick;
00408 }
00409 
00410 /// Convert Thread ID to TCB pointer
00411 static P_TCB rt_tid2ptcb (osThreadId thread_id) {
00412   P_TCB ptcb;
00413 
00414   if (thread_id == NULL) return NULL;
00415 
00416   if ((uint32_t)thread_id & 3) return NULL;
00417 
00418 #ifdef OS_SECTIONS_LINK_INFO
00419   if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) {
00420     if (thread_id  < (osThreadId)os_section_id$$Base)  return NULL;
00421     if (thread_id >= (osThreadId)os_section_id$$Limit) return NULL;
00422   }
00423 #endif
00424 
00425   ptcb = thread_id;
00426 
00427   if (ptcb->cb_type != TCB) return NULL;
00428 
00429   return ptcb;
00430 }
00431 
00432 /// Convert ID pointer to Object pointer
00433 static void *rt_id2obj (void *id) {
00434 
00435   if ((uint32_t)id & 3) return NULL;
00436 
00437 #ifdef OS_SECTIONS_LINK_INFO
00438   if ((os_section_id$$Base != 0) && (os_section_id$$Limit != 0)) {
00439     if (id  < (void *)os_section_id$$Base)  return NULL;
00440     if (id >= (void *)os_section_id$$Limit) return NULL;
00441   }
00442 #endif
00443 
00444   return id;
00445 }
00446 
00447 
00448 // ==== Kernel Control ====
00449 
00450 uint8_t os_initialized;                         // Kernel Initialized flag
00451 uint8_t os_running;                             // Kernel Running flag
00452 
00453 // Kernel Control Service Calls declarations
00454 SVC_0_1(svcKernelInitialize, osStatus, RET_osStatus)
00455 SVC_0_1(svcKernelStart,      osStatus, RET_osStatus)
00456 SVC_0_1(svcKernelRunning,    int32_t,  RET_int32_t)
00457 
00458 extern void  sysThreadError   (osStatus status);
00459 osThreadId   svcThreadCreate  (osThreadDef_t *thread_def, void *argument);
00460 osMessageQId svcMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id);
00461 
00462 // Kernel Control Service Calls
00463 
00464 /// Initialize the RTOS Kernel for creating objects
00465 osStatus svcKernelInitialize (void) {
00466   if (os_initialized) return osOK;
00467 
00468   rt_sys_init();                                // RTX System Initialization
00469   os_tsk.run->prio = 255;                       // Highest priority
00470 
00471   sysThreadError(osOK);
00472 
00473   os_initialized = 1;
00474 
00475   return osOK;
00476 }
00477 
00478 /// Start the RTOS Kernel
00479 osStatus svcKernelStart (void) {
00480 
00481   if (os_running) return osOK;
00482 
00483   // Create OS Timers resources (Message Queue & Thread)
00484   osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
00485   osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
00486 
00487   rt_tsk_prio(0, 0);                            // Lowest priority
00488   __set_PSP(os_tsk.run->tsk_stack + 8*4);       // New context
00489   os_tsk.run = NULL;                            // Force context switch
00490 
00491   rt_sys_start();
00492 
00493   os_running = 1;
00494 
00495   return osOK;
00496 }
00497 
00498 /// Check if the RTOS kernel is already started
00499 int32_t svcKernelRunning(void) {
00500   return os_running;
00501 }
00502 
00503 // Kernel Control Public API
00504 
00505 /// Initialize the RTOS Kernel for creating objects
00506 osStatus osKernelInitialize (void) {
00507   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
00508   if ((__get_CONTROL() & 1) == 0) {             // Privileged mode
00509     return   svcKernelInitialize();
00510   } else {
00511     return __svcKernelInitialize();
00512   }
00513 }
00514 
00515 /// Start the RTOS Kernel
00516 osStatus osKernelStart (void) {
00517   uint32_t stack[8];
00518   
00519   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
00520   switch (__get_CONTROL() & 0x03) {
00521     case 0x00:                                  // Privileged Thread mode & MSP
00522       __set_PSP((uint32_t)(stack + 8));         // Initial PSP
00523       if (os_flags & 1) {                       
00524         __set_CONTROL(0x02);                    // Set Privileged Thread mode & PSP
00525       } else {
00526         __set_CONTROL(0x03);                    // Set Unprivileged Thread mode & PSP
00527       }
00528       __DSB();
00529       __ISB();
00530       break;
00531     case 0x01:                                  // Unprivileged Thread mode & MSP
00532       return osErrorOS;
00533     case 0x02:                                  // Privileged Thread mode & PSP
00534       if ((os_flags & 1) == 0) {                // Unprivileged Thread mode requested
00535         __set_CONTROL(0x03);                    // Set Unprivileged Thread mode & PSP
00536         __DSB();
00537         __ISB();
00538       }
00539       break;
00540     case 0x03:                                  // Unprivileged Thread mode & PSP
00541       if  (os_flags & 1) return osErrorOS;      // Privileged Thread mode requested
00542       break;
00543   }
00544   return __svcKernelStart();
00545 }
00546 
00547 /// Check if the RTOS kernel is already started
00548 int32_t osKernelRunning(void) {
00549   if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) {
00550     // in ISR or Privileged
00551     return os_running;
00552   } else {
00553     return __svcKernelRunning();
00554   }
00555 }
00556 
00557 
00558 // ==== Thread Management ====
00559 
00560 __NO_RETURN void osThreadExit (void);
00561 
00562 // Thread Service Calls declarations
00563 SVC_2_1(svcThreadCreate,      osThreadId, osThreadDef_t *, void *,     RET_pointer)
00564 SVC_0_1(svcThreadGetId,       osThreadId,                              RET_pointer)
00565 SVC_1_1(svcThreadTerminate,   osStatus,   osThreadId,                  RET_osStatus)
00566 SVC_0_1(svcThreadYield,       osStatus,                                RET_osStatus)
00567 SVC_2_1(svcThreadSetPriority, osStatus,   osThreadId,      osPriority, RET_osStatus)
00568 SVC_1_1(svcThreadGetPriority, osPriority, osThreadId,                  RET_osPriority)
00569 
00570 // Thread Service Calls
00571 extern OS_TID rt_get_TID (void);
00572 extern void   rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body);
00573 
00574 /// Create a thread and add it to Active Threads and set it to state READY
00575 osThreadId svcThreadCreate (osThreadDef_t *thread_def, void *argument) {
00576   P_TCB  ptcb;
00577   
00578   if ((thread_def == NULL) ||
00579       (thread_def->pthread == NULL) ||
00580       (thread_def->tpriority <= osPriorityIdle) ||
00581       (thread_def->tpriority > osPriorityRealtime) ||
00582       (thread_def->stacksize == 0) ||
00583       (thread_def->stack_pointer == NULL) ) {
00584     sysThreadError(osErrorParameter); 
00585     return NULL; 
00586   }
00587   
00588   U8 priority = thread_def->tpriority - osPriorityIdle + 1;
00589   P_TCB task_context = &thread_def->tcb;
00590   
00591   /* If "size != 0" use a private user provided stack. */
00592   task_context->stack      = (U32*)thread_def->stack_pointer;
00593   task_context->priv_stack = thread_def->stacksize;
00594   /* Pass parameter 'argv' to 'rt_init_context' */
00595   task_context->msg = argument;
00596   /* For 'size == 0' system allocates the user stack from the memory pool. */
00597   rt_init_context (task_context, priority, (FUNCP)thread_def->pthread);
00598 
00599   /* Find a free entry in 'os_active_TCB' table. */
00600   OS_TID tsk = rt_get_TID ();
00601   os_active_TCB[tsk-1] = task_context;
00602   task_context->task_id = tsk;
00603   DBG_TASK_NOTIFY(task_context, __TRUE);
00604   rt_dispatch (task_context);
00605   
00606   ptcb = (P_TCB)os_active_TCB[tsk - 1];         // TCB pointer
00607 
00608   *((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit;
00609 
00610   return ptcb;
00611 }
00612 
00613 /// Return the thread ID of the current running thread
00614 osThreadId svcThreadGetId (void) {
00615   OS_TID tsk;
00616 
00617   tsk = rt_tsk_self();
00618   if (tsk == 0) return NULL;
00619   return (P_TCB)os_active_TCB[tsk - 1];
00620 }
00621 
00622 /// Terminate execution of a thread and remove it from ActiveThreads
00623 osStatus svcThreadTerminate (osThreadId thread_id) {
00624   OS_RESULT res;
00625   P_TCB     ptcb;
00626   
00627   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
00628   if (ptcb == NULL) return osErrorParameter;
00629   
00630   res = rt_tsk_delete(ptcb->task_id);           // Delete task
00631 
00632   if (res == OS_R_NOK) return osErrorResource;  // Delete task failed
00633   
00634   return osOK;
00635 }
00636 
00637 /// Pass control to next thread that is in state READY
00638 osStatus svcThreadYield (void) {
00639   rt_tsk_pass();                                // Pass control to next task
00640   return osOK;
00641 }
00642 
00643 /// Change prority of an active thread
00644 osStatus svcThreadSetPriority (osThreadId thread_id, osPriority priority) {
00645   OS_RESULT res;
00646   P_TCB     ptcb;
00647 
00648   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
00649   if (ptcb == NULL) return osErrorParameter;
00650 
00651   if ((priority < osPriorityIdle) || (priority > osPriorityRealtime)) {
00652     return osErrorValue;
00653   }
00654 
00655   res = rt_tsk_prio(                            // Change task priority
00656     ptcb->task_id,                              // Task ID
00657     priority - osPriorityIdle + 1               // New task priority
00658   );
00659 
00660   if (res == OS_R_NOK) return osErrorResource;  // Change task priority failed
00661 
00662   return osOK;
00663 }
00664 
00665 /// Get current prority of an active thread
00666 osPriority svcThreadGetPriority (osThreadId thread_id) {
00667   P_TCB ptcb;
00668 
00669   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
00670   if (ptcb == NULL) return osPriorityError;
00671 
00672   return (osPriority)(ptcb->prio - 1 + osPriorityIdle); 
00673 }
00674 
00675 
00676 // Thread Public API
00677 
00678 /// Create a thread and add it to Active Threads and set it to state READY
00679 osThreadId osThreadCreate (osThreadDef_t *thread_def, void *argument) {
00680   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
00681   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
00682     // Privileged and not running
00683     return   svcThreadCreate(thread_def, argument);
00684   } else {
00685     return __svcThreadCreate(thread_def, argument);
00686   }
00687 }
00688 
00689 /// Return the thread ID of the current running thread
00690 osThreadId osThreadGetId (void) {
00691   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
00692   return __svcThreadGetId();
00693 }
00694 
00695 /// Terminate execution of a thread and remove it from ActiveThreads
00696 osStatus osThreadTerminate (osThreadId thread_id) {
00697   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
00698   return __svcThreadTerminate(thread_id);
00699 }
00700 
00701 /// Pass control to next thread that is in state READY
00702 osStatus osThreadYield (void) {
00703   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
00704   return __svcThreadYield();
00705 }
00706 
00707 /// Change prority of an active thread
00708 osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) {
00709   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
00710   return __svcThreadSetPriority(thread_id, priority);
00711 }
00712 
00713 /// Get current prority of an active thread
00714 osPriority osThreadGetPriority (osThreadId thread_id) {
00715   if (__get_IPSR() != 0) return osPriorityError;// Not allowed in ISR
00716   return __svcThreadGetPriority(thread_id);
00717 }
00718 
00719 /// INTERNAL - Not Public
00720 /// Auto Terminate Thread on exit (used implicitly when thread exists)
00721 __NO_RETURN void osThreadExit (void) { 
00722   __svcThreadTerminate(__svcThreadGetId()); 
00723   for (;;);                                     // Should never come here
00724 }
00725 
00726 
00727 // ==== Generic Wait Functions ====
00728 
00729 // Generic Wait Service Calls declarations
00730 SVC_1_1(svcDelay,           osStatus, uint32_t, RET_osStatus)
00731 #if osFeature_Wait != 0
00732 SVC_1_3(svcWait,  os_InRegs osEvent,  uint32_t, RET_osEvent)
00733 #endif
00734 
00735 // Generic Wait Service Calls
00736 
00737 /// Wait for Timeout (Time Delay)
00738 osStatus svcDelay (uint32_t millisec) {
00739   if (millisec == 0) return osOK;
00740   rt_dly_wait(rt_ms2tick(millisec));
00741   return osEventTimeout;
00742 }
00743 
00744 /// Wait for Signal, Message, Mail, or Timeout
00745 #if osFeature_Wait != 0
00746 os_InRegs osEvent_type svcWait (uint32_t millisec) {
00747   osEvent ret;
00748 
00749   if (millisec == 0) {
00750     ret.status = osOK;
00751     return osEvent_ret_status;
00752   }
00753 
00754   /* To Do: osEventSignal, osEventMessage, osEventMail */
00755   rt_dly_wait(rt_ms2tick(millisec));
00756   ret.status = osEventTimeout;
00757 
00758   return osEvent_ret_status;
00759 }
00760 #endif
00761 
00762 
00763 // Generic Wait API
00764 
00765 /// Wait for Timeout (Time Delay)
00766 osStatus osDelay (uint32_t millisec) {
00767   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
00768   return __svcDelay(millisec);
00769 }
00770 
00771 /// Wait for Signal, Message, Mail, or Timeout
00772 os_InRegs osEvent osWait (uint32_t millisec) {
00773   osEvent ret;
00774 
00775 #if osFeature_Wait == 0
00776   ret.status = osErrorOS;
00777   return ret;
00778 #else
00779   if (__get_IPSR() != 0) {                      // Not allowed in ISR
00780     ret.status = osErrorISR;
00781     return ret;
00782   }
00783   return __svcWait(millisec);
00784 #endif
00785 }
00786 
00787 
00788 // ==== Timer Management ====
00789 
00790 // Timer definitions
00791 #define osTimerInvalid  0
00792 #define osTimerStopped  1
00793 #define osTimerRunning  2
00794 
00795 // Timer structures 
00796 
00797 typedef struct os_timer_cb_ {                   // Timer Control Block
00798   struct os_timer_cb_ *next;                    // Pointer to next active Timer
00799   uint8_t             state;                    // Timer State
00800   uint8_t              type;                    // Timer Type (Periodic/One-shot)
00801   uint16_t         reserved;                    // Reserved
00802   uint16_t             tcnt;                    // Timer Delay Count
00803   uint16_t             icnt;                    // Timer Initial Count 
00804   void                 *arg;                    // Timer Function Argument
00805   osTimerDef_t       *timer;                    // Pointer to Timer definition
00806 } os_timer_cb;
00807 
00808 // Timer variables
00809 os_timer_cb *os_timer_head;                     // Pointer to first active Timer
00810 
00811 
00812 // Timer Helper Functions
00813 
00814 // Insert Timer into the list sorted by time
00815 static void rt_timer_insert (os_timer_cb *pt, uint32_t tcnt) {
00816   os_timer_cb *p, *prev;
00817 
00818   prev = NULL;
00819   p = os_timer_head;
00820   while (p != NULL) {
00821     if (tcnt < p->tcnt) break;
00822     tcnt -= p->tcnt;
00823     prev = p;
00824     p = p->next;
00825   }
00826   pt->next = p;
00827   pt->tcnt = (uint16_t)tcnt;
00828   if (p != NULL) {
00829     p->tcnt -= pt->tcnt;
00830   }
00831   if (prev != NULL) {
00832     prev->next = pt;
00833   } else {
00834     os_timer_head = pt;
00835   }
00836 }
00837 
00838 // Remove Timer from the list
00839 static int rt_timer_remove (os_timer_cb *pt) {
00840   os_timer_cb *p, *prev;
00841 
00842   prev = NULL;
00843   p = os_timer_head;
00844   while (p != NULL) {
00845     if (p == pt) break;
00846     prev = p;
00847     p = p->next;
00848   }
00849   if (p == NULL) return -1;
00850   if (prev != NULL) {
00851     prev->next = pt->next;
00852   } else {
00853     os_timer_head = pt->next;
00854   }
00855   if (pt->next != NULL) {
00856     pt->next->tcnt += pt->tcnt;
00857   }
00858 
00859   return 0;
00860 }
00861 
00862 
00863 // Timer Service Calls declarations
00864 SVC_3_1(svcTimerCreate,           osTimerId,  osTimerDef_t *, os_timer_type, void *, RET_pointer)
00865 SVC_2_1(svcTimerStart,            osStatus,   osTimerId,      uint32_t,              RET_osStatus)
00866 SVC_1_1(svcTimerStop,             osStatus,   osTimerId,                             RET_osStatus)
00867 SVC_1_1(svcTimerDelete,           osStatus,   osTimerId,                             RET_osStatus)
00868 SVC_1_2(svcTimerCall,   os_InRegs osCallback, osTimerId,                             RET_osCallback)
00869 
00870 // Timer Management Service Calls
00871 
00872 /// Create timer
00873 osTimerId svcTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument) {
00874   os_timer_cb *pt;
00875 
00876   if ((timer_def == NULL) || (timer_def->ptimer == NULL)) {
00877     sysThreadError(osErrorParameter);
00878     return NULL;
00879   }
00880 
00881   pt = timer_def->timer;
00882   if (pt == NULL) {
00883     sysThreadError(osErrorParameter);
00884     return NULL;
00885   }
00886 
00887   if ((type != osTimerOnce) && (type != osTimerPeriodic)) {
00888     sysThreadError(osErrorValue);
00889     return NULL;
00890   }
00891 
00892   if (osThreadId_osTimerThread == NULL) {
00893     sysThreadError(osErrorResource);
00894     return NULL;
00895   }
00896 
00897   if (pt->state != osTimerInvalid){
00898     sysThreadError(osErrorResource);
00899     return NULL;
00900   }
00901 
00902   pt->state = osTimerStopped;
00903   pt->type  =  (uint8_t)type;
00904   pt->arg   = argument;
00905   pt->timer = timer_def;
00906 
00907   return (osTimerId)pt;
00908 }
00909 
00910 /// Start or restart timer
00911 osStatus svcTimerStart (osTimerId timer_id, uint32_t millisec) {
00912   os_timer_cb *pt;
00913   uint32_t     tcnt;
00914 
00915   pt = rt_id2obj(timer_id);
00916   if (pt == NULL) return osErrorParameter;
00917 
00918   tcnt = rt_ms2tick(millisec);
00919   if (tcnt == 0) return osErrorValue;
00920 
00921   switch (pt->state) {
00922     case osTimerRunning:
00923       if (rt_timer_remove(pt) != 0) {
00924         return osErrorResource;
00925       }
00926       break;
00927     case osTimerStopped:
00928       pt->state = osTimerRunning;
00929       pt->icnt  = (uint16_t)tcnt;
00930       break;
00931     default:
00932       return osErrorResource;
00933   }
00934   
00935   rt_timer_insert(pt, tcnt);
00936 
00937   return osOK;
00938 }
00939 
00940 /// Stop timer
00941 osStatus svcTimerStop (osTimerId timer_id) {
00942   os_timer_cb *pt;
00943 
00944   pt = rt_id2obj(timer_id);
00945   if (pt == NULL) return osErrorParameter;
00946 
00947   if (pt->state != osTimerRunning) return osErrorResource;
00948 
00949   pt->state = osTimerStopped;
00950 
00951   if (rt_timer_remove(pt) != 0) {
00952     return osErrorResource;
00953   }
00954 
00955   return osOK;
00956 }
00957 
00958 /// Delete timer
00959 osStatus svcTimerDelete (osTimerId timer_id) {
00960   os_timer_cb *pt;
00961 
00962   pt = rt_id2obj(timer_id);
00963   if (pt == NULL) return osErrorParameter;
00964 
00965   switch (pt->state) {
00966     case osTimerRunning:
00967       rt_timer_remove(pt);
00968       break;
00969     case osTimerStopped:
00970       break;
00971     default:
00972       return osErrorResource;
00973   }
00974 
00975   pt->state = osTimerInvalid;
00976 
00977   return osOK;
00978 }
00979 
00980 /// Get timer callback parameters
00981 os_InRegs osCallback_type svcTimerCall (osTimerId timer_id) {
00982   os_timer_cb *pt;
00983   osCallback   ret;
00984 
00985   pt = rt_id2obj(timer_id);
00986   if (pt == NULL) {
00987     ret.fp  = NULL;
00988     ret.arg = NULL;
00989     return osCallback_ret;
00990   }
00991 
00992   ret.fp  = (void *)pt->timer->ptimer;
00993   ret.arg = pt->arg;
00994 
00995   return osCallback_ret;
00996 }
00997 
00998 static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
00999 
01000 /// Timer Tick (called each SysTick)
01001 void sysTimerTick (void) {
01002   os_timer_cb *pt, *p;
01003 
01004   p = os_timer_head;
01005   if (p == NULL) return;
01006 
01007   p->tcnt--;
01008   while ((p != NULL) && (p->tcnt == 0)) {
01009     pt = p;
01010     p = p->next;
01011     os_timer_head = p;
01012     isrMessagePut(osMessageQId_osTimerMessageQ, (uint32_t)pt, 0);
01013     if (pt->type == osTimerPeriodic) {
01014       rt_timer_insert(pt, pt->icnt);
01015     } else {
01016       pt->state = osTimerStopped;
01017     }
01018   }
01019 }
01020 
01021 
01022 // Timer Management Public API
01023 
01024 /// Create timer
01025 osTimerId osTimerCreate (osTimerDef_t *timer_def, os_timer_type type, void *argument) {
01026   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
01027   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
01028     // Privileged and not running
01029     return   svcTimerCreate(timer_def, type, argument);
01030   } else {
01031     return __svcTimerCreate(timer_def, type, argument);
01032   }
01033 }
01034 
01035 /// Start or restart timer
01036 osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
01037   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01038   return __svcTimerStart(timer_id, millisec);
01039 }
01040 
01041 /// Stop timer
01042 osStatus osTimerStop (osTimerId timer_id) {
01043   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01044   return __svcTimerStop(timer_id);
01045 }
01046 
01047 /// Delete timer
01048 osStatus osTimerDelete (osTimerId timer_id) {
01049   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01050   return __svcTimerDelete(timer_id);
01051 }
01052 
01053 /// INTERNAL - Not Public
01054 /// Get timer callback parameters (used by OS Timer Thread)
01055 os_InRegs osCallback osTimerCall (osTimerId timer_id) { 
01056   return __svcTimerCall(timer_id); 
01057 }
01058 
01059 
01060 // Timer Thread
01061 __NO_RETURN void osTimerThread (void const *argument) {
01062   osCallback cb;
01063   osEvent    evt;
01064 
01065   for (;;) {
01066     evt = osMessageGet(osMessageQId_osTimerMessageQ, osWaitForever);
01067     if (evt.status == osEventMessage) {
01068       cb = osTimerCall(evt.value.p);
01069       if (cb.fp != NULL) {
01070         (*(os_ptimer)cb.fp)(cb.arg);
01071       }
01072     }
01073   }
01074 }
01075 
01076 
01077 // ==== Signal Management ====
01078 
01079 // Signal Service Calls declarations
01080 SVC_2_1(svcSignalSet,             int32_t, osThreadId, int32_t,  RET_int32_t)
01081 SVC_2_1(svcSignalClear,           int32_t, osThreadId, int32_t,  RET_int32_t)
01082 SVC_1_1(svcSignalGet,             int32_t, osThreadId,           RET_int32_t)
01083 SVC_2_3(svcSignalWait,  os_InRegs osEvent, int32_t,    uint32_t, RET_osEvent)
01084 
01085 // Signal Service Calls
01086 
01087 /// Set the specified Signal Flags of an active thread
01088 int32_t svcSignalSet (osThreadId thread_id, int32_t signal) {
01089   P_TCB   ptcb;
01090   int32_t sig;
01091 
01092   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
01093   if (ptcb == NULL) return 0x80000000;
01094 
01095   if (signal & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
01096 
01097   sig = ptcb->events;                           // Previous signal flags
01098 
01099   rt_evt_set(signal, ptcb->task_id);            // Set event flags
01100 
01101   return sig;
01102 }
01103 
01104 /// Clear the specified Signal Flags of an active thread
01105 int32_t svcSignalClear (osThreadId thread_id, int32_t signal) {
01106   P_TCB   ptcb;
01107   int32_t sig;
01108 
01109   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
01110   if (ptcb == NULL) return 0x80000000;
01111 
01112   if (signal & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
01113 
01114   sig = ptcb->events;                           // Previous signal flags
01115 
01116   rt_evt_clr(signal, ptcb->task_id);            // Clear event flags
01117 
01118   return sig;
01119 }
01120 
01121 /// Get Signal Flags status of an active thread
01122 int32_t svcSignalGet (osThreadId thread_id) {
01123   P_TCB ptcb;
01124 
01125   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
01126   if (ptcb == NULL) return 0x80000000;
01127 
01128   return ptcb->events;                          // Return event flags
01129 }
01130 
01131 /// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
01132 os_InRegs osEvent_type svcSignalWait (int32_t signals, uint32_t millisec) {
01133   OS_RESULT res;
01134   osEvent   ret;
01135 
01136   if (signals & (0xFFFFFFFF << osFeature_Signals)) {
01137     ret.status = osErrorValue;
01138     return osEvent_ret_status;
01139   }
01140 
01141   if (signals != 0) {                           // Wait for all specified signals
01142     res = rt_evt_wait(signals, rt_ms2tick(millisec), __TRUE);
01143   } else {                                      // Wait for any signal
01144     res = rt_evt_wait(0xFFFF,  rt_ms2tick(millisec), __FALSE);
01145   }
01146 
01147   if (res == OS_R_EVT) {
01148     ret.status = osEventSignal;
01149     ret.value.signals = signals ? signals : os_tsk.run->waits;
01150   } else {
01151     ret.status = millisec ? osEventTimeout : osOK;
01152     ret.value.signals = 0;
01153   }
01154 
01155   return osEvent_ret_value;
01156 }
01157 
01158 
01159 // Signal ISR Calls
01160 
01161 /// Set the specified Signal Flags of an active thread
01162 static __INLINE int32_t isrSignalSet (osThreadId thread_id, int32_t signal) {
01163   P_TCB   ptcb;
01164   int32_t sig;
01165 
01166   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
01167   if (ptcb == NULL) return 0x80000000;
01168 
01169   if (signal & (0xFFFFFFFF << osFeature_Signals)) return 0x80000000;
01170 
01171   sig = ptcb->events;                           // Previous signal flags
01172 
01173   isr_evt_set(signal, ptcb->task_id);           // Set event flags
01174 
01175   return sig;
01176 }
01177 
01178 
01179 // Signal Public API
01180 
01181 /// Set the specified Signal Flags of an active thread
01182 int32_t osSignalSet (osThreadId thread_id, int32_t signal) {
01183   if (__get_IPSR() != 0) {                      // in ISR
01184     return   isrSignalSet(thread_id, signal); 
01185   } else {                                      // in Thread
01186     return __svcSignalSet(thread_id, signal);
01187   }
01188 }
01189 
01190 /// Clear the specified Signal Flags of an active thread
01191 int32_t osSignalClear (osThreadId thread_id, int32_t signal) {
01192   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01193   return __svcSignalClear(thread_id, signal);
01194 }
01195 
01196 /// Get Signal Flags status of an active thread
01197 int32_t osSignalGet (osThreadId thread_id) {
01198   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01199   return __svcSignalGet(thread_id);
01200 }
01201 
01202 /// Wait for one or more Signal Flags to become signaled for the current RUNNING thread
01203 os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
01204   osEvent ret;
01205 
01206   if (__get_IPSR() != 0) {                      // Not allowed in ISR
01207     ret.status = osErrorISR;
01208     return ret;
01209   }
01210   return __svcSignalWait(signals, millisec);
01211 }
01212 
01213 
01214 // ==== Mutex Management ====
01215 
01216 // Mutex Service Calls declarations
01217 SVC_1_1(svcMutexCreate,  osMutexId, osMutexDef_t *,           RET_pointer)
01218 SVC_2_1(svcMutexWait,    osStatus,  osMutexId,      uint32_t, RET_osStatus)
01219 SVC_1_1(svcMutexRelease, osStatus,  osMutexId,                RET_osStatus)
01220 SVC_1_1(svcMutexDelete,  osStatus,  osMutexId,                RET_osStatus)
01221 
01222 // Mutex Service Calls
01223 
01224 /// Create and Initialize a Mutex object
01225 osMutexId svcMutexCreate (osMutexDef_t *mutex_def) {
01226   OS_ID mut;
01227 
01228   if (mutex_def == NULL) {
01229     sysThreadError(osErrorParameter);
01230     return NULL;
01231   }
01232 
01233   mut = mutex_def->mutex;
01234   if (mut == NULL) {
01235     sysThreadError(osErrorParameter);
01236     return NULL;
01237   }
01238 
01239   if (((P_MUCB)mut)->cb_type != 0) {
01240     sysThreadError(osErrorParameter);
01241     return NULL;
01242   }
01243 
01244   rt_mut_init(mut);                             // Initialize Mutex
01245 
01246   return mut;
01247 }
01248 
01249 /// Wait until a Mutex becomes available
01250 osStatus svcMutexWait (osMutexId mutex_id, uint32_t millisec) {
01251   OS_ID     mut;
01252   OS_RESULT res;
01253 
01254   mut = rt_id2obj(mutex_id);
01255   if (mut == NULL) return osErrorParameter;
01256 
01257   if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
01258 
01259   res = rt_mut_wait(mut, rt_ms2tick(millisec)); // Wait for Mutex
01260 
01261   if (res == OS_R_TMO) {
01262     return (millisec ? osErrorTimeoutResource : osErrorResource);
01263   }
01264 
01265   return osOK;
01266 }
01267 
01268 /// Release a Mutex that was obtained with osMutexWait
01269 osStatus svcMutexRelease (osMutexId mutex_id) {
01270   OS_ID     mut;
01271   OS_RESULT res;
01272 
01273   mut = rt_id2obj(mutex_id);
01274   if (mut == NULL) return osErrorParameter;
01275 
01276   if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
01277 
01278   res = rt_mut_release(mut);                    // Release Mutex
01279 
01280   if (res == OS_R_NOK) return osErrorResource;  // Thread not owner or Zero Counter
01281 
01282   return osOK;
01283 }
01284 
01285 /// Delete a Mutex that was created by osMutexCreate
01286 osStatus svcMutexDelete (osMutexId mutex_id) {
01287   OS_ID mut;
01288 
01289   mut = rt_id2obj(mutex_id);
01290   if (mut == NULL) return osErrorParameter;
01291 
01292   if (((P_MUCB)mut)->cb_type != MUCB) return osErrorParameter;
01293 
01294   rt_mut_delete(mut);                           // Release Mutex
01295 
01296   return osOK;
01297 }
01298 
01299 
01300 // Mutex Public API
01301 
01302 /// Create and Initialize a Mutex object
01303 osMutexId osMutexCreate (osMutexDef_t *mutex_def) {
01304   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
01305   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
01306     // Privileged and not running
01307     return    svcMutexCreate(mutex_def);
01308   } else {
01309     return __svcMutexCreate(mutex_def);
01310   }
01311 }
01312 
01313 /// Wait until a Mutex becomes available
01314 osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
01315   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01316   return __svcMutexWait(mutex_id, millisec);
01317 }
01318 
01319 /// Release a Mutex that was obtained with osMutexWait
01320 osStatus osMutexRelease (osMutexId mutex_id) {
01321   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01322   return __svcMutexRelease(mutex_id);
01323 }
01324 
01325 /// Delete a Mutex that was created by osMutexCreate
01326 osStatus osMutexDelete (osMutexId mutex_id) {
01327   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01328   return __svcMutexDelete(mutex_id);
01329 }
01330 
01331 
01332 // ==== Semaphore Management ====
01333 
01334 // Semaphore Service Calls declarations
01335 SVC_2_1(svcSemaphoreCreate,  osSemaphoreId, const osSemaphoreDef_t *,  int32_t, RET_pointer)
01336 SVC_2_1(svcSemaphoreWait,    int32_t,       osSemaphoreId,      uint32_t, RET_int32_t)
01337 SVC_1_1(svcSemaphoreRelease, osStatus,      osSemaphoreId,                RET_osStatus)
01338 SVC_1_1(svcSemaphoreDelete,  osStatus,            osSemaphoreId,                RET_osStatus)
01339 
01340 // Semaphore Service Calls
01341 
01342 /// Create and Initialize a Semaphore object
01343 osSemaphoreId svcSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
01344   OS_ID sem;
01345 
01346   if (semaphore_def == NULL) {
01347     sysThreadError(osErrorParameter);
01348     return NULL;
01349   }
01350 
01351   sem = semaphore_def->semaphore;
01352   if (sem == NULL) {
01353     sysThreadError(osErrorParameter);
01354     return NULL;
01355   }
01356 
01357   if (((P_SCB)sem)->cb_type != 0) {
01358     sysThreadError(osErrorParameter);
01359     return NULL;
01360   }
01361 
01362   if (count > osFeature_Semaphore) {
01363     sysThreadError(osErrorValue);
01364     return NULL;
01365   }
01366 
01367   rt_sem_init(sem, count);                      // Initialize Semaphore
01368   
01369   return sem;
01370 }
01371 
01372 /// Wait until a Semaphore becomes available
01373 int32_t svcSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
01374   OS_ID     sem;
01375   OS_RESULT res;
01376 
01377   sem = rt_id2obj(semaphore_id);
01378   if (sem == NULL) return -1;
01379 
01380   if (((P_SCB)sem)->cb_type != SCB) return -1;
01381 
01382   res = rt_sem_wait(sem, rt_ms2tick(millisec)); // Wait for Semaphore
01383 
01384   if (res == OS_R_TMO) return 0;                // Timeout
01385 
01386   return (((P_SCB)sem)->tokens + 1);
01387 }
01388 
01389 /// Release a Semaphore
01390 osStatus svcSemaphoreRelease (osSemaphoreId semaphore_id) {
01391   OS_ID sem;
01392 
01393   sem = rt_id2obj(semaphore_id);
01394   if (sem == NULL) return osErrorParameter;
01395 
01396   if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
01397 
01398   rt_sem_send(sem);                             // Release Semaphore
01399 
01400   return osOK;
01401 }
01402 
01403 /// Delete a Semaphore that was created by osSemaphoreCreate
01404 osStatus svcSemaphoreDelete (osSemaphoreId semaphore_id) {
01405   OS_ID sem;
01406 
01407   sem = rt_id2obj(semaphore_id);
01408   if (sem == NULL) return osErrorParameter;
01409 
01410   if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
01411 
01412   rt_sem_delete(sem);                           // Delete Semaphore
01413 
01414   return osOK;
01415 }
01416 
01417 
01418 // Semaphore ISR Calls
01419 
01420 /// Release a Semaphore
01421 static __INLINE osStatus isrSemaphoreRelease (osSemaphoreId semaphore_id) {
01422   OS_ID sem;
01423 
01424   sem = rt_id2obj(semaphore_id);
01425   if (sem == NULL) return osErrorParameter;
01426 
01427   if (((P_SCB)sem)->cb_type != SCB) return osErrorParameter;
01428 
01429   isr_sem_send(sem);                            // Release Semaphore
01430 
01431   return osOK;
01432 }
01433 
01434 
01435 // Semaphore Public API
01436 
01437 /// Create and Initialize a Semaphore object
01438 osSemaphoreId osSemaphoreCreate (osSemaphoreDef_t *semaphore_def, int32_t count) {
01439   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
01440   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
01441     // Privileged and not running
01442     return   svcSemaphoreCreate(semaphore_def, count);
01443   } else {
01444     return __svcSemaphoreCreate(semaphore_def, count);
01445   }
01446 }
01447 
01448 /// Wait until a Semaphore becomes available
01449 int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
01450   if (__get_IPSR() != 0) return -1;             // Not allowed in ISR
01451   return __svcSemaphoreWait(semaphore_id, millisec);
01452 }
01453 
01454 /// Release a Semaphore
01455 osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
01456   if (__get_IPSR() != 0) {                      // in ISR
01457     return   isrSemaphoreRelease(semaphore_id);
01458   } else {                                      // in Thread
01459     return __svcSemaphoreRelease(semaphore_id);
01460   }
01461 }
01462 
01463 /// Delete a Semaphore that was created by osSemaphoreCreate
01464 osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
01465   if (__get_IPSR() != 0) return osErrorISR;     // Not allowed in ISR
01466   return __svcSemaphoreDelete(semaphore_id);
01467 }
01468 
01469 
01470 // ==== Memory Management Functions ====
01471 
01472 // Memory Management Helper Functions
01473 
01474 // Clear Memory Box (Zero init)
01475 static void rt_clr_box (void *box_mem, void *box) {
01476   uint32_t *p, n;
01477 
01478   if (box) {
01479     p = box;
01480     for (n = ((P_BM)box_mem)->blk_size; n; n -= 4) {
01481       *p++ = 0;
01482     }
01483   }
01484 }
01485 
01486 // Memory Management Service Calls declarations
01487 SVC_1_1(svcPoolCreate, osPoolId, const osPoolDef_t *,           RET_pointer)
01488 SVC_2_1(sysPoolAlloc,  void *,   osPoolId,      uint32_t, RET_pointer)
01489 SVC_2_1(sysPoolFree,   osStatus, osPoolId,      void *,   RET_osStatus)
01490 
01491 // Memory Management Service & ISR Calls
01492 
01493 /// Create and Initialize memory pool
01494 osPoolId svcPoolCreate (const osPoolDef_t *pool_def) {
01495   uint32_t blk_sz;
01496 
01497   if ((pool_def == NULL) ||
01498       (pool_def->pool_sz == 0) ||
01499       (pool_def->item_sz == 0) ||
01500       (pool_def->pool == NULL)) {
01501     sysThreadError(osErrorParameter);
01502     return NULL;
01503   }
01504 
01505   blk_sz = (pool_def->item_sz + 3) & ~3;
01506 
01507   _init_box(pool_def->pool, sizeof(struct OS_BM) + pool_def->pool_sz * blk_sz, blk_sz);
01508 
01509   return pool_def->pool;
01510 }
01511 
01512 /// Allocate a memory block from a memory pool
01513 void *sysPoolAlloc (osPoolId pool_id, uint32_t clr) {
01514   void *ptr;
01515 
01516   if (pool_id == NULL) return NULL;
01517 
01518   ptr = rt_alloc_box(pool_id);
01519   if (clr) {
01520     rt_clr_box(pool_id, ptr);
01521   }
01522 
01523   return ptr;
01524 }
01525 
01526 /// Return an allocated memory block back to a specific memory pool
01527 osStatus sysPoolFree (osPoolId pool_id, void *block) {
01528   int32_t res;
01529     
01530   if (pool_id == NULL) return osErrorParameter;
01531 
01532   res = rt_free_box(pool_id, block);
01533   if (res != 0) return osErrorValue;
01534 
01535   return osOK;
01536 }
01537 
01538 
01539 // Memory Management Public API
01540 
01541 /// Create and Initialize memory pool
01542 osPoolId osPoolCreate (osPoolDef_t *pool_def) {
01543   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
01544   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
01545     // Privileged and not running
01546     return   svcPoolCreate(pool_def);
01547   } else {
01548     return __svcPoolCreate(pool_def);
01549   }
01550 }
01551 
01552 /// Allocate a memory block from a memory pool
01553 void *osPoolAlloc (osPoolId pool_id) {
01554   if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) {    // in ISR or Privileged
01555     return   sysPoolAlloc(pool_id, 0);
01556   } else {                                      // in Thread
01557     return __sysPoolAlloc(pool_id, 0);
01558   }
01559 }
01560 
01561 /// Allocate a memory block from a memory pool and set memory block to zero
01562 void *osPoolCAlloc (osPoolId pool_id) {
01563   if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) {    // in ISR or Privileged
01564     return   sysPoolAlloc(pool_id, 1);
01565   } else {                                      // in Thread
01566     return __sysPoolAlloc(pool_id, 1);
01567   }
01568 }
01569 
01570 /// Return an allocated memory block back to a specific memory pool
01571 osStatus osPoolFree (osPoolId pool_id, void *block) {
01572   if ((__get_IPSR() != 0) || ((__get_CONTROL() & 1) == 0)) {    // in ISR or Privileged
01573     return   sysPoolFree(pool_id, block);
01574   } else {                                      // in Thread
01575     return __sysPoolFree(pool_id, block);
01576   }
01577 }
01578 
01579 
01580 // ==== Message Queue Management Functions ====
01581 
01582 // Message Queue Management Service Calls declarations
01583 SVC_2_1(svcMessageCreate,        osMessageQId,    osMessageQDef_t *, osThreadId,           RET_pointer)
01584 SVC_3_1(svcMessagePut,              osStatus,     osMessageQId,      uint32_t,   uint32_t, RET_osStatus)
01585 SVC_2_3(svcMessageGet,    os_InRegs osEvent,      osMessageQId,      uint32_t,             RET_osEvent)
01586 
01587 // Message Queue Service Calls
01588 
01589 /// Create and Initialize Message Queue
01590 osMessageQId svcMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id) {
01591 
01592   if ((queue_def == NULL) ||
01593       (queue_def->queue_sz == 0) ||
01594       (queue_def->pool == NULL)) {
01595     sysThreadError(osErrorParameter);
01596     return NULL;
01597   }
01598   
01599   if (((P_MCB)queue_def->pool)->cb_type != 0) {
01600     sysThreadError(osErrorParameter);
01601     return NULL;
01602   }
01603 
01604   rt_mbx_init(queue_def->pool, 4*(queue_def->queue_sz + 4));
01605 
01606   return queue_def->pool;
01607 }
01608 
01609 /// Put a Message to a Queue
01610 osStatus svcMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
01611   OS_RESULT res;
01612 
01613   if (queue_id == NULL) return osErrorParameter;
01614 
01615   if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter;
01616 
01617   res = rt_mbx_send(queue_id, (void *)info, rt_ms2tick(millisec));
01618 
01619   if (res == OS_R_TMO) {
01620     return (millisec ? osErrorTimeoutResource : osErrorResource);
01621   }
01622 
01623   return osOK;
01624 }
01625 
01626 /// Get a Message or Wait for a Message from a Queue
01627 os_InRegs osEvent_type svcMessageGet (osMessageQId queue_id, uint32_t millisec) {
01628   OS_RESULT res;
01629   osEvent   ret;
01630 
01631   if (queue_id == NULL) {
01632     ret.status = osErrorParameter;
01633     return osEvent_ret_status;
01634   }
01635 
01636   if (((P_MCB)queue_id)->cb_type != MCB) {
01637     ret.status = osErrorParameter;
01638     return osEvent_ret_status;
01639   }
01640 
01641   res = rt_mbx_wait(queue_id, &ret.value.p, rt_ms2tick(millisec));
01642   
01643   if (res == OS_R_TMO) {
01644     ret.status = millisec ? osEventTimeout : osOK;
01645     return osEvent_ret_value;
01646   }
01647 
01648   ret.status = osEventMessage;
01649 
01650   return osEvent_ret_value;
01651 }
01652 
01653 
01654 // Message Queue ISR Calls
01655 
01656 /// Put a Message to a Queue
01657 static __INLINE osStatus isrMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
01658 
01659   if ((queue_id == NULL) || (millisec != 0)) {
01660     return osErrorParameter;
01661   }
01662 
01663   if (((P_MCB)queue_id)->cb_type != MCB) return osErrorParameter;
01664 
01665   if (rt_mbx_check(queue_id) == 0) {            // Check if Queue is full
01666     return osErrorResource;
01667   }
01668 
01669   isr_mbx_send(queue_id, (void *)info);
01670 
01671   return osOK;
01672 }
01673 
01674 /// Get a Message or Wait for a Message from a Queue
01675 static __INLINE os_InRegs osEvent isrMessageGet (osMessageQId queue_id, uint32_t millisec) {
01676   OS_RESULT res;
01677   osEvent   ret;
01678 
01679   if ((queue_id == NULL) || (millisec != 0)) {
01680     ret.status = osErrorParameter;
01681     return ret;
01682   }
01683 
01684   if (((P_MCB)queue_id)->cb_type != MCB) {
01685     ret.status = osErrorParameter;
01686     return ret;
01687   }
01688 
01689   res = isr_mbx_receive(queue_id, &ret.value.p);
01690   
01691   if (res != OS_R_MBX) {
01692     ret.status = osOK;
01693     return ret;
01694   }
01695 
01696   ret.status = osEventMessage; 
01697 
01698   return ret;
01699 }
01700 
01701 
01702 // Message Queue Management Public API
01703 
01704 /// Create and Initialize Message Queue
01705 osMessageQId osMessageCreate (osMessageQDef_t *queue_def, osThreadId thread_id) {
01706   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
01707   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
01708     // Privileged and not running
01709     return   svcMessageCreate(queue_def, thread_id);
01710   } else {
01711     return __svcMessageCreate(queue_def, thread_id);
01712   }
01713 }
01714 
01715 /// Put a Message to a Queue
01716 osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
01717   if (__get_IPSR() != 0) {                      // in ISR
01718     return   isrMessagePut(queue_id, info, millisec);
01719   } else {                                      // in Thread
01720     return __svcMessagePut(queue_id, info, millisec);
01721   }
01722 }
01723 
01724 /// Get a Message or Wait for a Message from a Queue
01725 os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
01726   if (__get_IPSR() != 0) {                      // in ISR
01727     return   isrMessageGet(queue_id, millisec);
01728   } else {                                      // in Thread
01729     return __svcMessageGet(queue_id, millisec);
01730   }
01731 }
01732 
01733 
01734 // ==== Mail Queue Management Functions ====
01735 
01736 // Mail Queue Management Service Calls declarations
01737 SVC_2_1(svcMailCreate, osMailQId, osMailQDef_t *, osThreadId,                   RET_pointer)
01738 SVC_4_1(sysMailAlloc,  void *,    osMailQId,      uint32_t, uint32_t, uint32_t, RET_pointer)
01739 SVC_3_1(sysMailFree,   osStatus,  osMailQId,      void *,   uint32_t,           RET_osStatus)
01740 
01741 // Mail Queue Management Service & ISR Calls
01742 
01743 /// Create and Initialize mail queue
01744 osMailQId svcMailCreate (osMailQDef_t *queue_def, osThreadId thread_id) {
01745   uint32_t blk_sz;
01746   P_MCB    pmcb;
01747   void    *pool;
01748 
01749   if ((queue_def == NULL) ||
01750       (queue_def->queue_sz == 0) ||
01751       (queue_def->item_sz  == 0) ||
01752       (queue_def->pool == NULL)) {
01753     sysThreadError(osErrorParameter);
01754     return NULL;
01755   }
01756 
01757   pmcb = *(((void **)queue_def->pool) + 0);
01758   pool = *(((void **)queue_def->pool) + 1);
01759 
01760   if ((pool == NULL) || (pmcb == NULL) || (pmcb->cb_type != 0)) {
01761     sysThreadError(osErrorParameter);
01762     return NULL;
01763   }
01764 
01765   blk_sz = (queue_def->item_sz + 3) & ~3;
01766 
01767   _init_box(pool, sizeof(struct OS_BM) + queue_def->queue_sz * blk_sz, blk_sz);
01768 
01769   rt_mbx_init(pmcb, 4*(queue_def->queue_sz + 4));
01770 
01771 
01772   return queue_def->pool;
01773 }
01774 
01775 /// Allocate a memory block from a mail
01776 void *sysMailAlloc (osMailQId queue_id, uint32_t millisec, uint32_t isr, uint32_t clr) {
01777   P_MCB pmcb;
01778   void *pool;
01779   void *mem;
01780 
01781   if (queue_id == NULL) return NULL;
01782 
01783   pmcb = *(((void **)queue_id) + 0);
01784   pool = *(((void **)queue_id) + 1);
01785 
01786   if ((pool == NULL) || (pmcb == NULL)) return NULL;
01787 
01788   if (isr && (millisec != 0)) return NULL;
01789 
01790   mem = rt_alloc_box(pool);
01791   if (clr) {
01792     rt_clr_box(pool, mem);
01793   }
01794 
01795   if ((mem == NULL) && (millisec != 0)) {
01796     // Put Task to sleep when Memory not available
01797     if (pmcb->p_lnk != NULL) {
01798       rt_put_prio((P_XCB)pmcb, os_tsk.run);
01799     } else {
01800       pmcb->p_lnk = os_tsk.run;
01801       os_tsk.run->p_lnk = NULL;
01802       os_tsk.run->p_rlnk = (P_TCB)pmcb;
01803       // Task is waiting to allocate a message
01804       pmcb->state = 3;
01805     }
01806     rt_block(rt_ms2tick(millisec), WAIT_MBX);
01807   }
01808 
01809   return mem;  
01810 }
01811 
01812 /// Free a memory block from a mail
01813 osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
01814   P_MCB   pmcb;
01815   P_TCB   ptcb;
01816   void   *pool;
01817   void   *mem;
01818   int32_t res;
01819 
01820   if (queue_id == NULL) return osErrorParameter;
01821 
01822   pmcb = *(((void **)queue_id) + 0);
01823   pool = *(((void **)queue_id) + 1);
01824 
01825   if ((pmcb == NULL) || (pool == NULL)) return osErrorParameter;
01826 
01827   res = rt_free_box(pool, mail);
01828 
01829   if (res != 0) return osErrorValue;
01830 
01831   if (pmcb->state == 3) {
01832     // Task is waiting to allocate a message
01833     if (isr) {
01834       rt_psq_enq (pmcb, (U32)pool);
01835       rt_psh_req ();
01836     } else {
01837       mem = rt_alloc_box(pool);
01838       if (mem != NULL) {
01839         ptcb = rt_get_first((P_XCB)pmcb);
01840         if (pmcb->p_lnk == NULL) {
01841           pmcb->state = 0;
01842         }
01843         rt_ret_val(ptcb, (U32)mem);
01844         rt_rmv_dly(ptcb);
01845         rt_dispatch(ptcb);
01846       }
01847     }
01848   }
01849 
01850   return osOK;
01851 }
01852 
01853 
01854 // Mail Queue Management Public API
01855 
01856 /// Create and Initialize mail queue
01857 osMailQId osMailCreate (osMailQDef_t *queue_def, osThreadId thread_id) {
01858   if (__get_IPSR() != 0) return NULL;           // Not allowed in ISR
01859   if (((__get_CONTROL() & 1) == 0) && (os_running == 0)) {
01860     // Privileged and not running
01861     return   svcMailCreate(queue_def, thread_id);
01862   } else {
01863     return __svcMailCreate(queue_def, thread_id);
01864   }
01865 }
01866 
01867 /// Allocate a memory block from a mail
01868 void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
01869   if (__get_IPSR() != 0) {                      // in ISR
01870     return   sysMailAlloc(queue_id, millisec, 1, 0);
01871   } else {                                      // in Thread
01872     return __sysMailAlloc(queue_id, millisec, 0, 0);
01873   }
01874 }
01875 
01876 /// Allocate a memory block from a mail and set memory block to zero
01877 void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
01878   if (__get_IPSR() != 0) {                      // in ISR
01879     return   sysMailAlloc(queue_id, millisec, 1, 1);
01880   } else {                                      // in Thread
01881     return __sysMailAlloc(queue_id, millisec, 0, 1);
01882   }
01883 }
01884 
01885 /// Free a memory block from a mail
01886 osStatus osMailFree (osMailQId queue_id, void *mail) {
01887   if (__get_IPSR() != 0) {                      // in ISR
01888     return   sysMailFree(queue_id, mail, 1);
01889   } else {                                      // in Thread
01890     return __sysMailFree(queue_id, mail, 0);
01891   }
01892 }
01893 
01894 /// Put a mail to a queue
01895 osStatus osMailPut (osMailQId queue_id, void *mail) {
01896   if (queue_id == NULL) return osErrorParameter;
01897   return osMessagePut(*((void **)queue_id), (uint32_t)mail, 0);
01898 }
01899 
01900 /// Get a mail from a queue
01901 os_InRegs osEvent osMailGet (osMailQId queue_id, uint32_t millisec) {
01902   osEvent ret;
01903 
01904   if (queue_id == NULL) {
01905     ret.status = osErrorParameter;
01906     return ret;
01907   }
01908 
01909   ret = osMessageGet(*((void **)queue_id), millisec);
01910   if (ret.status == osEventMessage) ret.status = osEventMail;
01911 
01912   return ret;
01913 }