embkernel
 All Classes Functions Variables Typedefs Groups Pages
Rtos.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
8 #include "Rtos.hpp"
9 #include "RtosTask.hpp"
10 #include "RtosList.hpp"
11 #include "RtosPortable.hpp"
12 #include "RtosHeap.hpp"
13 #include <string.h>
14 
15 Rtos rtos;
16 
19 RtosList Rtos::sListReady[RTOS_CFG_MAX_PRIORITIES];
22 size_t Rtos::sMaxPriorities = RTOS_CFG_MAX_PRIORITIES;
23 size_t Rtos::sCurrentTaskCount = 0;
24 void* Rtos::sMemToFree = 0;
25 RtosTask Rtos::sIdleTask(0, "idle", RTOS_CFG_MIN_STACK_SIZE, Rtos::idleRun);
26 
27 #if RTOS_CFG_TRACE_BUFFER_SIZE
28 Rtos::TRACE_BUFFER Rtos::sTraceBuffer;
29 #endif
30 
34 void Rtos::start() {
35  sMemToFree = 0;
36  sTick = 0xFFFFFFFF - 1234;
37 
39  schedule(sCurrentTask->mCurrentStackPointer);
40 
41 #if RTOS_CFG_TRACE_BUFFER_SIZE
42  clearTraceBuffer();
43 #endif
44  RtosPortable::start();
45 }
46 
51 void Rtos::sleep(TICK tick) {
52  if (!tick) { //Tick=0 -> return
53  return;
54  }
55 
56  RtosPortable::enterCriticalSection();
57 
59 
60  RtosPortable::yield();
61  RtosPortable::exitCriticalSection();
62 }
63 
68 void Rtos::sleepUntil(TICK tick) {
69  RtosPortable::enterCriticalSection();
70 
71  TICK ticksToSleep = 1;
72  if (!isElapsed(tick)) {
73  ticksToSleep = tick - sTick;
74  }
75 
76  putOnSleepingList(sCurrentTask, ticksToSleep);
77 
78  RtosPortable::yield();
79  RtosPortable::exitCriticalSection();
80 }
81 
87 bool Rtos::isElapsed(TICK tick) {
88  if ((sTick == tick)) {
89  return true;
90  }
91  TICK diff = tick - sTick;
92  if (diff > (TICK_MAX >> 1)) {
93  return true;
94  }
95  return false;
96 
97 }
98 
103 void Rtos::addTask(RtosTask* task) {
104  RtosPortable::enterCriticalSection();
106  sListReady[task->mPriority].insertAtBeginning(task->mIterableCore);
107  RtosPortable::exitCriticalSection();
108 }
109 
115  RtosPortable::enterCriticalSection();
116  if (task->mIterableCore.mListOwner) {
117  task->mIterableCore.mListOwner->remove(task->mIterableCore);
118  }
119  if (task->mIterableSyncObj.mListOwner) {
120  task->mIterableSyncObj.mListOwner->remove(task->mIterableCore);
121  }
123 
124  schedule(sCurrentTask->mCurrentStackPointer);
125 
126  sMemToFree = task->mStack;
127  RtosPortable::yield();
128  RtosPortable::exitCriticalSection();
129 }
130 
137  RTOS_ASSERT(!RtosPortable::isStackOverflow(task->mStack, task->mStackSize));
138 
139  task->mIsTimeout = false;
140 
141  RtosListIterable* iterable = &task->mIterableCore;
142 
143  iterable->mListOwner->remove(*iterable);
144 
145  if (tick == TICK_INFINITE) {
146  return;
147  }
148 
149  iterable->mSortValue = sTick + tick;
150  sListSleep.insertSorted(*iterable, sTick);
151 }
152 
158  RtosListIterable* iterable = &task->mIterableCore;
159  iterable->mListOwner->remove(*iterable);
160  sListSuspended.insertAtEnd(*iterable);
161 }
162 
166 void Rtos::onTick() {
167  sTick++;
168 
169  for (RtosListIterable* iterable = sListSleep.mFirst; iterable && (iterable->mSortValue == sTick);) {
170  RtosListIterable* next = iterable->mNext;
172 
173  RtosTask* task = iterable->mTaskOwner;
174 
175  if (task->mIterableSyncObj.mListOwner) { //Event timeout
176  task->mIsTimeout = true;
177  task->mIterableSyncObj.mListOwner->remove(task->mIterableSyncObj);
178  }
179 
180  sListReady[task->mPriority].insertAtBeginning(*iterable);
181 
182  iterable = next;
183  }
184 }
185 
190 void* Rtos::schedule(void* stackPointer) {
191  sCurrentTask->mCurrentStackPointer = stackPointer;
192 
193  //remove memory used by killed task
194  if (sMemToFree) {
196  sMemToFree = 0;
197  }
198 
199  RTOS_ASSERT(!RtosPortable::isStackOverflow(sCurrentTask->mStack, sCurrentTask->mStackSize)); //
200 
201 #if RTOS_CFG_TRACE_BUFFER_SIZE
202  RtosTask* previousTask = sCurrentTask;
203 #endif
204 
205  for (int i = RTOS_CFG_MAX_PRIORITIES - 1; i >= 0; i--) {
206  RtosListIterable* iterable = sListReady[i].getFirst();
207  if (iterable) {
208  sCurrentTask = iterable->mTaskOwner;
209  sListReady[i].insertAtEnd(sCurrentTask->mIterableCore);
210  break;
211  }
212  }
213 
214 #if RTOS_CFG_TRACE_BUFFER_SIZE
215  if (previousTask != sCurrentTask) {
216  if (sTraceBuffer.count < RTOS_CFG_TRACE_BUFFER_SIZE) {
217  sTraceBuffer.buffer[sTraceBuffer.indexIn].cycles = RtosPortable::getCyclesCounter();
218  sTraceBuffer.buffer[sTraceBuffer.indexIn].task = sCurrentTask;
219  sTraceBuffer.indexIn++;
220  if (sTraceBuffer.indexIn >= RTOS_CFG_TRACE_BUFFER_SIZE) {
221  sTraceBuffer.indexIn = 0;
222  }
223  sTraceBuffer.count++;
224  }
225  else {
226  sTraceBuffer.overloadError = true;
227  }
228  }
229 #endif
230 
231  return sCurrentTask->mCurrentStackPointer;
232 }
233 
238 void Rtos::idleRun(RtosTask* task) {
239  while (1) {
240 #if RTOS_CFG_USE_LOW_POWER_IN_IDLE
241  RTOS_LOW_POWER_MODE();
242 #else
243  RTOS_NOP();
244 #endif
245  }
246 }
247 
248 
249 
250 #if RTOS_CFG_TRACE_BUFFER_SIZE
251 int Rtos::getTraceBuffer(TRACE_TAG** p) {
252  if (sTraceBuffer.overloadError) {
253  return -1;
254  }
255  int count = sTraceBuffer.count;
256  if (count <= 0) {
257  return 0;
258  }
259  *p = &sTraceBuffer.buffer[sTraceBuffer.indexOut];
260  if (sTraceBuffer.indexOut + count > RTOS_CFG_TRACE_BUFFER_SIZE) {
261  count = RTOS_CFG_TRACE_BUFFER_SIZE - sTraceBuffer.indexOut;
262  sTraceBuffer.indexOut = 0;
263  }
264  else {
265  sTraceBuffer.indexOut += count;
266  }
267  return count;
268 }
269 
270 void Rtos::releaseBuffer(int count) {
271  RtosPortable::enterCriticalSection();
272  sTraceBuffer.count -= count;
273  RtosPortable::exitCriticalSection();
274 }
275 
276 void Rtos::clearTraceBuffer() {
277  RtosPortable::enterCriticalSection();
278  memset(&sTraceBuffer, 0, sizeof(sTraceBuffer));
279  RtosPortable::exitCriticalSection();
280 }
281 #endif
282