Dependencies:   mbed

Committer:
mbed714
Date:
Tue Sep 21 19:48:05 2010 +0000
Revision:
0:331db0b44b67

        

Who changed what in which revision?

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