OpenCores
URL https://opencores.org/ocsvn/plasma/plasma/trunk

Subversion Repositories plasma

[/] [plasma/] [trunk/] [kernel/] [rtos.c] - Blame information for rev 200

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 138 rhoads
/*--------------------------------------------------------------------
2
 * TITLE: Plasma Real Time Operating System
3
 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4
 * DATE CREATED: 12/17/05
5
 * FILENAME: rtos.c
6
 * PROJECT: Plasma CPU core
7
 * COPYRIGHT: Software placed into the public domain by the author.
8
 *    Software 'as is' without warranty.  Author liable for nothing.
9
 * DESCRIPTION:
10
 *    Plasma Real Time Operating System
11
 *    Fully pre-emptive RTOS with support for:
12
 *       Heaps, Threads, Semaphores, Mutexes, Message Queues, and Timers.
13
 *    This file tries to be hardware independent except for calls to:
14
 *       MemoryRead() and MemoryWrite() for interrupts.
15 167 rhoads
 *    Partial support for multiple CPUs using symmetric multiprocessing.
16 138 rhoads
 *--------------------------------------------------------------------*/
17
#include "plasma.h"
18
#include "rtos.h"
19
 
20
#define HEAP_MAGIC 0x1234abcd
21
#define THREAD_MAGIC 0x4321abcd
22
#define SEM_RESERVED_COUNT 2
23
#define HEAP_COUNT 8
24
 
25 167 rhoads
 
26 138 rhoads
/*************** Structures ***************/
27
#ifdef WIN32
28 189 rhoads
   #define setjmp _setjmp
29 138 rhoads
   //x86 registers
30
   typedef struct jmp_buf2 {
31
      uint32 Ebp, Ebx, Edi, Esi, sp, pc, extra[10];
32
   } jmp_buf2;
33 189 rhoads
#elif defined(ARM_CPU)
34
   //ARM registers
35
   typedef struct jmp_buf2 {
36
      uint32 r[13], sp, lr, pc, cpsr, extra[5];
37
   } jmp_buf2;
38 138 rhoads
#else  
39
   //Plasma registers
40
   typedef struct jmp_buf2 {
41
      uint32 s[9], gp, sp, pc;
42
   } jmp_buf2;
43
#endif
44
 
45
typedef struct HeapNode_s {
46
   struct HeapNode_s *next;
47
   int size;
48
} HeapNode_t;
49
 
50
struct OS_Heap_s {
51
   uint32 magic;
52
   const char *name;
53
   OS_Semaphore_t *semaphore;
54
   HeapNode_t *available;
55
   HeapNode_t base;
56
   struct OS_Heap_s *alternate;
57
};
58
//typedef struct OS_Heap_s OS_Heap_t;
59
 
60 168 rhoads
typedef enum {
61 176 rhoads
   THREAD_PEND    = 0,
62 168 rhoads
   THREAD_READY   = 1,
63
   THREAD_RUNNING = 2
64
} OS_ThreadState_e;
65
 
66 138 rhoads
struct OS_Thread_s {
67
   const char *name;
68 168 rhoads
   OS_ThreadState_e state;
69 189 rhoads
   int cpuIndex;
70 176 rhoads
   int cpuLock;
71 138 rhoads
   jmp_buf env;
72
   OS_FuncPtr_t funcPtr;
73
   void *arg;
74
   uint32 priority;
75
   uint32 ticksTimeout;
76
   void *info;
77
   OS_Semaphore_t *semaphorePending;
78
   int returnCode;
79 167 rhoads
   uint32 spinLocks;
80 189 rhoads
   uint32 processId;
81
   OS_Heap_t *heap;
82 138 rhoads
   struct OS_Thread_s *next, *prev;
83
   struct OS_Thread_s *nextTimeout, *prevTimeout;
84
   uint32 magic[1];
85
};
86
//typedef struct OS_Thread_s OS_Thread_t;
87
 
88
struct OS_Semaphore_s {
89
   const char *name;
90
   struct OS_Thread_s *threadHead;
91
   int count;
92
};
93
//typedef struct OS_Semaphore_s OS_Semaphore_t;
94
 
95
struct OS_Mutex_s {
96
   OS_Semaphore_t *semaphore;
97
   OS_Thread_t *thread;
98
   int count;
99
};
100
//typedef struct OS_Mutex_s OS_Mutex_t;
101
 
102
struct OS_MQueue_s {
103
   const char *name;
104
   OS_Semaphore_t *semaphore;
105
   int count, size, used, read, write;
106
};
107
//typedef struct OS_MQueue_s OS_MQueue_t;
108
 
109
struct OS_Timer_s {
110
   const char *name;
111
   struct OS_Timer_s *next, *prev;
112
   uint32 ticksTimeout;
113
   uint32 ticksRestart;
114
   int active;
115
   OS_MQueue_t *mqueue;
116
   uint32 info;
117
};
118
//typedef struct OS_Timer_s OS_Timer_t;
119
 
120
 
121
/*************** Globals ******************/
122
static OS_Heap_t *HeapArray[HEAP_COUNT];
123 189 rhoads
static OS_Thread_t *ThreadCurrent[OS_CPU_COUNT];
124
static OS_Thread_t *ThreadHead;   //Linked list of threads sorted by priority
125
static OS_Thread_t *TimeoutHead;  //Linked list of threads sorted by timeout
126 138 rhoads
static int ThreadSwapEnabled;
127
static int ThreadNeedReschedule;
128
static uint32 ThreadTime;
129
static void *NeedToFree;
130
static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT];
131 189 rhoads
static OS_Semaphore_t *SemaphoreSleep;
132
static OS_Semaphore_t *SemaphoreLock;
133
static OS_Semaphore_t *SemaphoreTimer;
134 138 rhoads
static OS_Timer_t *TimerHead;     //Linked list of timers sorted by timeout
135
static OS_FuncPtr_t Isr[32];
136
static int InterruptInside;
137 200 rhoads
int InitStack[128];               //Used by boot.asm
138 138 rhoads
 
139
 
140
/***************** Heap *******************/
141
/******************************************/
142 189 rhoads
OS_Heap_t *OS_HeapCreate(const char *name, void *memory, uint32 size)
143 138 rhoads
{
144
   OS_Heap_t *heap;
145
 
146 189 rhoads
   assert(((uint32)memory & 3) == 0);
147
   heap = (OS_Heap_t*)memory;
148 138 rhoads
   heap->magic = HEAP_MAGIC;
149 189 rhoads
   heap->name = name;
150
   heap->semaphore = OS_SemaphoreCreate(name, 1);
151 138 rhoads
   heap->available = (HeapNode_t*)(heap + 1);
152
   heap->available->next = &heap->base;
153 189 rhoads
   heap->available->size = (size - sizeof(OS_Heap_t)) / sizeof(HeapNode_t);
154 138 rhoads
   heap->base.next = heap->available;
155
   heap->base.size = 0;
156
   return heap;
157
}
158
 
159
 
160
/******************************************/
161 189 rhoads
void OS_HeapDestroy(OS_Heap_t *heap)
162 138 rhoads
{
163 189 rhoads
   OS_SemaphoreDelete(heap->semaphore);
164 138 rhoads
}
165
 
166
 
