Dependencies:   mbed

Revision:
0:331db0b44b67
diff -r 000000000000 -r 331db0b44b67 scmRTOS/Common/OS_Kernel.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scmRTOS/Common/OS_Kernel.h	Tue Sep 21 19:48:05 2010 +0000
@@ -0,0 +1,439 @@
+//******************************************************************************
+//*
+//*     FULLNAME:  Single-Chip Microcontroller Real-Time Operating System
+//*
+//*     NICKNAME:  scmRTOS
+//*
+//*     PURPOSE:  OS Kernel Header. Declarations And Definitions
+//*
+//*     Version: 3.10
+//*
+//*     $Revision: 256 $
+//*     $Date:: 2010-01-22 #$
+//*
+//*     Copyright (c) 2003-2010, Harry E. Zhurov
+//*
+//*     Permission is hereby granted, free of charge, to any person
+//*     obtaining  a copy of this software and associated documentation
+//*     files (the "Software"), to deal in the Software without restriction,
+//*     including without limitation the rights to use, copy, modify, merge,
+//*     publish, distribute, sublicense, and/or sell copies of the Software,
+//*     and to permit persons to whom the Software is furnished to do so,
+//*     subject to the following conditions:
+//*
+//*     The above copyright notice and this permission notice shall be included
+//*     in all copies or substantial portions of the Software.
+//*
+//*     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+//*     EXPRESS  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+//*     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+//*     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+//*     CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+//*     TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+//*     THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//*
+//*     =================================================================
+//*     See http://scmrtos.sourceforge.net for documentation, latest
+//*     information, license and contact details.
+//*     =================================================================
+//*
+//*****************************************************************************
+
+#ifndef OS_KERNEL_H
+#define OS_KERNEL_H
+
+#include <stddef.h>
+#include <commdefs.h>
+#include <usrlib.h>
+
+//------------------------------------------------------------------------------
+
+//==============================================================================
+extern "C" void OS_Start(TStackItem* sp);
+
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+    extern "C" void OS_ContextSwitcher(TStackItem** Curr_SP, TStackItem* Next_SP);
+#else
+    extern "C" TStackItem* OS_ContextSwitchHook(TStackItem* sp);
+#endif
+
+//==============================================================================
+
+//------------------------------------------------------------------------------
+//
+//
+//     NAME       :   OS
+//
+//     PURPOSE    :   Namespace for all OS stuff
+//
+//     DESCRIPTION:   Includes:  Kernel,
+//                               Processes,
+//                               Mutexes,
+//                               Event Flags,
+//                               Byte-wide Channels,
+//                               Arbitrary-type Channels,
+//                               Messages
+//
+namespace OS
+{
+    class TBaseProcess;
+
+    INLINE inline void SetPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm |=  PrioTag; }
+    INLINE inline void ClrPrioTag(TProcessMap& pm, const TProcessMap PrioTag) { pm &= ~PrioTag; }
+
+    //--------------------------------------------------------------------------
+    //
+    //     NAME       :   TKernel
+    //
+    ///  Implements kernel-level operations such as
+    ///  process management, process-level scheduling,
+    ///  ISR-level scheduling, system timing.
+    //
+    //     DESCRIPTION:
+    //
+    //
+    class TKernel
+    {
+        //-----------------------------------------------------------
+        //
+        //     Declarations
+        //
+        
+
+        friend class TISRW;
+        friend class TISRW_SS;
+        friend class TBaseProcess;
+        friend class TMutex;
+        friend class TEventFlag;
+        friend class TChannel;
+        friend class TBaseMessage;
+
+        template<typename T, word size, class S> friend class channel;
+        template<typename T>                     friend class message;
+
+        friend void          Run();
+        friend void          WakeUpProcess(TBaseProcess& p);
+        friend void          ForceWakeUpProcess(TBaseProcess& p);
+        friend inline bool   IsProcessSleeping(const TBaseProcess& p);
+        friend inline bool   IsProcessSuspended(const TBaseProcess& p);
+        friend inline dword  GetTickCount();
+
+        //-----------------------------------------------------------
+        //
+        //      Data
+        //
+    private:
+        byte CurProcPriority;
+        TProcessMap ReadyProcessMap;
+        TBaseProcess* ProcessTable[scmRTOS_PROCESS_COUNT+1];
+        volatile byte ISR_NestCount;
+
+    #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+        byte SchedProcPriority;
+    #endif
+
+    #if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+        volatile dword SysTickCount;
+    #endif
+
+    //-----------------------------------------------------------
+    //
+    //      Functions
+    //
+    public:
+        INLINE TKernel()
+            : CurProcPriority(pr0)
+            , ReadyProcessMap( (1 << (scmRTOS_PROCESS_COUNT + 1)) - 1)  // set all processes ready
+            , ISR_NestCount(0)
+        {
+        }
+
+    private:
+        INLINE inline void RegisterProcess(TBaseProcess* const p);
+
+        void Sched();
+        INLINE void Scheduler() { if(ISR_NestCount) return; else  Sched(); }
+        INLINE inline void SchedISR();
+
+    #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+        INLINE inline bool IsContextSwitchDone() const volatile;
+    #endif
+        INLINE void SetProcessReady  (const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); SetPrioTag( ReadyProcessMap, PrioTag); }
+        INLINE void SetProcessUnready(const byte pr) { TProcessMap PrioTag = GetPrioTag(pr); ClrPrioTag( ReadyProcessMap, PrioTag); }
+
+    public:
+        INLINE inline void SystemTimer();
+    #if scmRTOS_CONTEXT_SWITCH_SCHEME == 1
+        INLINE inline TStackItem* ContextSwitchHook(TStackItem* sp);
+    #endif
+
+    };  // End of TKernel class definition
+    //--------------------------------------------------------------------------
+    extern TKernel Kernel;
+
+    //--------------------------------------------------------------------------
+    //
+    /// BaseProcess
+    ///
+    /// Implements base class-type for application processes
+    //
+    //      DESCRIPTION:
+    //
+    //
+    class TBaseProcess
+    {
+        friend class TKernel;
+        friend class TISRW;
+        friend class TISRW_SS;
+        friend class TEventFlag;
+        friend class TMutex;
+        friend class TBaseMessage;
+
+        template<typename T, word size, class S> friend class channel;
+        template<typename T>                     friend class message;
+
+
+        friend void         Run();
+        friend void         WakeUpProcess(TBaseProcess& p);
+        friend void         ForceWakeUpProcess(TBaseProcess& p);
+        friend bool         IsProcessSleeping(const TBaseProcess& p);
+        friend bool         IsProcessSuspended(const TBaseProcess& p);
+
+    public:
+    #if SEPARATE_RETURN_STACK == 0
+        TBaseProcess( TStackItem* Stack, word stack_size, TPriority pr, void (*exec)() );
+    #else
+        TBaseProcess( TStackItem* Stack, TStackItem* RStack, TPriority pr, void (*exec)() );
+    #endif
+
+        static void Sleep(TTimeout timeout = 0);
+
+    protected:
+        TStackItem* StackPointer;
+        word StackSize;
+        TTimeout Timeout;
+        TPriority Priority;
+        
+    };
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    ///  process
+    ///
+    ///  Implements template for application processes instantiation
+    //
+    //      DESCRIPTION:
+    //
+    //
+    #if SEPARATE_RETURN_STACK == 0
+
+        template<TPriority pr, word stack_size>
+        class process : public TBaseProcess
+        {
+        public:
+            INLINE_PROCESS_CTOR process();
+#ifdef DEBUG_STACK
+word UsedStackSize();
+#endif //DEBUG_STACK
+            OS_PROCESS static void Exec();
+
+        private:
+            TStackItem Stack[stack_size/sizeof(TStackItem)];
+        };
+
+        template<TPriority pr, word stack_size>
+        OS::process<pr, stack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)]
+                                                              , stack_size // debug
+                                                              , pr
+                                                              , reinterpret_cast<void (*)()>(Exec) )
+        {
+        }
+#ifdef DEBUG_STACK
+template<TPriority pr, word stack_size>
+word process<pr,stack_size>::UsedStackSize()
+{
+TStackItem* Idx = Stack;
+while(*(Idx++) == STACK_FILL_CONST);
+return ((Stack + (StackSize/sizeof(TStackItem))) - Idx)*sizeof(TStackItem);
+}
+#endif //DEBUG_STACK
+    #else
+
+        template<TPriority pr, word stack_size, word rstack_size>
+        class process : public TBaseProcess
+        {
+        public:
+            INLINE_PROCESS_CTOR process();
+
+            OS_PROCESS static void Exec();
+
+        private:
+            TStackItem Stack [stack_size/sizeof(TStackItem)];
+            TStackItem RStack[rstack_size/sizeof(TStackItem)];
+        };
+
+        template<TPriority pr, word stack_size, word rstack_size>
+        process<pr, stack_size, rstack_size>::process() : TBaseProcess( &Stack[stack_size/sizeof(TStackItem)]
+                                                                      , &RStack[rstack_size/sizeof(TStackItem)]
+                                                                      , pr
+                                                                      , reinterpret_cast<void (*)()>(Exec))
+        {
+        }
+
+    #endif
+    //--------------------------------------------------------------------------
+
+    //--------------------------------------------------------------------------
+    //
+    //       Miscellaneous
+    //
+    //
+    INLINE inline void Run();
+    INLINE inline void LockSystemTimer()   { TCritSect cs; LOCK_SYSTEM_TIMER();   }
+    INLINE inline void UnlockSystemTimer() { TCritSect cs; UNLOCK_SYSTEM_TIMER(); }
+    void WakeUpProcess(TBaseProcess& p);
+    void ForceWakeUpProcess(TBaseProcess& p);
+    INLINE inline void Sleep(TTimeout t = 0) { TBaseProcess::Sleep(t); }
+
+    INLINE inline bool IsProcessSleeping(const TBaseProcess& p)
+    {
+        TCritSect cs;
+        if(p.Timeout)
+            return true;
+        else
+            return false;
+    }
+
+    INLINE inline bool IsProcessSuspended(const TBaseProcess& p)
+    {
+        TCritSect cs;
+        if(Kernel.ReadyProcessMap & GetPrioTag(p.Priority))
+            return false;
+        else
+            return true;
+    }
+    //--------------------------------------------------------------------------
+
+#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+    INLINE inline dword GetTickCount() { TCritSect cs; return Kernel.SysTickCount; }
+#endif
+
+#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
+    INLINE_SYS_TIMER_HOOK void  SystemTimerUserHook();
+#endif
+
+#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
+    INLINE_CONTEXT_SWITCH_HOOK void  ContextSwitchUserHook();
+#endif
+    
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+//
+///  Register Process
+///
+///  Places pointer to process in kernel's process table
+//
+void OS::TKernel::RegisterProcess(OS::TBaseProcess* const p)
+{
+    ProcessTable[p->Priority] = p;
+}
+//------------------------------------------------------------------------------
+//
+/// System Timer Implementation
+///
+/// Performs process's timeouts checking and
+///               moving processes to ready-to-run state
+//
+void OS::TKernel::SystemTimer()
+{
+    SYS_TIMER_CRIT_SECT();
+#if scmRTOS_SYSTEM_TICKS_ENABLE == 1
+    SysTickCount++;
+#endif
+
+#if scmRTOS_PRIORITY_ORDER == 0
+    const byte BaseIndex = 0;
+#else
+    const byte BaseIndex = 1;
+#endif
+
+    for(byte i = BaseIndex; i < (scmRTOS_PROCESS_COUNT + BaseIndex); i++)
+    {
+        TBaseProcess* p = ProcessTable[i];
+
+        if(p->Timeout > 0)
+        {
+            if(--p->Timeout == 0)
+            {
+                SetProcessReady(p->Priority);
+            }
+        }
+    }
+}
+//------------------------------------------------------------------------------
+//
+///    ISR optimized scheduler
+///
+///    !!! IMPORTANT: This function must be call from ISR services only !!!
+//
+//
+#if scmRTOS_CONTEXT_SWITCH_SCHEME == 0
+void OS::TKernel::SchedISR()
+{
+    byte NextPrty = GetHighPriority(ReadyProcessMap);
+    if(NextPrty != CurProcPriority)
+    {
+        TStackItem*  Next_SP = ProcessTable[NextPrty]->StackPointer;
+        TStackItem** Curr_SP_addr = &(ProcessTable[CurProcPriority]->StackPointer);
+        CurProcPriority = NextPrty;
+        OS_ContextSwitcher(Curr_SP_addr, Next_SP);
+    }
+}
+#else
+void OS::TKernel::SchedISR()
+{
+    byte NextPrty = GetHighPriority(ReadyProcessMap);
+    if(NextPrty != CurProcPriority)
+    {
+        SchedProcPriority    = NextPrty;
+        RaiseContextSwitch();
+    }
+}
+//------------------------------------------------------------------------------
+bool OS::TKernel::IsContextSwitchDone() const volatile
+{
+     byte cur    = CurProcPriority;    ///< reading to temporary vars is performed due to
+     byte sched  = SchedProcPriority;  ///< suppress warning about order of volatile access
+     return cur == sched;
+}
+//------------------------------------------------------------------------------
+TStackItem* OS::TKernel::ContextSwitchHook(TStackItem* sp)
+{
+    ProcessTable[CurProcPriority]->StackPointer = sp;
+    sp = ProcessTable[SchedProcPriority]->StackPointer;
+
+#if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1
+    ContextSwitchUserHook();
+#endif 
+
+    CurProcPriority = SchedProcPriority;
+    return sp;
+}
+//------------------------------------------------------------------------------
+#endif // scmRTOS_CONTEXT_SWITCH_SCHEME
+
+//-----------------------------------------------------------------------------
+/// Start Operation
+INLINE inline void OS::Run()
+{
+    TStackItem* sp = Kernel.ProcessTable[pr0]->StackPointer;
+    OS_Start(sp);
+}
+
+#include <OS_Services.h>
+
+#endif // OS_KERNEL_H
+