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

Subversion Repositories plasma

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

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

powered by: WebSVN 2.1.0

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