167
/******************************************/
168
//Modified from K&R
169 189 rhoads
void *OS_HeapMalloc(OS_Heap_t *heap, int bytes)
170 138 rhoads
{
171
   HeapNode_t *node, *prevp;
172
   int nunits;
173
 
174 189 rhoads
   if(heap == NULL && OS_ThreadSelf())
175
      heap = OS_ThreadSelf()->heap;
176
   if((uint32)heap < HEAP_COUNT)
177
      heap = HeapArray[(int)heap];
178
   nunits = (bytes + sizeof(HeapNode_t) - 1) / sizeof(HeapNode_t) + 1;
179
   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
180
   prevp = heap->available;
181 138 rhoads
   for(node = prevp->next; ; prevp = node, node = node->next)
182
   {
183
      if(node->size >= nunits)       //Big enough?
184
      {
185
         if(node->size == nunits)    //Exactly
186
            prevp->next = node->next;
187
         else
188
         {                           //Allocate tail end
189
            node->size -= nunits;
190
            node += node->size;
191
            node->size = nunits;
192
         }
193 189 rhoads
         heap->available = prevp;
194
         node->next = (HeapNode_t*)heap;
195
         OS_SemaphorePost(heap->semaphore);
196 138 rhoads
         return (void*)(node + 1);
197
      }
198 189 rhoads
      if(node == heap->available)   //Wrapped around free list
199 138 rhoads
      {
200 189 rhoads
         OS_SemaphorePost(heap->semaphore);
201
         if(heap->alternate)
202
            return OS_HeapMalloc(heap->alternate, bytes);
203 138 rhoads
         return NULL;
204
      }
205
   }
206
}
207
 
208
 
209
/******************************************/
210
//Modified from K&R
211 189 rhoads
void OS_HeapFree(void *block)
212 138 rhoads
{
213
   OS_Heap_t *heap;
214
   HeapNode_t *bp, *node;
215
 
216 189 rhoads
   assert(block);
217
   bp = (HeapNode_t*)block - 1;   //point to block header
218 138 rhoads
   heap = (OS_Heap_t*)bp->next;
219
   assert(heap->magic == HEAP_MAGIC);
220
   if(heap->magic != HEAP_MAGIC)
221
      return;
222
   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
223
   for(node = heap->available; !(node < bp && bp < node->next); node = node->next)
224
   {
225
      if(node >= node->next && (bp > node || bp < node->next))
226
         break;               //freed block at start or end of area
227
   }
228
 
229
   if(bp + bp->size == node->next)   //join to upper
230
   {
231
      bp->size += node->next->size;
232
      bp->next = node->next->next;
233
   }
234
   else
235
   {
236
      bp->next = node->next;
237
   }
238
 
239
   if(node + node->size == bp)       //join to lower
240
   {
241
      node->size += bp->size;
242
      node->next = bp->next;
243
   }
244
   else
245
      node->next = bp;
246
   heap->available = node;
247
   OS_SemaphorePost(heap->semaphore);
248
}
249
 
250
 
251
/******************************************/
252 189 rhoads
void OS_HeapAlternate(OS_Heap_t *heap, OS_Heap_t *alternate)
253 138 rhoads
{
254 189 rhoads
   heap->alternate = alternate;
255 138 rhoads
}
256
 
257
 
258
/******************************************/
259 189 rhoads
void OS_HeapRegister(void *index, OS_Heap_t *heap)
260 138 rhoads
{
261 189 rhoads
   if((uint32)index < HEAP_COUNT)
262
      HeapArray[(int)index] = heap;
263 138 rhoads
}
264
 
265
 
266
 
267
/***************** Thread *****************/
268
/******************************************/
269
//Linked list of threads sorted by priority
270
//Must be called with interrupts disabled
271
static void OS_ThreadPriorityInsert(OS_Thread_t **head, OS_Thread_t *thread)
272
{
273
   OS_Thread_t *node, *prev;
274
 
275
   prev = NULL;
276
   for(node = *head; node; node = node->next)
277
   {
278
      if(node->priority <= thread->priority)
279
         break;
280
      prev = node;
281
   }
282
 
283
   if(prev == NULL)
284
   {
285
      thread->next = *head;
286
      thread->prev = NULL;
287
      *head = thread;
288
   }
289
   else
290
   {
291
      if(prev->next)
292
         prev->next->prev = thread;
293
      thread->next = prev->next;
294
      thread->prev = prev;
295
      prev->next = thread;
296
   }
297
   assert(ThreadHead);
298 168 rhoads
   if(*head == ThreadHead)
299
      thread->state = THREAD_READY;
300 138 rhoads
}
301
 
302
 
303
/******************************************/
304
//Must be called with interrupts disabled
305
static void OS_ThreadPriorityRemove(OS_Thread_t **head, OS_Thread_t *thread)
306
{
307
   assert(thread->magic[0] == THREAD_MAGIC);  //check stack overflow
308
   if(thread->prev == NULL)
309
      *head = thread->next;
310
   else
311
      thread->prev->next = thread->next;
312
   if(thread->next)
313
      thread->next->prev = thread->prev;
314
   thread->next = NULL;
315
   thread->prev = NULL;
316 176 rhoads
   thread->state = THREAD_PEND;
317 138 rhoads
}
318
 
319
 
320
/******************************************/
321
//Linked list of threads sorted by timeout value
322
//Must be called with interrupts disabled
323
static void OS_ThreadTimeoutInsert(OS_Thread_t *thread)
324
{
325
   OS_Thread_t *node, *prev;
326
   int diff;
327
 
328
   prev = NULL;
329
   for(node = TimeoutHead; node; node = node->nextTimeout)
330
   {
331
      diff = thread->ticksTimeout - node->ticksTimeout;
332
      if(diff <= 0)
333
         break;
334
      prev = node;
335
   }
336
 
337
   if(prev == NULL)
338
   {
339
      thread->nextTimeout = TimeoutHead;
340
      thread->prevTimeout = NULL;
341 151 rhoads
      if(TimeoutHead)
342
         TimeoutHead->prevTimeout = thread;
343 138 rhoads
      TimeoutHead = thread;
344
   }
345
   else
346
   {
347
      if(prev->nextTimeout)
348
         prev->nextTimeout->prevTimeout = thread;
349
      thread->nextTimeout = prev->nextTimeout;
350
      thread->prevTimeout = prev;
351
      prev->nextTimeout = thread;
352
   }
353
}
354
 
355
 
356
/******************************************/
357
//Must be called with interrupts disabled
358
static void OS_ThreadTimeoutRemove(OS_Thread_t *thread)
359
{
360
   if(thread->prevTimeout == NULL && TimeoutHead != thread)
361
      return;         //not in list
362
   if(thread->prevTimeout == NULL)
363
      TimeoutHead = thread->nextTimeout;
364
   else
365
      thread->prevTimeout->nextTimeout = thread->nextTimeout;
366
   if(thread->nextTimeout)
367
      thread->nextTimeout->prevTimeout = thread->prevTimeout;
368
   thread->nextTimeout = NULL;
369
   thread->prevTimeout = NULL;
370
}
371
 
372
 
