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.

Dependencies:   mbed

Committer:
igorsk
Date:
Thu Sep 09 21:19:01 2010 +0000
Revision:
0:a405220cf420

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igorsk 0:a405220cf420 1 //******************************************************************************
igorsk 0:a405220cf420 2 //*
igorsk 0:a405220cf420 3 //* FULLNAME: Single-Chip Microcontroller Real-Time Operating System
igorsk 0:a405220cf420 4 //*
igorsk 0:a405220cf420 5 //* NICKNAME: scmRTOS
igorsk 0:a405220cf420 6 //*
igorsk 0:a405220cf420 7 //* PURPOSE: OS Services Source
igorsk 0:a405220cf420 8 //*
igorsk 0:a405220cf420 9 //* Version: 3.10
igorsk 0:a405220cf420 10 //*
igorsk 0:a405220cf420 11 //* $Revision: 256 $
igorsk 0:a405220cf420 12 //* $Date:: 2010-01-22 #$
igorsk 0:a405220cf420 13 //*
igorsk 0:a405220cf420 14 //* Copyright (c) 2003-2010, Harry E. Zhurov
igorsk 0:a405220cf420 15 //*
igorsk 0:a405220cf420 16 //* Permission is hereby granted, free of charge, to any person
igorsk 0:a405220cf420 17 //* obtaining a copy of this software and associated documentation
igorsk 0:a405220cf420 18 //* files (the "Software"), to deal in the Software without restriction,
igorsk 0:a405220cf420 19 //* including without limitation the rights to use, copy, modify, merge,
igorsk 0:a405220cf420 20 //* publish, distribute, sublicense, and/or sell copies of the Software,
igorsk 0:a405220cf420 21 //* and to permit persons to whom the Software is furnished to do so,
igorsk 0:a405220cf420 22 //* subject to the following conditions:
igorsk 0:a405220cf420 23 //*
igorsk 0:a405220cf420 24 //* The above copyright notice and this permission notice shall be included
igorsk 0:a405220cf420 25 //* in all copies or substantial portions of the Software.
igorsk 0:a405220cf420 26 //*
igorsk 0:a405220cf420 27 //* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
igorsk 0:a405220cf420 28 //* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
igorsk 0:a405220cf420 29 //* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
igorsk 0:a405220cf420 30 //* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
igorsk 0:a405220cf420 31 //* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
igorsk 0:a405220cf420 32 //* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
igorsk 0:a405220cf420 33 //* THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
igorsk 0:a405220cf420 34 //*
igorsk 0:a405220cf420 35 //* =================================================================
igorsk 0:a405220cf420 36 //* See http://scmrtos.sourceforge.net for documentation, latest
igorsk 0:a405220cf420 37 //* information, license and contact details.
igorsk 0:a405220cf420 38 //* =================================================================
igorsk 0:a405220cf420 39 //*
igorsk 0:a405220cf420 40 //******************************************************************************
igorsk 0:a405220cf420 41
igorsk 0:a405220cf420 42 #include "scmRTOS.h"
igorsk 0:a405220cf420 43
igorsk 0:a405220cf420 44 using namespace OS;
igorsk 0:a405220cf420 45
igorsk 0:a405220cf420 46 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 47 //
igorsk 0:a405220cf420 48 //
igorsk 0:a405220cf420 49 // TEventFlag
igorsk 0:a405220cf420 50 //
igorsk 0:a405220cf420 51 //
igorsk 0:a405220cf420 52 bool OS::TEventFlag::Wait(TTimeout timeout)
igorsk 0:a405220cf420 53 {
igorsk 0:a405220cf420 54 TCritSect cs;
igorsk 0:a405220cf420 55
igorsk 0:a405220cf420 56 if(Value) // if flag already signaled
igorsk 0:a405220cf420 57 {
igorsk 0:a405220cf420 58 Value = efOff; // clear flag
igorsk 0:a405220cf420 59 return true;
igorsk 0:a405220cf420 60 }
igorsk 0:a405220cf420 61 else
igorsk 0:a405220cf420 62 {
igorsk 0:a405220cf420 63 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
igorsk 0:a405220cf420 64 p->Timeout = timeout;
igorsk 0:a405220cf420 65 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 66
igorsk 0:a405220cf420 67 SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map
igorsk 0:a405220cf420 68 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 69
igorsk 0:a405220cf420 70 Kernel.Scheduler();
igorsk 0:a405220cf420 71
igorsk 0:a405220cf420 72 p->Timeout = 0;
igorsk 0:a405220cf420 73
igorsk 0:a405220cf420 74 if( !(ProcessMap & PrioTag) ) // if waked up by signal() or signal_ISR()
igorsk 0:a405220cf420 75 return true;
igorsk 0:a405220cf420 76
igorsk 0:a405220cf420 77 ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by
igorsk 0:a405220cf420 78 return false; // OS::ForceWakeUpProcess(), remove process from the wait map
igorsk 0:a405220cf420 79 }
igorsk 0:a405220cf420 80 }
igorsk 0:a405220cf420 81 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 82 void OS::TEventFlag::Signal()
igorsk 0:a405220cf420 83 {
igorsk 0:a405220cf420 84 TCritSect cs;
igorsk 0:a405220cf420 85 if(ProcessMap) // if any process waits for event
igorsk 0:a405220cf420 86 {
igorsk 0:a405220cf420 87 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired
igorsk 0:a405220cf420 88 // or it was waked up by OS::ForceWakeUpProcess()
igorsk 0:a405220cf420 89
igorsk 0:a405220cf420 90 if( ProcessMap & ~Timeouted ) // if any process has to be waked up
igorsk 0:a405220cf420 91 {
igorsk 0:a405220cf420 92 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
igorsk 0:a405220cf420 93 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
igorsk 0:a405220cf420 94 // Used to check that process waked up by signal() or signalISR()
igorsk 0:a405220cf420 95 // and not by timeout or OS::ForceWakeUpProcess()
igorsk 0:a405220cf420 96 Kernel.Scheduler();
igorsk 0:a405220cf420 97 return;
igorsk 0:a405220cf420 98 }
igorsk 0:a405220cf420 99 }
igorsk 0:a405220cf420 100 Value = efOn;
igorsk 0:a405220cf420 101 }
igorsk 0:a405220cf420 102 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 103
igorsk 0:a405220cf420 104 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 105 //
igorsk 0:a405220cf420 106 //
igorsk 0:a405220cf420 107 // TMutex
igorsk 0:a405220cf420 108 //
igorsk 0:a405220cf420 109 //
igorsk 0:a405220cf420 110 void OS::TMutex::Lock()
igorsk 0:a405220cf420 111 {
igorsk 0:a405220cf420 112 TCritSect cs;
igorsk 0:a405220cf420 113
igorsk 0:a405220cf420 114 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 115 while(ValueTag)
igorsk 0:a405220cf420 116 {
igorsk 0:a405220cf420 117 SetPrioTag(ProcessMap, PrioTag); // mutex already locked by another process, put current process to the wait map
igorsk 0:a405220cf420 118 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 119
igorsk 0:a405220cf420 120 Kernel.Scheduler();
igorsk 0:a405220cf420 121 }
igorsk 0:a405220cf420 122 ValueTag = PrioTag; // mutex has been successfully locked
igorsk 0:a405220cf420 123 }
igorsk 0:a405220cf420 124 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 125 void OS::TMutex::Unlock()
igorsk 0:a405220cf420 126 {
igorsk 0:a405220cf420 127 TCritSect cs;
igorsk 0:a405220cf420 128
igorsk 0:a405220cf420 129 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 130 if(ValueTag != PrioTag) return; // the only process that had locked mutex can unlock the mutex
igorsk 0:a405220cf420 131 ValueTag = 0;
igorsk 0:a405220cf420 132 if(ProcessMap)
igorsk 0:a405220cf420 133 {
igorsk 0:a405220cf420 134 byte pr = GetHighPriority(ProcessMap);
igorsk 0:a405220cf420 135 PrioTag = GetPrioTag(pr);
igorsk 0:a405220cf420 136 ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map
igorsk 0:a405220cf420 137 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
igorsk 0:a405220cf420 138 Kernel.Scheduler();
igorsk 0:a405220cf420 139 }
igorsk 0:a405220cf420 140 }
igorsk 0:a405220cf420 141 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 142 void OS::TMutex::UnlockISR()
igorsk 0:a405220cf420 143 {
igorsk 0:a405220cf420 144 TCritSect cs;
igorsk 0:a405220cf420 145
igorsk 0:a405220cf420 146 ValueTag = 0;
igorsk 0:a405220cf420 147 if(ProcessMap)
igorsk 0:a405220cf420 148 {
igorsk 0:a405220cf420 149 byte pr = GetHighPriority(ProcessMap);
igorsk 0:a405220cf420 150 TProcessMap PrioTag = GetPrioTag(pr);
igorsk 0:a405220cf420 151 ClrPrioTag(ProcessMap, PrioTag); // remove next ready process from the wait map
igorsk 0:a405220cf420 152 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
igorsk 0:a405220cf420 153 }
igorsk 0:a405220cf420 154 }
igorsk 0:a405220cf420 155 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 156
igorsk 0:a405220cf420 157
igorsk 0:a405220cf420 158 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 159 //
igorsk 0:a405220cf420 160 //
igorsk 0:a405220cf420 161 // TChannel
igorsk 0:a405220cf420 162 //
igorsk 0:a405220cf420 163 //
igorsk 0:a405220cf420 164 void OS::TChannel::CheckWaiters(TProcessMap& pm)
igorsk 0:a405220cf420 165 {
igorsk 0:a405220cf420 166 if(pm)
igorsk 0:a405220cf420 167 {
igorsk 0:a405220cf420 168 byte pr = GetHighPriority(pm);
igorsk 0:a405220cf420 169 TProcessMap PrioTag = GetPrioTag(pr);
igorsk 0:a405220cf420 170 ClrPrioTag(pm, PrioTag); // remove next ready process from the wait map
igorsk 0:a405220cf420 171 SetPrioTag(Kernel.ReadyProcessMap, PrioTag); // place next process to the ready map
igorsk 0:a405220cf420 172 Kernel.Scheduler();
igorsk 0:a405220cf420 173 }
igorsk 0:a405220cf420 174 }
igorsk 0:a405220cf420 175 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 176 void OS::TChannel::Push(byte x)
igorsk 0:a405220cf420 177 {
igorsk 0:a405220cf420 178 TCritSect cs;
igorsk 0:a405220cf420 179
igorsk 0:a405220cf420 180 while (!Cbuf.get_free_size())
igorsk 0:a405220cf420 181 {
igorsk 0:a405220cf420 182 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 183 SetPrioTag (ProducersProcessMap, PrioTag); // channel is full, put current process to the wait map
igorsk 0:a405220cf420 184 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 185 Kernel.Scheduler(); // wait until waked-up by Pop() or Read()
igorsk 0:a405220cf420 186 }
igorsk 0:a405220cf420 187
igorsk 0:a405220cf420 188 Cbuf.put(x);
igorsk 0:a405220cf420 189 CheckWaiters(ConsumersProcessMap);
igorsk 0:a405220cf420 190 }
igorsk 0:a405220cf420 191 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 192 byte OS::TChannel::Pop()
igorsk 0:a405220cf420 193 {
igorsk 0:a405220cf420 194 TCritSect cs;
igorsk 0:a405220cf420 195 byte x;
igorsk 0:a405220cf420 196
igorsk 0:a405220cf420 197 while(!Cbuf.get_count())
igorsk 0:a405220cf420 198 {
igorsk 0:a405220cf420 199 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 200 SetPrioTag(ConsumersProcessMap, PrioTag); // channel is empty, put current process to the wait map
igorsk 0:a405220cf420 201 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 202 Kernel.Scheduler(); // wait until waked up by Push() or Write()
igorsk 0:a405220cf420 203 }
igorsk 0:a405220cf420 204 x = Cbuf.get();
igorsk 0:a405220cf420 205 CheckWaiters(ProducersProcessMap);
igorsk 0:a405220cf420 206 return x;
igorsk 0:a405220cf420 207 }
igorsk 0:a405220cf420 208 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 209 void OS::TChannel::Write(const byte* data, const byte count)
igorsk 0:a405220cf420 210 {
igorsk 0:a405220cf420 211 TCritSect cs;
igorsk 0:a405220cf420 212
igorsk 0:a405220cf420 213 while(Cbuf.get_free_size() < count)
igorsk 0:a405220cf420 214 {
igorsk 0:a405220cf420 215 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 216 SetPrioTag(ProducersProcessMap, PrioTag); // channel has not enough space, put current process to the wait map
igorsk 0:a405220cf420 217 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 218 Kernel.Scheduler(); // wait until waked up by Read() or Pop()
igorsk 0:a405220cf420 219 }
igorsk 0:a405220cf420 220
igorsk 0:a405220cf420 221 Cbuf.write(data, count);
igorsk 0:a405220cf420 222 CheckWaiters(ConsumersProcessMap);
igorsk 0:a405220cf420 223 }
igorsk 0:a405220cf420 224 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 225 void OS::TChannel::Read(byte* const data, const byte count)
igorsk 0:a405220cf420 226 {
igorsk 0:a405220cf420 227 TCritSect cs;
igorsk 0:a405220cf420 228
igorsk 0:a405220cf420 229 while(Cbuf.get_count() < count)
igorsk 0:a405220cf420 230 {
igorsk 0:a405220cf420 231 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 232 SetPrioTag(ConsumersProcessMap, PrioTag); // channel doesn't contain enough data, put current process to the wait map
igorsk 0:a405220cf420 233 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 234 Kernel.Scheduler(); // wait until waked up by Write() or Push()
igorsk 0:a405220cf420 235 }
igorsk 0:a405220cf420 236
igorsk 0:a405220cf420 237 Cbuf.read(data, count);
igorsk 0:a405220cf420 238 CheckWaiters(ProducersProcessMap);
igorsk 0:a405220cf420 239 }
igorsk 0:a405220cf420 240 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 241
igorsk 0:a405220cf420 242 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 243 //
igorsk 0:a405220cf420 244 // OS::message template
igorsk 0:a405220cf420 245 //
igorsk 0:a405220cf420 246 // Function-members implementation
igorsk 0:a405220cf420 247 //
igorsk 0:a405220cf420 248 //
igorsk 0:a405220cf420 249 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 250 bool OS::TBaseMessage::wait(TTimeout timeout)
igorsk 0:a405220cf420 251 {
igorsk 0:a405220cf420 252 TCritSect cs;
igorsk 0:a405220cf420 253
igorsk 0:a405220cf420 254 if(NonEmpty) // message alredy send
igorsk 0:a405220cf420 255 {
igorsk 0:a405220cf420 256 NonEmpty = false;
igorsk 0:a405220cf420 257 return true;
igorsk 0:a405220cf420 258 }
igorsk 0:a405220cf420 259 else
igorsk 0:a405220cf420 260 {
igorsk 0:a405220cf420 261 TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
igorsk 0:a405220cf420 262 p->Timeout = timeout;
igorsk 0:a405220cf420 263 TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);
igorsk 0:a405220cf420 264
igorsk 0:a405220cf420 265 SetPrioTag(ProcessMap, PrioTag); // put current process to the wait map
igorsk 0:a405220cf420 266 ClrPrioTag(Kernel.ReadyProcessMap, PrioTag); // remove current process from the ready map
igorsk 0:a405220cf420 267 Kernel.Scheduler(); // wait until wake up
igorsk 0:a405220cf420 268
igorsk 0:a405220cf420 269 p->Timeout = 0;
igorsk 0:a405220cf420 270 if( !(ProcessMap & PrioTag) ) // if waked up by send() or sendISR()
igorsk 0:a405220cf420 271 return true;
igorsk 0:a405220cf420 272
igorsk 0:a405220cf420 273 ClrPrioTag(ProcessMap, PrioTag); // otherwise waked up by timeout or by
igorsk 0:a405220cf420 274 return false; // OS::ForceWakeUpProcess(), remove process from wait map
igorsk 0:a405220cf420 275 }
igorsk 0:a405220cf420 276 }
igorsk 0:a405220cf420 277 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 278 void OS::TBaseMessage::send()
igorsk 0:a405220cf420 279 {
igorsk 0:a405220cf420 280 TCritSect cs;
igorsk 0:a405220cf420 281
igorsk 0:a405220cf420 282 if(ProcessMap)
igorsk 0:a405220cf420 283 {
igorsk 0:a405220cf420 284 TProcessMap Timeouted = Kernel.ReadyProcessMap; // Process has its tag set in ReadyProcessMap if timeout expired,
igorsk 0:a405220cf420 285 // or it was waked up by OS::ForceWakeUpProcess()
igorsk 0:a405220cf420 286 if( ProcessMap & ~Timeouted ) // if any process has to be waked up
igorsk 0:a405220cf420 287 {
igorsk 0:a405220cf420 288 SetPrioTag(Kernel.ReadyProcessMap, ProcessMap); // place all waiting processes to the ready map
igorsk 0:a405220cf420 289 ClrPrioTag(ProcessMap, ~Timeouted); // remove all non-timeouted processes from the waiting map.
igorsk 0:a405220cf420 290 Kernel.Scheduler();
igorsk 0:a405220cf420 291 return;
igorsk 0:a405220cf420 292 }
igorsk 0:a405220cf420 293 }
igorsk 0:a405220cf420 294
igorsk 0:a405220cf420 295 NonEmpty = true;
igorsk 0:a405220cf420 296 }
igorsk 0:a405220cf420 297 //------------------------------------------------------------------------------
igorsk 0:a405220cf420 298