Greg Steiert / maxim_dev

Dependents:   sensomed

Committer:
switches
Date:
Tue Nov 08 18:27:11 2016 +0000
Revision:
0:0e018d759a2a
Initial commit

Who changed what in which revision?

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