373 176 rhoads
#if OS_CPU_COUNT <= 1
374 138 rhoads
/******************************************/
375 151 rhoads
//Loads a new thread 
376 138 rhoads
//Must be called with interrupts disabled
377 189 rhoads
static void OS_ThreadReschedule(int roundRobin)
378 138 rhoads
{
379 176 rhoads
   OS_Thread_t *threadNext, *threadCurrent, *threadTry;
380 138 rhoads
   int rc;
381
 
382
   if(ThreadSwapEnabled == 0 || InterruptInside)
383
   {
384 189 rhoads
      ThreadNeedReschedule |= 2 + roundRobin;  //Reschedule later
385 138 rhoads
      return;
386
   }
387
 
388
   //Determine which thread should run
389 176 rhoads
   threadCurrent = ThreadCurrent[0];
390 167 rhoads
   threadNext = threadCurrent;
391 176 rhoads
   if(threadCurrent == NULL || threadCurrent->state == THREAD_PEND)
392
      threadNext = ThreadHead;
393
   else if(threadCurrent->priority < ThreadHead->priority)
394
      threadNext = ThreadHead;
395 189 rhoads
   else if(roundRobin)
396 176 rhoads
   {
397
      //Determine next ready thread with same priority
398
      threadTry = threadCurrent->next;
399
      if(threadTry && threadTry->priority == threadCurrent->priority)
400
         threadNext = threadTry;
401
      else
402
         threadNext = ThreadHead;
403
   }
404
 
405
   if(threadNext != threadCurrent)
406
   {
407
      //Swap threads
408
      ThreadCurrent[0] = threadNext;
409
      assert(threadNext);
410
      if(threadCurrent)
411
      {
412
         assert(threadCurrent->magic[0] == THREAD_MAGIC); //check stack overflow
413
         rc = setjmp(threadCurrent->env);  //ANSI C call to save registers
414
         if(rc)
415
         {
416
            //Returned from longjmp()
417
            return;
418
         }
419
      }
420
 
421
      threadNext = ThreadCurrent[0];       //removed warning
422
      longjmp(threadNext->env, 1);         //ANSI C call to restore registers
423
   }
424
}
425
 
426 189 rhoads
#else //OS_CPU_COUNT > 1
427 176 rhoads
 
428
/******************************************/
429 189 rhoads
//Check if a different CPU needs to swap threads
430
static void OS_ThreadRescheduleCheck(void)
431 176 rhoads
{
432 189 rhoads
   OS_Thread_t *threadBest;
433
   uint32 i, priorityLow, cpuIndex = OS_CpuIndex();
434
   int cpuLow;
435 176 rhoads
 
436 189 rhoads
   //Find the CPU running the lowest priority thread
437 176 rhoads
   cpuLow = 0;
438
   priorityLow = 0xffffffff;
439
   for(i = 0; i < OS_CPU_COUNT; ++i)
440
   {
441
      if(i != cpuIndex && (ThreadCurrent[i] == NULL ||
442
         ThreadCurrent[i]->priority < priorityLow))
443
      {
444
         cpuLow = i;
445
         if(ThreadCurrent[i])
446
            priorityLow = ThreadCurrent[i]->priority;
447
         else
448
            priorityLow = 0;
449
      }
450
   }
451
 
452 189 rhoads
   //Determine highest priority ready thread for other CPUs
453
   for(threadBest = ThreadHead; threadBest && threadBest->priority > priorityLow;
454
      threadBest = threadBest->next)
455
   {
456
      if(threadBest->state == THREAD_READY)
457
      {
458
         if(threadBest->cpuLock == -1)
459
         {
460
            OS_CpuInterrupt(cpuLow, 1);  //Reschedule on the other CPU
461
            break;
462
         }
463
         else if(threadBest->priority > ThreadCurrent[threadBest->cpuLock]->priority)
464
         {
465
            OS_CpuInterrupt(threadBest->cpuLock, 1);  //Reschedule on the other CPU
466
            break;
467
         }
468
      }
469
   }
470
}
471
 
472
 
473
/******************************************/
474
//Loads a new thread in a multiprocessor environment
475
//Must be called with interrupts disabled
476
static void OS_ThreadReschedule(int roundRobin)
477
{
478
   OS_Thread_t *threadNext, *threadCurrent, *threadBest, *threadAlt;
479
   uint32 cpuIndex = OS_CpuIndex();
480
   int rc;
481
 
482
   if(ThreadSwapEnabled == 0 || InterruptInside)
483
   {
484
      ThreadNeedReschedule |= 2 + roundRobin;  //Reschedule later
485
      return;
486
   }
487
 
488
   //Determine highest priority ready thread
489 168 rhoads
   for(threadBest = ThreadHead; threadBest; threadBest = threadBest->next)
490
   {
491 176 rhoads
      if(threadBest->state == THREAD_READY &&
492
         (threadBest->cpuLock == -1 || threadBest->cpuLock == (int)cpuIndex))
493 168 rhoads
         break;
494
   }
495 176 rhoads
 
496
   //Determine which thread should run
497
   threadCurrent = ThreadCurrent[cpuIndex];
498
   threadNext = threadCurrent;
499
   if(threadCurrent == NULL || threadCurrent->state == THREAD_PEND)
500
   {
501 168 rhoads
      threadNext = threadBest;
502 176 rhoads
   }
503
   else if(threadBest && threadCurrent->priority < threadBest->priority)
504
   {
505 168 rhoads
      threadNext = threadBest;
506 176 rhoads
   }
507 189 rhoads
   else if(roundRobin)
508 138 rhoads
   {
509 176 rhoads
      //Find the next ready thread
510
      for(threadAlt = threadCurrent->next; threadAlt; threadAlt = threadAlt->next)
511 168 rhoads
      {
512 176 rhoads
         if(threadAlt->state == THREAD_READY &&
513
            (threadAlt->cpuLock == -1 || threadAlt->cpuLock == (int)cpuIndex))
514 168 rhoads
            break;
515
      }
516 176 rhoads
      if(threadAlt && threadAlt->priority == threadCurrent->priority)
517
         threadNext = threadAlt;
518
      else if(threadBest && threadBest->priority >= threadCurrent->priority)
519 168 rhoads
         threadNext = threadBest;
520 138 rhoads
   }
521
 
522 167 rhoads
   if(threadNext != threadCurrent)
523 138 rhoads
   {
524
      //Swap threads
525 167 rhoads
      ThreadCurrent[cpuIndex] = threadNext;
526
      assert(threadNext);
527 168 rhoads
      if(threadCurrent)
528 138 rhoads
      {
529 168 rhoads
         assert(threadCurrent->magic[0] == THREAD_MAGIC); //check stack overflow
530
         threadCurrent->state = THREAD_READY;
531 176 rhoads
         threadCurrent->spinLocks = OS_SpinCountGet();
532 189 rhoads
         threadCurrent->cpuIndex = -1;
533 176 rhoads
         rc = setjmp(threadCurrent->env);   //ANSI C call to save registers
534 138 rhoads
         if(rc)
535
         {
536
            //Returned from longjmp()
537
            return;
538
         }
539
      }
540 168 rhoads
 
541 176 rhoads
      //Restore spin lock count
542 167 rhoads
      cpuIndex = OS_CpuIndex();             //removed warning
543
      threadNext = ThreadCurrent[cpuIndex]; //removed warning
544 176 rhoads
      threadNext->state = THREAD_RUNNING;
545
      OS_SpinCountSet(threadNext->spinLocks);
546 189 rhoads
      threadNext->cpuIndex = (int)cpuIndex;
547
      OS_ThreadRescheduleCheck();
548 176 rhoads
      longjmp(threadNext->env, 1);          //ANSI C call to restore registers
549 138 rhoads
   }
550 189 rhoads
   OS_ThreadRescheduleCheck();
551 138 rhoads
}
552
 
