Daniel Peter
/
RtosTest
Embed:
(wiki syntax)
Show/hide line numbers
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, word stack_size, 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 word StackSize; 00214 TTimeout Timeout; 00215 TPriority Priority; 00216 00217 }; 00218 //-------------------------------------------------------------------------- 00219 00220 //-------------------------------------------------------------------------- 00221 // 00222 /// process 00223 /// 00224 /// Implements template for application processes instantiation 00225 // 00226 // DESCRIPTION: 00227 // 00228 // 00229 #if SEPARATE_RETURN_STACK == 0 00230 00231 template<TPriority pr, word stack_size> 00232 class process : public TBaseProcess 00233 { 00234 public: 00235 INLINE_PROCESS_CTOR process(); 00236 #ifdef DEBUG_STACK 00237 word UsedStackSize(); 00238 #endif //DEBUG_STACK 00239 OS_PROCESS static void Exec(); 00240 00241 private: 00242 TStackItem Stack[stack_size/sizeof(TStackItem)]; 00243 }; 00244 00245 template<TPriority pr, word stack_size> 00246 OS::process<pr, stack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)] 00247 , stack_size // debug 00248 , pr 00249 , reinterpret_cast<void (*)()>(Exec) ) 00250 { 00251 } 00252 #ifdef DEBUG_STACK 00253 template<TPriority pr, word stack_size> 00254 word process<pr,stack_size>::UsedStackSize() 00255 { 00256 TStackItem* Idx = Stack; 00257 while(*(Idx++) == STACK_FILL_CONST); 00258 return ((Stack + (StackSize/sizeof(TStackItem))) - Idx)*sizeof(TStackItem); 00259 } 00260 #endif //DEBUG_STACK 00261 #else 00262 00263 template<TPriority pr, word stack_size, word rstack_size> 00264 class process : public TBaseProcess 00265 { 00266 public: 00267 INLINE_PROCESS_CTOR process(); 00268 00269 OS_PROCESS static void Exec(); 00270 00271 private: 00272 TStackItem Stack [stack_size/sizeof(TStackItem)]; 00273 TStackItem RStack[rstack_size/sizeof(TStackItem)]; 00274 }; 00275 00276 template<TPriority pr, word stack_size, word rstack_size> 00277 process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)] 00278 , &RStack[rstack_size/sizeof(TStackItem)] 00279 , pr 00280 , reinterpret_cast<void (*)()>(Exec)) 00281 { 00282 } 00283 00284 #endif 00285 //-------------------------------------------------------------------------- 00286 00287 //-------------------------------------------------------------------------- 00288 // 00289 // Miscellaneous 00290 // 00291 // 00292 INLINE inline void Run(); 00293 INLINE inline void LockSystemTimer() { TCritSect cs; LOCK_SYSTEM_TIMER(); } 00294 INLINE inline void UnlockSystemTimer() { TCritSect cs; UNLOCK_SYSTEM_TIMER(); } 00295 void WakeUpProcess(TBaseProcess& p); 00296 void ForceWakeUpProcess(TBaseProcess& p); 00297 INLINE inline void Sleep(TTimeout t = 0) { TBaseProcess::Sleep(t); } 00298 00299 INLINE inline bool IsProcessSleeping(const TBaseProcess& p) 00300 { 00301 TCritSect cs; 00302 if(p.Timeout) 00303 return true; 00304 else 00305 return false; 00306 } 00307 00308 INLINE inline bool IsProcessSuspended(const TBaseProcess& p) 00309 { 00310 TCritSect cs; 00311 if(Kernel.ReadyProcessMap & GetPrioTag(p.Priority)) 00312 return false; 00313 else 00314 return true; 00315 } 00316 //-------------------------------------------------------------------------- 00317 00318 #if scmRTOS_SYSTEM_TICKS_ENABLE == 1 00319 INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; } 00320 #endif 00321 00322 #if scmRTOS_SYSTIMER_HOOK_ENABLE == 1 00323 INLINE_SYS_TIMER_HOOK void SystemTimerUserHook(); 00324 #endif 00325 00326 #if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 00327 INLINE_CONTEXT_SWITCH_HOOK void ContextSwitchUserHook(); 00328 #endif 00329 00330 } 00331 //------------------------------------------------------------------------------ 00332 00333 //------------------------------------------------------------------------------ 00334 // 00335 /// Register Process 00336 /// 00337 /// Places pointer to process in kernel's process table 00338 // 00339 void OS::TKernel::RegisterProcess(OS::TBaseProcess* const p) 00340 { 00341 ProcessTable[p->Priority] = p; 00342 } 00343 //------------------------------------------------------------------------------ 00344 // 00345 /// System Timer Implementation 00346 /// 00347 /// Performs process's timeouts checking and 00348 /// moving processes to ready-to-run state 00349 // 00350 void OS::TKernel::SystemTimer() 00351 { 00352 SYS_TIMER_CRIT_SECT(); 00353 #if scmRTOS_SYSTEM_TICKS_ENABLE == 1 00354 SysTickCount++; 00355 #endif 00356 00357 #if scmRTOS_PRIORITY_ORDER == 0 00358 const byte BaseIndex = 0; 00359 #else 00360 const byte BaseIndex = 1; 00361 #endif 00362 00363 for(byte i = BaseIndex; i < (scmRTOS_PROCESS_COUNT + BaseIndex); i++) 00364 { 00365 TBaseProcess* p = ProcessTable[i]; 00366 00367 if(p->Timeout > 0) 00368 { 00369 if(--p->Timeout == 0) 00370 { 00371 SetProcessReady(p->Priority); 00372 } 00373 } 00374 } 00375 } 00376 //------------------------------------------------------------------------------ 00377 // 00378 /// ISR optimized scheduler 00379 /// 00380 /// !!! IMPORTANT: This function must be call from ISR services only !!! 00381 // 00382 // 00383 #if scmRTOS_CONTEXT_SWITCH_SCHEME == 0 00384 void OS::TKernel::SchedISR() 00385 { 00386 byte NextPrty = GetHighPriority(ReadyProcessMap); 00387 if(NextPrty != CurProcPriority) 00388 { 00389 TStackItem* Next_SP = ProcessTable[NextPrty]->StackPointer; 00390 TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer); 00391 CurProcPriority = NextPrty; 00392 OS_ContextSwitcher(Curr_SP_addr, Next_SP); 00393 } 00394 } 00395 #else 00396 void OS::TKernel::SchedISR() 00397 { 00398 byte NextPrty = GetHighPriority(ReadyProcessMap); 00399 if(NextPrty != CurProcPriority) 00400 { 00401 SchedProcPriority = NextPrty; 00402 RaiseContextSwitch(); 00403 } 00404 } 00405 //------------------------------------------------------------------------------ 00406 bool OS::TKernel::IsContextSwitchDone() const volatile 00407 { 00408 byte cur = CurProcPriority; ///< reading to temporary vars is performed due to 00409 byte sched = SchedProcPriority; ///< suppress warning about order of volatile access 00410 return cur == sched; 00411 } 00412 //------------------------------------------------------------------------------ 00413 TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp) 00414 { 00415 ProcessTable[CurProcPriority]->StackPointer = sp; 00416 sp = ProcessTable[SchedProcPriority]->StackPointer; 00417 00418 #if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 00419 ContextSwitchUserHook(); 00420 #endif 00421 00422 CurProcPriority = SchedProcPriority; 00423 return sp; 00424 } 00425 //------------------------------------------------------------------------------ 00426 #endif // scmRTOS_CONTEXT_SWITCH_SCHEME 00427 00428 //----------------------------------------------------------------------------- 00429 /// Start Operation 00430 INLINE inline void OS::Run() 00431 { 00432 TStackItem* sp = Kernel.ProcessTable[pr0]->StackPointer; 00433 OS_Start(sp); 00434 } 00435 00436 #include <OS_Services.h> 00437 00438 #endif // OS_KERNEL_H 00439
Generated on Tue Jul 12 2022 21:14:46 by 1.7.2