Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed Socket lwip-eth lwip-sys lwip
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 }
Generated on Tue Jul 12 2022 19:57:00 by