553
 
554 189 rhoads
/******************************************/
555 176 rhoads
void OS_ThreadCpuLock(OS_Thread_t *Thread, int CpuIndex)
556
{
557
   Thread->cpuLock = CpuIndex;
558
   if(Thread == OS_ThreadSelf() && CpuIndex != (int)OS_CpuIndex())
559
      OS_ThreadSleep(1);
560
}
561
 
562
#endif //#if OS_CPU_COUNT <= 1
563
 
564
 
565 138 rhoads
/******************************************/
566 189 rhoads
static void OS_ThreadInit(void *arg)
567 138 rhoads
{
568 167 rhoads
   uint32 cpuIndex = OS_CpuIndex();
569 189 rhoads
   (void)arg;
570 138 rhoads
 
571 168 rhoads
   OS_CriticalEnd(1);
572 167 rhoads
   ThreadCurrent[cpuIndex]->funcPtr(ThreadCurrent[cpuIndex]->arg);
573 138 rhoads
   OS_ThreadExit();
574
}
575
 
576
 
577
/******************************************/
578
//Stops warning "argument X might be clobbered by `longjmp'"
579
static void OS_ThreadRegsInit(jmp_buf env)
580
{
581
   setjmp(env); //ANSI C call to save registers
582
}
583
 
584
 
585
/******************************************/
586 189 rhoads
OS_Thread_t *OS_ThreadCreate(const char *name,
587
                             OS_FuncPtr_t funcPtr,
588
                             void *arg,
589
                             uint32 priority,
590
                             uint32 stackSize)
591 138 rhoads
{
592
   OS_Thread_t *thread;
593
   uint8 *stack;
594
   jmp_buf2 *env;
595
   uint32 state;
596
 
597
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
598
   if(NeedToFree)
599
      OS_HeapFree(NeedToFree);
600
   NeedToFree = NULL;
601
   OS_SemaphorePost(SemaphoreLock);
602
 
603 189 rhoads
   if(stackSize == 0)
604
      stackSize = STACK_SIZE_DEFAULT;
605
   if(stackSize < STACK_SIZE_MINIMUM)
606
      stackSize = STACK_SIZE_MINIMUM;
607
   thread = (OS_Thread_t*)OS_HeapMalloc(NULL, sizeof(OS_Thread_t) + stackSize);
608 138 rhoads
   assert(thread);
609
   if(thread == NULL)
610
      return NULL;
611 189 rhoads
   memset(thread, 0, sizeof(OS_Thread_t));
612 138 rhoads
   stack = (uint8*)(thread + 1);
613 189 rhoads
   memset(stack, 0xcd, stackSize);
614 138 rhoads
 
615 189 rhoads
   thread->name = name;
616 168 rhoads
   thread->state = THREAD_READY;
617 176 rhoads
   thread->cpuLock = -1;
618 189 rhoads
   thread->funcPtr = funcPtr;
619
   thread->arg = arg;
620
   thread->priority = priority;
621 138 rhoads
   thread->info = NULL;
622
   thread->semaphorePending = NULL;
623
   thread->returnCode = 0;
624 167 rhoads
   thread->spinLocks = 1;
625 189 rhoads
   if(OS_ThreadSelf())
626
   {
627
      thread->processId = OS_ThreadSelf()->processId;
628
      thread->heap = OS_ThreadSelf()->heap;
629
   }
630
   else
631
   {
632
      thread->processId = 0;
633
      thread->heap = NULL;
634
   }
635 138 rhoads
   thread->next = NULL;
636
   thread->prev = NULL;
637
   thread->nextTimeout = NULL;
638
   thread->prevTimeout = NULL;
639
   thread->magic[0] = THREAD_MAGIC;
640
 
641
   OS_ThreadRegsInit(thread->env);
642
   env = (jmp_buf2*)thread->env;
643 200 rhoads
   env->sp = (uint32)stack + stackSize - 24; //minimum stack frame size
644 138 rhoads
   env->pc = (uint32)OS_ThreadInit;
645
 
646
   state = OS_CriticalBegin();
647
   OS_ThreadPriorityInsert(&ThreadHead, thread);
648
   OS_ThreadReschedule(0);
649
   OS_CriticalEnd(state);
650
   return thread;
651
}
652
 
653
 
654
/******************************************/
655
void OS_ThreadExit(void)
656
{
657 167 rhoads
   uint32 state, cpuIndex = OS_CpuIndex();
658 138 rhoads
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
659
   if(NeedToFree)
660
      OS_HeapFree(NeedToFree);
661
   NeedToFree = NULL;
662
   OS_SemaphorePost(SemaphoreLock);
663
 
664
   state = OS_CriticalBegin();
665 167 rhoads
   OS_ThreadPriorityRemove(&ThreadHead, ThreadCurrent[cpuIndex]);
666
   NeedToFree = ThreadCurrent[cpuIndex];
667 138 rhoads
   OS_ThreadReschedule(0);
668
   OS_CriticalEnd(state);
669
}
670
 
671
 
672
/******************************************/
673
OS_Thread_t *OS_ThreadSelf(void)
674
{
675 167 rhoads
   return ThreadCurrent[OS_CpuIndex()];
676 138 rhoads
}
677
 
678
 
679
/******************************************/
680 189 rhoads
void OS_ThreadSleep(int ticks)
681 138 rhoads
{
682 189 rhoads
   OS_SemaphorePend(SemaphoreSleep, ticks);
683 138 rhoads
}
684
 
685
 
686
/******************************************/
687
uint32 OS_ThreadTime(void)
688
{
689
   return ThreadTime;
690
}
691
 
692
 
693
/******************************************/
694 189 rhoads
void OS_ThreadInfoSet(OS_Thread_t *thread, void *Info)
695 138 rhoads
{
696 189 rhoads
   thread->info = Info;
697 138 rhoads
}
698
 
699
 
700
/******************************************/
701 189 rhoads
void *OS_ThreadInfoGet(OS_Thread_t *thread)
702 138 rhoads
{
703 189 rhoads
   return thread->info;
704 138 rhoads
}
705
 
706
 
707
/******************************************/
708 189 rhoads
uint32 OS_ThreadPriorityGet(OS_Thread_t *thread)
709 138 rhoads
{
710 189 rhoads
   return thread->priority;
711 138 rhoads
}
712
 
713
 
714
/******************************************/
715 189 rhoads
void OS_ThreadPrioritySet(OS_Thread_t *thread, uint32 priority)
716 138 rhoads
{
717
   uint32 state;
718
   state = OS_CriticalBegin();
719 189 rhoads
   thread->priority = priority;
720
   if(thread->state != THREAD_PEND)
721 168 rhoads
   {
722 189 rhoads
      OS_ThreadPriorityRemove(&ThreadHead, thread);
723
      OS_ThreadPriorityInsert(&ThreadHead, thread);
724 168 rhoads
      OS_ThreadReschedule(0);
725
   }
726 138 rhoads
   OS_CriticalEnd(state);
727
}
728
 
729
 
730
/******************************************/
731 189 rhoads
void OS_ThreadProcessId(OS_Thread_t *thread, uint32 processId, OS_Heap_t *heap)
732
{
733
   thread->processId = processId;
734
   thread->heap = heap;
735
}
736
 
737
 
