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

Subversion Repositories plasma

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

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

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

powered by: WebSVN 2.1.0

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