Quick and dirty port of scmRTOS demo to mbed 1768. scmRTOS is a small RTOS written using C++. Offers (static) processes, critical sections, mutexes, messages, channels.
OS_Kernel.h
00001 //****************************************************************************** 00002 //* 00003 //* FULLNAME: Single-Chip Microcontroller Real-Time Operating System 00004 //* 00005 //* NICKNAME: scmRTOS 00006 //* 00007 //* PURPOSE: OS Kernel Header. Declarations And Definitions 00008 //* 00009 //* Version: 3.10 00010 //* 00011 //* $Revision: 256 $ 00012 //* $Date:: 2010-01-22 #$ 00013 //* 00014 //* Copyright (c) 2003-2010, Harry E. Zhurov 00015 //* 00016 //* Permission is hereby granted, free of charge, to any person 00017 //* obtaining a copy of this software and associated documentation 00018 //* files (the "Software"), to deal in the Software without restriction, 00019 //* including without limitation the rights to use, copy, modify, merge, 00020 //* publish, distribute, sublicense, and/or sell copies of the Software, 00021 //* and to permit persons to whom the Software is furnished to do so, 00022 //* subject to the following conditions: 00023 //* 00024 //* The above copyright notice and this permission notice shall be included 00025 //* in all copies or substantial portions of the Software. 00026 //* 00027 //* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00028 //* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00029 //* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00030 //* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 00031 //* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 00032 //* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 00033 //* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00034 //* 00035 //* ================================================================= 00036 //* See http://scmrtos.sourceforge.net for documentation, latest 00037 //* information, license and contact details. 00038 //* ================================================================= 00039 //* 00040 //***************************************************************************** 00041 00042 #ifndef OS_KERNEL_H 00043 #define OS_KERNEL_H 00044 00045 #include <stddef.h> 00046 #include <commdefs.h> 00047 #include <usrlib.h> 00048 00049 //------------------------------------------------------------------------------ 00050 00051 //============================================================================== 00052 extern "C" void OS_Start(TStackItem* sp); 00053 00054 #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 00055 extern "C" void OS_ContextSwitcher(TStackItem** Curr_SP, TStackItem* Next_SP); 00056 #else 00057 extern "C" TStackItem* OS_ContextSwitchHook(TStackItem* sp); 00058 #endif 00059 00060 //============================================================================== 00061 00062 //------------------------------------------------------------------------------ 00063 // 00064 // 00065 // NAME : OS 00066 // 00067 // PURPOSE : Namespace for all OS stuff 00068 // 00069 // DESCRIPTION: Includes: Kernel, 00070 // Processes, 00071 // Mutexes, 00072 // Event Flags, 00073 // Byte-wide Channels, 00074 // Arbitrary-type Channels, 00075 // Messages 00076 // 00077 namespace OS 00078 { 00079 class TBaseProcess; 00080 00081 INLINE inline void SetPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm |= PrioTag; } 00082 INLINE inline void ClrPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm &= ~PrioTag; } 00083 00084 //-------------------------------------------------------------------------- 00085 // 00086 // NAME : TKernel 00087 // 00088 /// Implements kernel-level operations such as 00089 /// process management, process-level scheduling, 00090 /// ISR-level scheduling, system timing. 00091 // 00092 // DESCRIPTION: 00093 // 00094 // 00095 class TKernel 00096 { 00097 //----------------------------------------------------------- 00098 // 00099 // Declarations 00100 // 00101 00102 00103 friend class TISRW; 00104 friend class TISRW_SS; 00105 friend class TBaseProcess; 00106 friend class TMutex; 00107 friend class TEventFlag; 00108 friend class TChannel; 00109 friend class TBaseMessage; 00110 00111 template<typename T, word size, class S> friend class channel; 00112 template<typename T> friend class message; 00113 00114 friend void Run(); 00115 friend void WakeUpProcess(TBaseProcess& p); 00116 friend void ForceWakeUpProcess(TBaseProcess& p); 00117 friend inline bool IsProcessSleeping(const TBaseProcess& p); 00118 friend inline bool IsProcessSuspended(const TBaseProcess& p); 00119 friend inline dword GetTickCount(); 00120 00121 //----------------------------------------------------------- 00122 // 00123 // Data 00124 // 00125 private: 00126 byte CurProcPriority; 00127 TProcessMap ReadyProcessMap; 00128 TBaseProcess* ProcessTable[scmRTOS_PROCESS_COUNT+1]; 00129 volatile byte ISR_NestCount; 00130 00131 #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 00132 byte SchedProcPriority; 00133 #endif 00134 00135 #if scmRTOS_SYSTEM_TICKS_ENABLE == 1 00136 volatile dword SysTickCount; 00137 #endif 00138 00139 //----------------------------------------------------------- 00140 // 00141 // Functions 00142 // 00143 public: 00144 INLINE TKernel() 00145 : CurProcPriority(pr0) 00146 , ReadyProcessMap( (1 << (scmRTOS_PROCESS_COUNT + 1)) - 1) // set all processes ready 00147 , ISR_NestCount(0) 00148 { 00149 } 00150 00151 private: 00152 INLINE inline void RegisterProcess(TBaseProcess* const p); 00153 00154 void Sched(); 00155 INLINE void Scheduler() { if(ISR_NestCount) return; else Sched(); } 00156 INLINE inline void SchedISR(); 00157 00158 #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 00159 INLINE inline bool IsContextSwitchDone() const volatile; 00160 #endif 00161 INLINE void SetProcessReady (const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); SetPrioTag( ReadyProcessMap, PrioTag); } 00162 INLINE void SetProcessUnready(const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); ClrPrioTag( ReadyProcessMap, PrioTag); } 00163 00164 public: 00165 INLINE inline void SystemTimer(); 00166 #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1 00167 INLINE inline TStackItem* ContextSwitchHook(TStackItem* sp); 00168 #endif 00169 00170 }; // End of TKernel class definition 00171 //-------------------------------------------------------------------------- 00172 extern TKernel Kernel; 00173 00174 //-------------------------------------------------------------------------- 00175 // 00176 /// BaseProcess 00177 /// 00178 /// Implements base class-type for application processes 00179 // 00180 // DESCRIPTION: 00181 // 00182 // 00183 class TBaseProcess 00184 { 00185 friend class TKernel; 00186 friend class TISRW; 00187 friend class TISRW_SS; 00188 friend class TEventFlag; 00189 friend class TMutex; 00190 friend class TBaseMessage; 00191 00192 template<typename T, word size, class S> friend class channel; 00193 template<typename T> friend class message; 00194 00195 00196 friend void Run(); 00197 friend void WakeUpProcess(TBaseProcess& p); 00198 friend void ForceWakeUpProcess(TBaseProcess& p); 00199 friend bool IsProcessSleeping(const TBaseProcess& p); 00200 friend bool IsProcessSuspended(const TBaseProcess& p); 00201 00202 public: 00203 #if SEPARATE_RETURN_STACK == 0 00204 TBaseProcess( TStackItem* Stack, TPriority pr, void (*exec)() ); 00205 #else 00206 TBaseProcess( TStackItem* Stack, TStackItem* RStack, TPriority pr, void (*exec)() ); 00207 #endif 00208 00209 static void Sleep(TTimeout timeout = 0); 00210 00211 protected: 00212 TStackItem* StackPointer; 00213 TTimeout Timeout; 00214 TPriority Priority; 00215 }; 00216 //-------------------------------------------------------------------------- 00217 00218 //-------------------------------------------------------------------------- 00219 // 00220 /// process 00221 /// 00222 /// Implements template for application processes instantiation 00223 // 00224 // DESCRIPTION: 00225 // 00226 // 00227 #if SEPARATE_RETURN_STACK == 0 00228 00229 template<TPriority pr, word stack_size> 00230 class process : public TBaseProcess 00231 { 00232 public: 00233 INLINE_PROCESS_CTOR process(); 00234 00235 OS_PROCESS static void Exec(); 00236 00237 private: 00238 TStackItem Stack[stack_size/sizeof(TStackItem)]; 00239 }; 00240 00241 template<TPriority pr, word stack_size> 00242 OS::process<pr, stack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)] 00243 , pr 00244 , reinterpret_cast<void (*)()>(Exec) ) 00245 { 00246 } 00247 00248 #else 00249 00250 template<TPriority pr, word stack_size, word rstack_size> 00251 class process : public TBaseProcess 00252 { 00253 public: 00254 INLINE_PROCESS_CTOR process(); 00255 00256 OS_PROCESS static void Exec(); 00257 00258 private: 00259 TStackItem Stack [stack_size/sizeof(TStackItem)]; 00260 TStackItem RStack[rstack_size/sizeof(TStackItem)]; 00261 }; 00262 00263 template<TPriority pr, word stack_size, word rstack_size> 00264 process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)] 00265 , &RStack[rstack_size/sizeof(TStackItem)] 00266 , pr 00267 , reinterpret_cast<void (*)()>(Exec)) 00268 { 00269 } 00270 00271 #endif 00272 //-------------------------------------------------------------------------- 00273 00274 //-------------------------------------------------------------------------- 00275 // 00276 // Miscellaneous 00277 // 00278 // 00279 INLINE inline void Run(); 00280 INLINE inline void LockSystemTimer() { TCritSect cs; LOCK_SYSTEM_TIMER(); } 00281 INLINE inline void UnlockSystemTimer() { TCritSect cs; UNLOCK_SYSTEM_TIMER(); } 00282 void WakeUpProcess(TBaseProcess& p); 00283 void ForceWakeUpProcess(TBaseProcess& p); 00284 INLINE inline void Sleep(TTimeout t = 0) { TBaseProcess::Sleep(t); } 00285 00286 INLINE inline bool IsProcessSleeping(const TBaseProcess& p) 00287 { 00288 TCritSect cs; 00289 if(p.Timeout) 00290 return true; 00291 else 00292 return false; 00293 } 00294 00295 INLINE inline bool IsProcessSuspended(const TBaseProcess& p) 00296 { 00297 TCritSect cs; 00298 if(Kernel.ReadyProcessMap & GetPrioTag(p.Priority)) 00299 return false; 00300 else 00301 return true; 00302 } 00303 //-------------------------------------------------------------------------- 00304 00305 #if scmRTOS_SYSTEM_TICKS_ENABLE == 1 00306 INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; } 00307 #endif 00308 00309 #if scmRTOS_SYSTIMER_HOOK_ENABLE == 1 00310 INLINE_SYS_TIMER_HOOK void SystemTimerUserHook(); 00311 #endif 00312 00313 #if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 00314 INLINE_CONTEXT_SWITCH_HOOK void ContextSwitchUserHook(); 00315 #endif 00316 00317 } 00318 //------------------------------------------------------------------------------ 00319 00320 //------------------------------------------------------------------------------ 00321 // 00322 /// Register Process 00323 /// 00324 /// Places pointer to process in kernel's process table 00325 // 00326 void OS::TKernel::RegisterProcess(OS::TBaseProcess* const p) 00327 { 00328 ProcessTable[p->Priority] = p; 00329 } 00330 //------------------------------------------------------------------------------ 00331 // 00332 /// System Timer Implementation 00333 /// 00334 /// Performs process's timeouts checking and 00335 /// moving processes to ready-to-run state 00336 // 00337 void OS::TKernel::SystemTimer() 00338 { 00339 SYS_TIMER_CRIT_SECT(); 00340 #if scmRTOS_SYSTEM_TICKS_ENABLE == 1 00341 SysTickCount++; 00342 #endif 00343 00344 #if scmRTOS_PRIORITY_ORDER == 0 00345 const byte BaseIndex = 0; 00346 #else 00347 const byte BaseIndex = 1; 00348 #endif 00349 00350 for(byte i = BaseIndex; i < (scmRTOS_PROCESS_COUNT + BaseIndex); i++) 00351 { 00352 TBaseProcess* p = ProcessTable[i]; 00353 00354 if(p->Timeout > 0) 00355 { 00356 if(--p->Timeout == 0) 00357 { 00358 SetProcessReady(p->Priority); 00359 } 00360 } 00361 } 00362 } 00363 //------------------------------------------------------------------------------ 00364 // 00365 /// ISR optimized scheduler 00366 /// 00367 /// !!! IMPORTANT: This function must be call from ISR services only !!! 00368 // 00369 // 00370 #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 00371 void OS::TKernel::SchedISR() 00372 { 00373 byte NextPrty = GetHighPriority(ReadyProcessMap); 00374 if(NextPrty != CurProcPriority) 00375 { 00376 TStackItem* Next_SP = ProcessTable[NextPrty]->StackPointer; 00377 TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer); 00378 CurProcPriority = NextPrty; 00379 OS_ContextSwitcher(Curr_SP_addr, Next_SP); 00380 } 00381 } 00382 #else 00383 void OS::TKernel::SchedISR() 00384 { 00385 byte NextPrty = GetHighPriority(ReadyProcessMap); 00386 if(NextPrty != CurProcPriority) 00387 { 00388 SchedProcPriority = NextPrty; 00389 RaiseContextSwitch(); 00390 } 00391 } 00392 //------------------------------------------------------------------------------ 00393 bool OS::TKernel::IsContextSwitchDone() const volatile 00394 { 00395 byte cur = CurProcPriority; ///< reading to temporary vars is performed due to 00396 byte sched = SchedProcPriority; ///< suppress warning about order of volatile access 00397 return cur == sched; 00398 } 00399 //------------------------------------------------------------------------------ 00400 TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp) 00401 { 00402 ProcessTable[CurProcPriority]->StackPointer = sp; 00403 sp = ProcessTable[SchedProcPriority]->StackPointer; 00404 00405 #if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 00406 ContextSwitchUserHook(); 00407 #endif 00408 00409 CurProcPriority = SchedProcPriority; 00410 return sp; 00411 } 00412 //------------------------------------------------------------------------------ 00413 #endif // scmRTOS_CONTEXT_SWITCH_SCHEME 00414 00415 //----------------------------------------------------------------------------- 00416 /// Start Operation 00417 INLINE inline void OS::Run() 00418 { 00419 TStackItem* sp = Kernel.ProcessTable[pr0]->StackPointer; 00420 OS_Start(sp); 00421 } 00422 00423 #include <OS_Services.h> 00424 00425 #endif // OS_KERNEL_H 00426
Generated on Tue Jul 12 2022 20:03:20 by 1.7.2