738
/******************************************/
739 138 rhoads
//Must be called with interrupts disabled
740
void OS_ThreadTick(void *Arg)
741
{
742
   OS_Thread_t *thread;
743
   OS_Semaphore_t *semaphore;
744
   int diff;
745
   (void)Arg;
746
 
747
   ++ThreadTime;
748
   while(TimeoutHead)
749
   {
750
      thread = TimeoutHead;
751
      diff = ThreadTime - thread->ticksTimeout;
752
      if(diff < 0)
753
         break;
754
      OS_ThreadTimeoutRemove(thread);
755
      semaphore = thread->semaphorePending;
756
      ++semaphore->count;
757
      thread->semaphorePending = NULL;
758
      thread->returnCode = -1;
759
      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
760
      OS_ThreadPriorityInsert(&ThreadHead, thread);
761
   }
762
   OS_ThreadReschedule(1);
763
}
764
 
765
 
766
 
767
/***************** Semaphore **************/
768
/******************************************/
769 189 rhoads
OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count)
770 138 rhoads
{
771
   OS_Semaphore_t *semaphore;
772 189 rhoads
   static int semCount = 0;
773 138 rhoads
 
774
   if(semCount < SEM_RESERVED_COUNT)
775 189 rhoads
      semaphore = &SemaphoreReserved[semCount++];  //Heap not ready yet
776 138 rhoads
   else
777 189 rhoads
      semaphore = (OS_Semaphore_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Semaphore_t));
778 138 rhoads
   assert(semaphore);
779
   if(semaphore == NULL)
780
      return NULL;
781
 
782 189 rhoads
   semaphore->name = name;
783 138 rhoads
   semaphore->threadHead = NULL;
784 189 rhoads
   semaphore->count = count;
785 138 rhoads
   return semaphore;
786
}
787
 
788
 
789
/******************************************/
790 189 rhoads
void OS_SemaphoreDelete(OS_Semaphore_t *semaphore)
791 138 rhoads
{
792 189 rhoads
   while(semaphore->threadHead)
793
      OS_SemaphorePost(semaphore);
794
   OS_HeapFree(semaphore);
795 138 rhoads
}
796
 
797
 
798
/******************************************/
799 189 rhoads
int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks)
800 138 rhoads
{
801 167 rhoads
   uint32 state, cpuIndex;
802 138 rhoads
   OS_Thread_t *thread;
803
   int returnCode=0;
804
 
805 189 rhoads
   assert(semaphore);
806 151 rhoads
   assert(InterruptInside == 0);
807 138 rhoads
   state = OS_CriticalBegin();
808 189 rhoads
   if(--semaphore->count < 0)
809 138 rhoads
   {
810 189 rhoads
      if(ticks == 0)
811 138 rhoads
      {
812 189 rhoads
         ++semaphore->count;
813 138 rhoads
         OS_CriticalEnd(state);
814
         return -1;
815
      }
816 189 rhoads
      cpuIndex = OS_CpuIndex();
817 167 rhoads
      thread = ThreadCurrent[cpuIndex];
818 189 rhoads
      assert(thread);
819
      thread->semaphorePending = semaphore;
820
      thread->ticksTimeout = ticks + OS_ThreadTime();
821 138 rhoads
      OS_ThreadPriorityRemove(&ThreadHead, thread);
822 189 rhoads
      OS_ThreadPriorityInsert(&semaphore->threadHead, thread);
823
      if(ticks != OS_WAIT_FOREVER)
824 138 rhoads
         OS_ThreadTimeoutInsert(thread);
825
      assert(ThreadHead);
826
      OS_ThreadReschedule(0);
827
      returnCode = thread->returnCode;
828
   }
829
   OS_CriticalEnd(state);
830
   return returnCode;
831
}
832
 
833
 
834
/******************************************/
835 189 rhoads
void OS_SemaphorePost(OS_Semaphore_t *semaphore)
836 138 rhoads
{
837
   uint32 state;
838 146 rhoads
   OS_Thread_t *thread;
839 138 rhoads
 
840 189 rhoads
   assert(semaphore);
841 138 rhoads
   state = OS_CriticalBegin();
842 189 rhoads
   if(++semaphore->count <= 0)
843 138 rhoads
   {
844 189 rhoads
      thread = semaphore->threadHead;
845 138 rhoads
      OS_ThreadTimeoutRemove(thread);
846 189 rhoads
      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
847 138 rhoads
      OS_ThreadPriorityInsert(&ThreadHead, thread);
848
      thread->semaphorePending = NULL;
849
      thread->returnCode = 0;
850 146 rhoads
      OS_ThreadReschedule(0);
851 138 rhoads
   }
852
   OS_CriticalEnd(state);
853
}
854
 
855
 
856
 
857
/***************** Mutex ******************/
858
/******************************************/
859 189 rhoads
OS_Mutex_t *OS_MutexCreate(const char *name)
860 138 rhoads
{
861
   OS_Mutex_t *mutex;
862
 
863 189 rhoads
   mutex = (OS_Mutex_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Mutex_t));
864 138 rhoads
   if(mutex == NULL)
865
      return NULL;
866 189 rhoads
   mutex->semaphore = OS_SemaphoreCreate(name, 1);
867 138 rhoads
   if(mutex->semaphore == NULL)
868
      return NULL;
869
   mutex->thread = NULL;
870
   mutex->count = 0;
871
   return mutex;
872
}
873
 
874
 
875
/******************************************/
876 189 rhoads
void OS_MutexDelete(OS_Mutex_t *mutex)
877 138 rhoads
{
878 189 rhoads
   OS_SemaphoreDelete(mutex->semaphore);
879
   OS_HeapFree(mutex);
880 138 rhoads
}
881
 
882
 
883
/******************************************/
884 189 rhoads
void OS_MutexPend(OS_Mutex_t *mutex)
885 138 rhoads
{
886
   OS_Thread_t *thread;
887
 
888 189 rhoads
   assert(mutex);
889 138 rhoads
   thread = OS_ThreadSelf();
890 189 rhoads
   if(thread == mutex->thread)
891 138 rhoads
   {
892 189 rhoads
      ++mutex->count;
893 138 rhoads
      return;
894
   }
895 189 rhoads
   OS_SemaphorePend(mutex->semaphore, OS_WAIT_FOREVER);
896
   mutex->thread = thread;
897
   mutex->count = 1;
898 138 rhoads
}
899
 
900
 
901
/******************************************/
902 189 rhoads
void OS_MutexPost(OS_Mutex_t *mutex)
903 138 rhoads
{
904 189 rhoads
   assert(mutex);
905
   assert(mutex->thread == OS_ThreadSelf());
906
   assert(mutex->count > 0);
907
   if(--mutex->count <= 0)
908 138 rhoads
   {
909 189 rhoads
      mutex->thread = NULL;
910
      OS_SemaphorePost(mutex->semaphore);
911 138 rhoads
   }
912
}
913
 
914
 
915
 
916
/***************** MQueue *****************/
917
/******************************************/
918 189 rhoads
OS_MQueue_t *OS_MQueueCreate(const char *name,
919
                             int messageCount,
920
                             int messageBytes)
921 138 rhoads
{
922
   OS_MQueue_t *queue;
923
   int size;
924
 
925 189 rhoads
   size = messageBytes / sizeof(uint32);
926
   queue = (OS_MQueue_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_MQueue_t) +
927
      messageCount * size * 4);
928 138 rhoads
   if(queue == NULL)
929
      return queue;
930 189 rhoads
   queue->name = name;
931
   queue->semaphore = OS_SemaphoreCreate(name, 0);
932 138 rhoads
   if(queue->semaphore == NULL)
933
      return NULL;
934 189 rhoads
   queue->count = messageCount;
935 138 rhoads
   queue->size = size;
936
   queue->used = 0;
937
   queue->read = 0;
938
   queue->write = 0;
939
   return queue;
940
}
941
 
942
 
943
/******************************************/
944 189 rhoads
void OS_MQueueDelete(OS_MQueue_t *mQueue)
945 138 rhoads
{
946 189 rhoads
   OS_SemaphoreDelete(mQueue->semaphore);
947
   OS_HeapFree(mQueue);
948 138 rhoads
}
949
 
950
 
951
/******************************************/
952 189 rhoads
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
953 138 rhoads
{
954
   uint32 state, *dst, *src;
955
   int i;
956
 
957 189 rhoads
   assert(mQueue);
958
   src = (uint32*)message;
959 138 rhoads
   state = OS_CriticalBegin();
960 189 rhoads
   if(++mQueue->used > mQueue->count)
961 138 rhoads
   {
962 189 rhoads
      --mQueue->used;
963 138 rhoads
      OS_CriticalEnd(state);
964
      return -1;
965
   }
966 189 rhoads
   dst = (uint32*)(mQueue + 1) + mQueue->write * mQueue->size;
967
   for(i = 0; i < mQueue->size; ++i)
968 138 rhoads
      dst[i] = src[i];
969 189 rhoads
   if(++mQueue->write >= mQueue->count)
970
      mQueue->write = 0;
971 138 rhoads
   OS_CriticalEnd(state);
972 189 rhoads
   OS_SemaphorePost(mQueue->semaphore);
973 138 rhoads
   return 0;
974
}
975
 
976
 
977
/******************************************/
978 189 rhoads
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
979 138 rhoads
{
980
   uint32 state, *dst, *src;
981
   int i, rc;
982
 
983 189 rhoads
   assert(mQueue);
984
   dst = (uint32*)message;
985
   rc = OS_SemaphorePend(mQueue->semaphore, ticks);
986 138 rhoads
   if(rc)
987
      return rc;
988
   state = OS_CriticalBegin();
989 189 rhoads
   --mQueue->used;
990
   src = (uint32*)(mQueue + 1) + mQueue->read * mQueue->size;
991
   for(i = 0; i < mQueue->size; ++i)
992 138 rhoads
      dst[i] = src[i];
993 189 rhoads
   if(++mQueue->read >= mQueue->count)
994
      mQueue->read = 0;
995 138 rhoads
   OS_CriticalEnd(state);
996
   return 0;
997
}
998
 
999
 
1000
 
1001
/***************** Timer ******************/
1002
/******************************************/
1003 189 rhoads
static void OS_TimerThread(void *arg)
1004 138 rhoads
{
1005
   uint32 timeNow;
1006
   int diff, ticks;
1007
   uint32 message[8];
1008
   OS_Timer_t *timer;
1009 189 rhoads
   (void)arg;
1010 138 rhoads
 
1011
   timeNow = OS_ThreadTime();
1012
   for(;;)
1013
   {
1014
      //Determine how long to sleep
1015
      OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1016
      if(TimerHead)
1017
         ticks = TimerHead->ticksTimeout - timeNow;
1018
      else
1019
         ticks = OS_WAIT_FOREVER;
1020
      OS_SemaphorePost(SemaphoreLock);
1021
      OS_SemaphorePend(SemaphoreTimer, ticks);
1022
 
1023
      //Send messages for all timed out timers
1024
      timeNow = OS_ThreadTime();
1025
      for(;;)
1026
      {
1027 189 rhoads
         timer = NULL;
1028 138 rhoads
         OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1029 189 rhoads
         if(TimerHead)
1030 138 rhoads
         {
1031 189 rhoads
            diff = timeNow - TimerHead->ticksTimeout;
1032
            if(diff >= 0)
1033
               timer = TimerHead;
1034 138 rhoads
         }
1035 189 rhoads
         OS_SemaphorePost(SemaphoreLock);
1036
         if(timer == NULL)
1037 138 rhoads
            break;
1038
         if(timer->ticksRestart)
1039
            OS_TimerStart(timer, timer->ticksRestart, timer->ticksRestart);
1040
         else
1041
            OS_TimerStop(timer);
1042
 
1043
         //Send message
1044
         message[0] = MESSAGE_TYPE_TIMER;
1045
         message[1] = (uint32)timer;
1046
         message[2] = (uint32)timer->info;
1047
         OS_MQueueSend(timer->mqueue, message);
1048
      }
1049
   }
1050
}
1051
 
1052
 
1053
/******************************************/
1054 189 rhoads
OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info)
1055 138 rhoads
{
1056
   OS_Timer_t *timer;
1057
   int startThread=0;
1058
 
1059
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1060
   if(SemaphoreTimer == NULL)
1061
   {
1062
      SemaphoreTimer = OS_SemaphoreCreate("Timer", 0);
1063
      startThread = 1;
1064
   }
1065
   OS_SemaphorePost(SemaphoreLock);
1066
   if(startThread)
1067
      OS_ThreadCreate("Timer", OS_TimerThread, NULL, 250, 2000);
1068
 
1069 189 rhoads
   timer = (OS_Timer_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Timer_t));
1070 138 rhoads
   if(timer == NULL)
1071
      return NULL;
1072 189 rhoads
   timer->name = name;
1073
   timer->mqueue = mQueue;
1074 138 rhoads
   timer->next = NULL;
1075
   timer->prev = NULL;
1076 189 rhoads
   timer->info = info;
1077 138 rhoads
   timer->active = 0;
1078
   return timer;
1079
}
1080
 
1081
 
1082
/******************************************/
1083 189 rhoads
void OS_TimerDelete(OS_Timer_t *timer)
1084 138 rhoads
{
1085 189 rhoads
   OS_TimerStop(timer);
1086
   OS_HeapFree(timer);
1087 138 rhoads
}
1088
 
1089
 
1090
/******************************************/
1091
//Must not be called from an ISR
1092 189 rhoads
void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart)
1093 138 rhoads
{
1094
   OS_Timer_t *node, *prev;
1095
   int diff, check=0;
1096
 
1097 189 rhoads
   assert(timer);
1098 167 rhoads
   assert(InterruptInside == 0);
1099 189 rhoads
   ticks += OS_ThreadTime();
1100
   if(timer->active)
1101
      OS_TimerStop(timer);
1102 138 rhoads
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1103 189 rhoads
   if(timer->active)
1104
   {
1105
      //Prevent race condition
1106
      OS_SemaphorePost(SemaphoreLock);
1107
      return;
1108
   }
1109
   timer->ticksTimeout = ticks;
1110
   timer->ticksRestart = ticksRestart;
1111
   timer->active = 1;
1112 138 rhoads
   prev = NULL;
1113
   for(node = TimerHead; node; node = node->next)
1114
   {
1115 189 rhoads
      diff = ticks - node->ticksTimeout;
1116 138 rhoads
      if(diff <= 0)
1117
         break;
1118
      prev = node;
1119
   }
1120 189 rhoads
   timer->next = node;
1121
   timer->prev = prev;
1122 138 rhoads
   if(node)
1123 189 rhoads
      node->prev = timer;
1124 138 rhoads
   if(prev == NULL)
1125
   {
1126 189 rhoads
      TimerHead = timer;
1127 138 rhoads
      check = 1;
1128
   }
1129
   else
1130 189 rhoads
      prev->next = timer;
1131 138 rhoads
   OS_SemaphorePost(SemaphoreLock);
1132
   if(check)
1133
      OS_SemaphorePost(SemaphoreTimer);
1134
}
1135
 
1136
 
1137
/******************************************/
1138
//Must not be called from an ISR
1139 189 rhoads
void OS_TimerStop(OS_Timer_t *timer)
1140 138 rhoads
{
1141 189 rhoads
   assert(timer);
1142 167 rhoads
   assert(InterruptInside == 0);
1143 138 rhoads
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
1144 189 rhoads
   if(timer->active)
1145 138 rhoads
   {
1146 189 rhoads
      timer->active = 0;
1147
      if(timer->prev == NULL)
1148
         TimerHead = timer->next;
1149 138 rhoads
      else
1150 189 rhoads
         timer->prev->next = timer->next;
1151
      if(timer->next)
1152
         timer->next->prev = timer->prev;
1153 138 rhoads
   }
1154
   OS_SemaphorePost(SemaphoreLock);
1155
}
1156
 
1157
 
1158
/***************** ISR ********************/
1159
/******************************************/
1160 189 rhoads
void OS_InterruptServiceRoutine(uint32 status, uint32 *stack)
1161 138 rhoads
{
1162
   int i;
1163 167 rhoads
   uint32 state;
1164 138 rhoads
 
1165 189 rhoads
   if(status == 0 && Isr[31])
1166
      Isr[31](stack);                   //SYSCALL or BREAK
1167
 
1168 138 rhoads
   InterruptInside = 1;
1169
   i = 0;
1170
   do
1171
   {
1172 189 rhoads
      if(status & 1)
1173 138 rhoads
      {
1174
         if(Isr[i])
1175 189 rhoads
            Isr[i](stack);
1176 138 rhoads
         else
1177
            OS_InterruptMaskClear(1 << i);
1178
      }
1179 189 rhoads
      status >>= 1;
1180 138 rhoads
      ++i;
1181 189 rhoads
   } while(status);
1182 138 rhoads
   InterruptInside = 0;
1183
 
1184 167 rhoads
   state = OS_SpinLock();
1185 138 rhoads
   if(ThreadNeedReschedule)
1186
      OS_ThreadReschedule(ThreadNeedReschedule & 1);
1187 167 rhoads
   OS_SpinUnlock(state);
1188 138 rhoads
}
1189
 
1190
 
1191
/******************************************/
1192 189 rhoads
void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr)
1193 138 rhoads
{
1194
   int i;
1195
 
1196
   for(i = 0; i < 32; ++i)
1197
   {
1198 189 rhoads
      if(mask & (1 << i))
1199
         Isr[i] = funcPtr;
1200 138 rhoads
   }
1201
}
1202
 
1203
 
1204
/******************************************/
1205
//Plasma hardware dependent
1206
uint32 OS_InterruptStatus(void)
1207
{
1208
   return MemoryRead(IRQ_STATUS);
1209
}
1210
 
1211
 
1212
/******************************************/
1213
//Plasma hardware dependent
1214 189 rhoads
uint32 OS_InterruptMaskSet(uint32 mask)
1215 138 rhoads
{
1216 189 rhoads
   uint32 state;
1217 138 rhoads
   state = OS_CriticalBegin();
1218 189 rhoads
   mask |= MemoryRead(IRQ_MASK);
1219 138 rhoads
   MemoryWrite(IRQ_MASK, mask);
1220
   OS_CriticalEnd(state);
1221
   return mask;
1222
}
1223
 
1224
 
1225
/******************************************/
1226
//Plasma hardware dependent
1227 189 rhoads
uint32 OS_InterruptMaskClear(uint32 mask)
1228 138 rhoads
{
1229 189 rhoads
   uint32 state;
1230 138 rhoads
   state = OS_CriticalBegin();
1231 189 rhoads
   mask = MemoryRead(IRQ_MASK) & ~mask;
1232 138 rhoads
   MemoryWrite(IRQ_MASK, mask);
1233
   OS_CriticalEnd(state);
1234
   return mask;
1235
}
1236
 
1237
 
1238
/**************** Init ********************/
1239
/******************************************/
1240
static volatile uint32 IdleCount;
1241 189 rhoads
static void OS_IdleThread(void *arg)
1242 138 rhoads
{
1243 189 rhoads
   (void)arg;
1244 138 rhoads
 
1245 151 rhoads
   //Don't block in the idle thread!
1246 138 rhoads
   for(;;)
1247
   {
1248
      ++IdleCount;
1249
   }
1250
}
1251
 
1252
 
1253
/******************************************/
1254
#ifndef DISABLE_IRQ_SIM
1255 189 rhoads
static void OS_IdleSimulateIsr(void *arg)
1256 138 rhoads
{
1257
   uint32 count=0, value;
1258 189 rhoads
   (void)arg;
1259 138 rhoads
 
1260
   for(;;)
1261
   {
1262
      MemoryRead(IRQ_MASK + 4);       //calls Sleep(10)
1263
#if WIN32
1264
      while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE)
1265 176 rhoads
         OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE, 0);
1266 138 rhoads
#endif
1267 189 rhoads
      value = OS_InterruptMaskSet(0) & 0xf;
1268
      if(value)
1269
         OS_InterruptServiceRoutine(value, 0);
1270 138 rhoads
      ++count;
1271
   }
1272
}
1273
#endif //DISABLE_IRQ_SIM
1274
 
1275
 
1276
/******************************************/
1277
//Plasma hardware dependent
1278 189 rhoads
static void OS_ThreadTickToggle(void *arg)
1279 138 rhoads
{
1280 167 rhoads
   uint32 status, mask, state;
1281 138 rhoads
 
1282 189 rhoads
   //Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT
1283 167 rhoads
   state = OS_SpinLock();
1284 138 rhoads
   status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1285
   mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT;
1286
   mask &= ~status;
1287
   MemoryWrite(IRQ_MASK, mask);
1288 189 rhoads
   OS_ThreadTick(arg);
1289 167 rhoads
   OS_SpinUnlock(state);
1290 138 rhoads
}
1291
 
1292
 
1293
/******************************************/
1294 189 rhoads
void OS_Init(uint32 *heapStorage, uint32 bytes)
1295 138 rhoads
{
1296 168 rhoads
   int i;
1297 138 rhoads
   OS_AsmInterruptInit();               //Patch interrupt vector
1298
   OS_InterruptMaskClear(0xffffffff);   //Disable interrupts
1299 189 rhoads
   HeapArray[0] = OS_HeapCreate("Default", heapStorage, bytes);
1300
   HeapArray[1] = HeapArray[0];
1301 138 rhoads
   SemaphoreSleep = OS_SemaphoreCreate("Sleep", 0);
1302
   SemaphoreLock = OS_SemaphoreCreate("Lock", 1);
1303 168 rhoads
   for(i = 0; i < OS_CPU_COUNT; ++i)
1304
      OS_ThreadCreate("Idle", OS_IdleThread, NULL, 0, 256);
1305 138 rhoads
#ifndef DISABLE_IRQ_SIM
1306
   if((OS_InterruptStatus() & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT)) == 0)
1307
   {
1308
      //Detected that running in simulator so create SimIsr thread
1309
      UartPrintfCritical("SimIsr\n");
1310
      OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
1311
   }
1312
#endif //DISABLE_IRQ_SIM
1313
 
1314
   //Plasma hardware dependent
1315 189 rhoads
   OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTickToggle);
1316 138 rhoads
   OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1317
}
1318
 
1319
 
1320
/******************************************/
1321
void OS_Start(void)
1322
{
1323
   ThreadSwapEnabled = 1;
1324 167 rhoads
   (void)OS_SpinLock();
1325 138 rhoads
   OS_ThreadReschedule(1);
1326
}
1327
 
1328
 
1329
/******************************************/
1330
//Place breakpoint here
1331
void OS_Assert(void)
1332
{
1333
}
1334
 
1335
 
1336 167 rhoads
#if OS_CPU_COUNT > 1
1337
static uint8 SpinLockArray[OS_CPU_COUNT];
1338
/******************************************/
1339
uint32 OS_CpuIndex(void)
1340
{
1341
   return 0; //0 to OS_CPU_COUNT-1
1342
}
1343
 
1344
 
1345
/******************************************/
1346
//Symmetric Multiprocessing Spin Lock Mutex
1347
uint32 OS_SpinLock(void)
1348
{
1349 168 rhoads
   uint32 state, cpuIndex, i, j, ok, delay;
1350 167 rhoads
 
1351 168 rhoads
   cpuIndex = OS_CpuIndex();
1352
   delay = cpuIndex + 8;
1353 167 rhoads
   state = OS_AsmInterruptEnable(0);
1354
   do
1355
   {
1356
      ok = 1;
1357 168 rhoads
      if(++SpinLockArray[cpuIndex] == 1)
1358 167 rhoads
      {
1359
         for(i = 0; i < OS_CPU_COUNT; ++i)
1360
         {
1361 168 rhoads
            if(i != cpuIndex && SpinLockArray[i])
1362 167 rhoads
               ok = 0;
1363
         }
1364
         if(ok == 0)
1365
         {
1366 168 rhoads
            SpinLockArray[cpuIndex] = 0;
1367
            for(j = 0; j < delay; ++j)  //wait a bit
1368 167 rhoads
               ++i;
1369 168 rhoads
            if(delay < 128)
1370
               delay <<= 1;
1371 167 rhoads
         }
1372
      }
1373
   } while(ok == 0);
1374
   return state;
1375
}
1376
 
1377
 
1378
/******************************************/
1379
void OS_SpinUnlock(uint32 state)
1380
{
1381 168 rhoads
   uint32 cpuIndex;
1382
   cpuIndex = OS_CpuIndex();
1383
   if(--SpinLockArray[cpuIndex] == 0)
1384 167 rhoads
      OS_AsmInterruptEnable(state);
1385 168 rhoads
 
1386
   assert(SpinLockArray[cpuIndex] < 10);
1387 167 rhoads
}
1388
 
1389
 
1390
/******************************************/
1391
//Must be called with interrupts disabled and spin locked
1392 176 rhoads
uint32 OS_SpinCountGet(void)
1393 167 rhoads
{
1394 168 rhoads
   uint32 cpuIndex, count;
1395
   cpuIndex = OS_CpuIndex();
1396
   count = SpinLockArray[cpuIndex];
1397 167 rhoads
   return count;
1398
}
1399
 
1400
 
1401
/******************************************/
1402
//Must be called with interrupts disabled and spin locked
1403 176 rhoads
void OS_SpinCountSet(uint32 count)
1404 167 rhoads
{
1405 168 rhoads
   uint32 cpuIndex;
1406
   cpuIndex = OS_CpuIndex();
1407
   SpinLockArray[cpuIndex] = (uint8)count;
1408
   assert(count);
1409 167 rhoads
}
1410 176 rhoads
 
1411
 
1412
/******************************************/
1413
void OS_CpuInterrupt(uint32 cpuIndex, uint32 bitfield)
1414
{
1415 189 rhoads
   //Request other CPU to reschedule threads
1416 176 rhoads
   (void)cpuIndex;
1417
   (void)bitfield;
1418
}
1419
 
1420
 
1421
/******************************************/
1422 189 rhoads
void OS_CpuInterruptServiceRoutine(void *arg)
1423 176 rhoads
{
1424
   uint32 state;
1425 189 rhoads
   (void)arg;
1426 176 rhoads
   state = OS_SpinLock();
1427
   OS_ThreadReschedule(0);
1428
   OS_SpinUnlock(state);
1429
}
1430 167 rhoads
#endif
1431
 
1432
 
1433 138 rhoads
/************** WIN32 Support *************/
1434
#ifdef WIN32
1435
//Support RTOS inside Windows
1436
extern int kbhit();
1437
extern int getch(void);
1438
extern int putch(int);
1439
extern void __stdcall Sleep(unsigned long value);
1440
 
1441
static uint32 Memory[8];
1442
 
1443 189 rhoads
uint32 MemoryRead(uint32 address)
1444 138 rhoads
{
1445 189 rhoads
   Memory[2] |= IRQ_UART_WRITE_AVAILABLE;    //IRQ_STATUS
1446
   switch(address)
1447 138 rhoads
   {
1448
   case UART_READ:
1449
      if(kbhit())
1450 189 rhoads
         Memory[0] = getch();                //UART_READ
1451 138 rhoads
      Memory[2] &= ~IRQ_UART_READ_AVAILABLE; //clear bit
1452
      return Memory[0];
1453
   case IRQ_MASK:
1454 189 rhoads
      return Memory[1];                      //IRQ_MASK
1455 138 rhoads
   case IRQ_MASK + 4:
1456
      Sleep(10);
1457
      return 0;
1458
   case IRQ_STATUS:
1459
      if(kbhit())
1460
         Memory[2] |= IRQ_UART_READ_AVAILABLE;
1461
      return Memory[2];
1462
   }
1463
   return 0;
1464
}
1465
 
1466 189 rhoads
void MemoryWrite(uint32 address, uint32 value)
1467 138 rhoads
{
1468 189 rhoads
   switch(address)
1469 138 rhoads
   {
1470
   case UART_WRITE:
1471 189 rhoads
      putch(value);
1472 138 rhoads
      break;
1473
   case IRQ_MASK:
1474 189 rhoads
      Memory[1] = value;
1475 138 rhoads
      break;
1476
   case IRQ_STATUS:
1477 189 rhoads
      Memory[2] = value;
1478 138 rhoads
      break;
1479
   }
1480
}
1481
 
1482 189 rhoads
uint32 OS_AsmInterruptEnable(uint32 enableInterrupt)
1483 138 rhoads
{
1484 189 rhoads
   return enableInterrupt;
1485 138 rhoads
}
1486
 
1487
void OS_AsmInterruptInit(void)
1488
{
1489
}
1490
#endif  //WIN32
1491
 
1492
 
1493
/**************** Example *****************/
1494
#ifndef NO_MAIN
1495
static uint8 HeapSpace[1024*512];
1496
 
1497
int main(void)
1498
{
1499
   UartPrintfCritical("Starting RTOS\n");
1500
   OS_Init((uint32*)HeapSpace, sizeof(HeapSpace));
1501
   UartInit();
1502 189 rhoads
   OS_ThreadCreate("Main", MainThread, NULL, 100, 64000);
1503 138 rhoads
   OS_Start();
1504
   return 0;
1505
}
1506
#endif
1507
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.