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

Subversion Repositories plasma

[/] [plasma/] [tags/] [V3_0/] [kernel/] [rtos.c] - Blame information for rev 380

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
 *--------------------------------------------------------------------*/
16
#include "plasma.h"
17
#include "rtos.h"
18
 
19
#define HEAP_MAGIC 0x1234abcd
20
#define THREAD_MAGIC 0x4321abcd
21
#define SEM_RESERVED_COUNT 2
22
#define HEAP_COUNT 8
23
 
24
/*************** Structures ***************/
25
#ifdef WIN32
26
#define setjmp _setjmp
27
   //x86 registers
28
   typedef struct jmp_buf2 {
29
      uint32 Ebp, Ebx, Edi, Esi, sp, pc, extra[10];
30
   } jmp_buf2;
31
#else  
32
   //Plasma registers
33
   typedef struct jmp_buf2 {
34
      uint32 s[9], gp, sp, pc;
35
   } jmp_buf2;
36
#endif
37
 
38
typedef struct HeapNode_s {
39
   struct HeapNode_s *next;
40
   int size;
41
} HeapNode_t;
42
 
43
struct OS_Heap_s {
44
   uint32 magic;
45
   const char *name;
46
   OS_Semaphore_t *semaphore;
47
   HeapNode_t *available;
48
   HeapNode_t base;
49
   struct OS_Heap_s *alternate;
50
};
51
//typedef struct OS_Heap_s OS_Heap_t;
52
 
53
struct OS_Thread_s {
54
   const char *name;
55
   jmp_buf env;
56
   OS_FuncPtr_t funcPtr;
57
   void *arg;
58
   uint32 priority;
59
   uint32 ticksTimeout;
60
   void *info;
61
   OS_Semaphore_t *semaphorePending;
62
   int returnCode;
63
   struct OS_Thread_s *next, *prev;
64
   struct OS_Thread_s *nextTimeout, *prevTimeout;
65
   uint32 magic[1];
66
};
67
//typedef struct OS_Thread_s OS_Thread_t;
68
 
69
struct OS_Semaphore_s {
70
   const char *name;
71
   struct OS_Thread_s *threadHead;
72
   int count;
73
};
74
//typedef struct OS_Semaphore_s OS_Semaphore_t;
75
 
76
struct OS_Mutex_s {
77
   OS_Semaphore_t *semaphore;
78
   OS_Thread_t *thread;
79
   int count;
80
};
81
//typedef struct OS_Mutex_s OS_Mutex_t;
82
 
83
struct OS_MQueue_s {
84
   const char *name;
85
   OS_Semaphore_t *semaphore;
86
   int count, size, used, read, write;
87
};
88
//typedef struct OS_MQueue_s OS_MQueue_t;
89
 
90
struct OS_Timer_s {
91
   const char *name;
92
   struct OS_Timer_s *next, *prev;
93
   uint32 ticksTimeout;
94
   uint32 ticksRestart;
95
   int active;
96
   OS_MQueue_t *mqueue;
97
   uint32 info;
98
};
99
//typedef struct OS_Timer_s OS_Timer_t;
100
 
101
 
102
/*************** Globals ******************/
103
static OS_Heap_t *HeapArray[HEAP_COUNT];
104
static OS_Semaphore_t *SemaphoreSleep;
105
static OS_Semaphore_t *SemaphoreLock;
106
static int ThreadSwapEnabled;
107
static int ThreadCurrentActive;
108
static int ThreadNeedReschedule;
109
static uint32 ThreadTime;
110
static OS_Thread_t *ThreadHead;   //Linked list of threads sorted by priority
111
static OS_Thread_t *TimeoutHead;  //Linked list of threads sorted by timeout
112
static OS_Thread_t *ThreadCurrent;
113
static void *NeedToFree;
114
static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT];
115
static OS_Timer_t *TimerHead;     //Linked list of timers sorted by timeout
116
static OS_Semaphore_t *SemaphoreTimer;
117
static OS_FuncPtr_t Isr[32];
118
static int InterruptInside;
119
 
120
 
121
/***************** Heap *******************/
122
/******************************************/
123
OS_Heap_t *OS_HeapCreate(const char *Name, void *Memory, uint32 Size)
124
{
125
   OS_Heap_t *heap;
126
 
127
   assert(((uint32)Memory & 3) == 0);
128
   heap = (OS_Heap_t*)Memory;
129
   heap->magic = HEAP_MAGIC;
130
   heap->name = Name;
131
   heap->semaphore = OS_SemaphoreCreate(Name, 1);
132
   heap->available = (HeapNode_t*)(heap + 1);
133
   heap->available->next = &heap->base;
134
   heap->available->size = (Size - sizeof(OS_Heap_t)) / sizeof(HeapNode_t);
135
   heap->base.next = heap->available;
136
   heap->base.size = 0;
137
   return heap;
138
}
139
 
140
 
141
/******************************************/
142
void OS_HeapDestroy(OS_Heap_t *Heap)
143
{
144
   OS_SemaphoreDelete(Heap->semaphore);
145
}
146
 
147
 
148
/******************************************/
149
//Modified from K&R
150
void *OS_HeapMalloc(OS_Heap_t *Heap, int Bytes)
151
{
152
   HeapNode_t *node, *prevp;
153
   int nunits;
154
 
155
   if((int)Heap < HEAP_COUNT)
156
      Heap = HeapArray[(int)Heap];
157
   //printf("OS_HeapMalloc(%s, %d)\n", Heap->name, Bytes);
158
   nunits = (Bytes + sizeof(HeapNode_t) - 1) / sizeof(HeapNode_t) + 1;
159
   OS_SemaphorePend(Heap->semaphore, OS_WAIT_FOREVER);
160
   prevp = Heap->available;
161
   for(node = prevp->next; ; prevp = node, node = node->next)
162
   {
163
      if(node->size >= nunits)       //Big enough?
164
      {
165
         if(node->size == nunits)    //Exactly
166
            prevp->next = node->next;
167
         else
168
         {                           //Allocate tail end
169
            node->size -= nunits;
170
            node += node->size;
171
            node->size = nunits;
172
         }
173
         Heap->available = prevp;
174
         node->next = (HeapNode_t*)Heap;
175
         OS_SemaphorePost(Heap->semaphore);
176
         //printf("ptr=0x%x\n", (uint32)(node + 1));
177
         return (void*)(node + 1);
178
      }
179
      if(node == Heap->available)   //Wrapped around free list
180
      {
181
         OS_SemaphorePost(Heap->semaphore);
182
         if(Heap->alternate)
183
            return OS_HeapMalloc(Heap->alternate, Bytes);
184
         return NULL;
185
      }
186
   }
187
}
188
 
189
 
190
/******************************************/
191
//Modified from K&R
192
void OS_HeapFree(void *Block)
193
{
194
   OS_Heap_t *heap;
195
   HeapNode_t *bp, *node;
196
 
197
   assert(Block);
198
   //printf("OS_HeapFree(0x%x)\n", Block);
199
   bp = (HeapNode_t*)Block - 1;   //point to block header
200
   heap = (OS_Heap_t*)bp->next;
201
   assert(heap->magic == HEAP_MAGIC);
202
   if(heap->magic != HEAP_MAGIC)
203
      return;
204
   OS_SemaphorePend(heap->semaphore, OS_WAIT_FOREVER);
205
   for(node = heap->available; !(node < bp && bp < node->next); node = node->next)
206
   {
207
      if(node >= node->next && (bp > node || bp < node->next))
208
         break;               //freed block at start or end of area
209
   }
210
 
211
   if(bp + bp->size == node->next)   //join to upper
212
   {
213
      bp->size += node->next->size;
214
      bp->next = node->next->next;
215
   }
216
   else
217
   {
218
      bp->next = node->next;
219
   }
220
 
221
   if(node + node->size == bp)       //join to lower
222
   {
223
      node->size += bp->size;
224
      node->next = bp->next;
225
   }
226
   else
227
      node->next = bp;
228
   heap->available = node;
229
   OS_SemaphorePost(heap->semaphore);
230
}
231
 
232
 
233
/******************************************/
234
void OS_HeapAlternate(OS_Heap_t *Heap, OS_Heap_t *Alternate)
235
{
236
   Heap->alternate = Alternate;
237
}
238
 
239
 
240
/******************************************/
241
void OS_HeapRegister(void *Index, OS_Heap_t *Heap)
242
{
243
   if((int)Index < HEAP_COUNT)
244
      HeapArray[(int)Index] = Heap;
245
}
246
 
247
 
248
 
249
/***************** Thread *****************/
250
/******************************************/
251
//Linked list of threads sorted by priority
252
//Must be called with interrupts disabled
253
static void OS_ThreadPriorityInsert(OS_Thread_t **head, OS_Thread_t *thread)
254
{
255
   OS_Thread_t *node, *prev;
256
 
257
   prev = NULL;
258
   for(node = *head; node; node = node->next)
259
   {
260
      if(node->priority <= thread->priority)
261
         break;
262
      prev = node;
263
   }
264
 
265
   if(prev == NULL)
266
   {
267
      thread->next = *head;
268
      thread->prev = NULL;
269
      *head = thread;
270
   }
271
   else
272
   {
273
      if(prev->next)
274
         prev->next->prev = thread;
275
      thread->next = prev->next;
276
      thread->prev = prev;
277
      prev->next = thread;
278
   }
279
   assert(ThreadHead);
280
}
281
 
282
 
283
/******************************************/
284
//Must be called with interrupts disabled
285
static void OS_ThreadPriorityRemove(OS_Thread_t **head, OS_Thread_t *thread)
286
{
287
   //printf("r(%d) ", thread->priority);
288
   assert(thread->magic[0] == THREAD_MAGIC);  //check stack overflow
289
   if(thread->prev == NULL)
290
      *head = thread->next;
291
   else
292
      thread->prev->next = thread->next;
293
   if(thread->next)
294
      thread->next->prev = thread->prev;
295
   thread->next = NULL;
296
   thread->prev = NULL;
297
   if(head == &ThreadHead && ThreadCurrent == thread)
298
      ThreadCurrentActive = 0;
299
}
300
 
301
 
302
/******************************************/
303
//Linked list of threads sorted by timeout value
304
//Must be called with interrupts disabled
305
static void OS_ThreadTimeoutInsert(OS_Thread_t *thread)
306
{
307
   OS_Thread_t *node, *prev;
308
   int diff;
309
 
310
   prev = NULL;
311
   for(node = TimeoutHead; node; node = node->nextTimeout)
312
   {
313
      diff = thread->ticksTimeout - node->ticksTimeout;
314
      if(diff <= 0)
315
         break;
316
      prev = node;
317
   }
318
 
319
   if(prev == NULL)
320
   {
321
      thread->nextTimeout = TimeoutHead;
322
      thread->prevTimeout = NULL;
323
      TimeoutHead = thread;
324
   }
325
   else
326
   {
327
      if(prev->nextTimeout)
328
         prev->nextTimeout->prevTimeout = thread;
329
      thread->nextTimeout = prev->nextTimeout;
330
      thread->prevTimeout = prev;
331
      prev->nextTimeout = thread;
332
   }
333
}
334
 
335
 
336
/******************************************/
337
//Must be called with interrupts disabled
338
static void OS_ThreadTimeoutRemove(OS_Thread_t *thread)
339
{
340
   if(thread->prevTimeout == NULL && TimeoutHead != thread)
341
      return;         //not in list
342
   if(thread->prevTimeout == NULL)
343
      TimeoutHead = thread->nextTimeout;
344
   else
345
      thread->prevTimeout->nextTimeout = thread->nextTimeout;
346
   if(thread->nextTimeout)
347
      thread->nextTimeout->prevTimeout = thread->prevTimeout;
348
   thread->nextTimeout = NULL;
349
   thread->prevTimeout = NULL;
350
}
351
 
352
 
353
/******************************************/
354
//Loads a new thread and enabled interrupts
355
//Must be called with interrupts disabled
356
//May enable interrupts
357
static void OS_ThreadReschedule(int RoundRobin)
358
{
359
   OS_Thread_t *threadNext, *threadPrev;
360
   int rc;
361
 
362
   if(ThreadSwapEnabled == 0 || InterruptInside)
363
   {
364
      ThreadNeedReschedule |= 2 + RoundRobin;
365
      return;
366
   }
367
 
368
   //Determine which thread should run
369
   threadNext = ThreadCurrent;
370
   assert(ThreadHead);
371
   if(ThreadCurrentActive == 0)
372
      threadNext = ThreadHead;
373
   else if(ThreadCurrent->priority < ThreadHead->priority)
374
      threadNext = ThreadHead;
375
   else if(RoundRobin)
376
   {
377
      if(ThreadCurrent->next &&
378
         ThreadCurrent->next->priority == ThreadHead->priority)
379
         threadNext = ThreadCurrent->next;
380
      else
381
         threadNext = ThreadHead;
382
   }
383
 
384
   if(threadNext != ThreadCurrent)
385
   {
386
      //Swap threads
387
      threadPrev = ThreadCurrent;
388
      ThreadCurrent = threadNext;
389
      if(threadPrev)
390
      {
391
         assert(threadPrev->magic[0] == THREAD_MAGIC); //check stack overflow
392
         //printf("OS_ThreadRescheduleSave(%s)\n", threadPrev->name);
393
         rc = setjmp(threadPrev->env);   //ANSI C call to save registers
394
         if(rc)
395
         {
396
            //Returned from longjmp()
397
            OS_CriticalEnd(0xffffffff);  //Must re-enable interrupts!
398
            return;
399
         }
400
      }
401
      ThreadCurrentActive = 1;
402
      //printf("OS_ThreadRescheduleRestore(%s)\n", ThreadCurrent->name);
403
      longjmp(ThreadCurrent->env, 1);    //ANSI C call to restore registers
404
   }
405
}
406
 
407
 
408
/******************************************/
409
static void OS_ThreadInit(void *Arg)
410
{
411
   (void)Arg;
412
 
413
   OS_AsmInterruptEnable(1);
414
   ThreadCurrent->funcPtr(ThreadCurrent->arg);
415
   OS_ThreadExit();
416
}
417
 
418
 
419
/******************************************/
420
//Stops warning "argument X might be clobbered by `longjmp'"
421
static void OS_ThreadRegsInit(jmp_buf env)
422
{
423
   setjmp(env); //ANSI C call to save registers
424
}
425
 
426
 
427
/******************************************/
428
OS_Thread_t *OS_ThreadCreate(const char *Name,
429
                             OS_FuncPtr_t FuncPtr,
430
                             void *Arg,
431
                             uint32 Priority,
432
                             uint32 StackSize)
433
{
434
   OS_Thread_t *thread;
435
   uint8 *stack;
436
   jmp_buf2 *env;
437
   uint32 state;
438
 
439
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
440
   if(NeedToFree)
441
      OS_HeapFree(NeedToFree);
442
   NeedToFree = NULL;
443
   OS_SemaphorePost(SemaphoreLock);
444
 
445
   if(StackSize == 0)
446
      StackSize = STACK_SIZE_DEFAULT;
447
   if(StackSize < STACK_SIZE_MINIMUM)
448
      StackSize = STACK_SIZE_MINIMUM;
449
   thread = (OS_Thread_t*)OS_HeapMalloc(NULL, sizeof(OS_Thread_t) + StackSize);
450
   assert(thread);
451
   if(thread == NULL)
452
      return NULL;
453
   stack = (uint8*)(thread + 1);
454
   memset(stack, 0xcd, StackSize);
455
 
456
   thread->name = Name;
457
   thread->funcPtr = FuncPtr;
458
   thread->arg = Arg;
459
   thread->priority = Priority;
460
   thread->info = NULL;
461
   thread->semaphorePending = NULL;
462
   thread->returnCode = 0;
463
   thread->next = NULL;
464
   thread->prev = NULL;
465
   thread->nextTimeout = NULL;
466
   thread->prevTimeout = NULL;
467
   thread->magic[0] = THREAD_MAGIC;
468
 
469
   OS_ThreadRegsInit(thread->env);
470
   env = (jmp_buf2*)thread->env;
471
   env->sp = (uint32)stack + StackSize - 4;
472
   env->pc = (uint32)OS_ThreadInit;
473
 
474
   state = OS_CriticalBegin();
475
   OS_ThreadPriorityInsert(&ThreadHead, thread);
476
   OS_ThreadReschedule(0);
477
   OS_CriticalEnd(state);
478
   return thread;
479
}
480
 
481
 
482
/******************************************/
483
void OS_ThreadExit(void)
484
{
485
   uint32 state;
486
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
487
   if(NeedToFree)
488
      OS_HeapFree(NeedToFree);
489
   NeedToFree = NULL;
490
   OS_SemaphorePost(SemaphoreLock);
491
 
492
   state = OS_CriticalBegin();
493
   OS_ThreadPriorityRemove(&ThreadHead, ThreadCurrent);
494
   NeedToFree = ThreadCurrent;
495
   OS_ThreadReschedule(0);
496
   assert(ThreadHead == NULL);
497
   OS_CriticalEnd(state);
498
}
499
 
500
 
501
/******************************************/
502
OS_Thread_t *OS_ThreadSelf(void)
503
{
504
   return ThreadCurrent;
505
}
506
 
507
 
508
/******************************************/
509
void OS_ThreadSleep(int Ticks)
510
{
511
   OS_SemaphorePend(SemaphoreSleep, Ticks);
512
}
513
 
514
 
515
/******************************************/
516
uint32 OS_ThreadTime(void)
517
{
518
   return ThreadTime;
519
}
520
 
521
 
522
/******************************************/
523
void OS_ThreadInfoSet(OS_Thread_t *Thread, void *Info)
524
{
525
   Thread->info = Info;
526
}
527
 
528
 
529
/******************************************/
530
void *OS_ThreadInfoGet(OS_Thread_t *Thread)
531
{
532
   return Thread->info;
533
}
534
 
535
 
536
/******************************************/
537
uint32 OS_ThreadPriorityGet(OS_Thread_t *Thread)
538
{
539
   return Thread->priority;
540
}
541
 
542
 
543
/******************************************/
544
void OS_ThreadPrioritySet(OS_Thread_t *Thread, uint32 Priority)
545
{
546
   uint32 state;
547
   state = OS_CriticalBegin();
548
   OS_ThreadPriorityRemove(&ThreadHead, Thread);
549
   Thread->priority = Priority;
550
   OS_ThreadPriorityInsert(&ThreadHead, Thread);
551
   OS_ThreadReschedule(0);
552
   OS_CriticalEnd(state);
553
}
554
 
555
 
556
/******************************************/
557
//Must be called with interrupts disabled
558
void OS_ThreadTick(void *Arg)
559
{
560
   OS_Thread_t *thread;
561
   OS_Semaphore_t *semaphore;
562
   int diff;
563
   (void)Arg;
564
 
565
   ++ThreadTime;
566
   while(TimeoutHead)
567
   {
568
      thread = TimeoutHead;
569
      diff = ThreadTime - thread->ticksTimeout;
570
      if(diff < 0)
571
         break;
572
      OS_ThreadTimeoutRemove(thread);
573
      semaphore = thread->semaphorePending;
574
      ++semaphore->count;
575
      thread->semaphorePending = NULL;
576
      thread->returnCode = -1;
577
      OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
578
      OS_ThreadPriorityInsert(&ThreadHead, thread);
579
   }
580
   OS_ThreadReschedule(1);
581
}
582
 
583
 
584
 
585
/***************** Semaphore **************/
586
/******************************************/
587
OS_Semaphore_t *OS_SemaphoreCreate(const char *Name, uint32 Count)
588
{
589
   OS_Semaphore_t *semaphore;
590
   static int semCount;
591
 
592
   if(semCount < SEM_RESERVED_COUNT)
593
      semaphore = &SemaphoreReserved[semCount++];
594
   else
595
      semaphore = (OS_Semaphore_t*)OS_HeapMalloc(NULL, sizeof(OS_Semaphore_t));
596
   assert(semaphore);
597
   if(semaphore == NULL)
598
      return NULL;
599
 
600
   semaphore->name = Name;
601
   semaphore->threadHead = NULL;
602
   semaphore->count = Count;
603
   return semaphore;
604
}
605
 
606
 
607
/******************************************/
608
void OS_SemaphoreDelete(OS_Semaphore_t *Semaphore)
609
{
610
   while(Semaphore->threadHead)
611
      OS_SemaphorePost(Semaphore);
612
   OS_HeapFree(Semaphore);
613
}
614
 
615
 
616
/******************************************/
617
int OS_SemaphorePend(OS_Semaphore_t *Semaphore, int Ticks)
618
{
619
   uint32 state;
620
   OS_Thread_t *thread;
621
   int returnCode=0;
622
 
623
   assert(Semaphore);
624
   state = OS_CriticalBegin();
625
   if(--Semaphore->count < 0)
626
   {
627
      if(Ticks == 0)
628
      {
629
         ++Semaphore->count;
630
         OS_CriticalEnd(state);
631
         return -1;
632
      }
633
      thread = ThreadCurrent;
634
      thread->semaphorePending = Semaphore;
635
      thread->ticksTimeout = Ticks + OS_ThreadTime();
636
      OS_ThreadPriorityRemove(&ThreadHead, thread);
637
      OS_ThreadPriorityInsert(&Semaphore->threadHead, thread);
638
      if(Ticks != OS_WAIT_FOREVER)
639
         OS_ThreadTimeoutInsert(thread);
640
      ThreadCurrentActive = 0;
641
      assert(ThreadHead);
642
      OS_ThreadReschedule(0);
643
      returnCode = thread->returnCode;
644
   }
645
   OS_CriticalEnd(state);
646
   return returnCode;
647
}
648
 
649
 
650
/******************************************/
651
void OS_SemaphorePost(OS_Semaphore_t *Semaphore)
652
{
653
   uint32 state;
654
   OS_Thread_t *thread=NULL;
655
 
656
   assert(Semaphore);
657
   state = OS_CriticalBegin();
658
   if(++Semaphore->count <= 0)
659
   {
660
      thread = Semaphore->threadHead;
661
      OS_ThreadTimeoutRemove(thread);
662
      OS_ThreadPriorityRemove(&Semaphore->threadHead, thread);
663
      OS_ThreadPriorityInsert(&ThreadHead, thread);
664
      thread->semaphorePending = NULL;
665
      thread->returnCode = 0;
666
   }
667
   if(thread)
668
      OS_ThreadReschedule(0);
669
   OS_CriticalEnd(state);
670
}
671
 
672
 
673
 
674
/***************** Mutex ******************/
675
/******************************************/
676
OS_Mutex_t *OS_MutexCreate(const char *Name)
677
{
678
   OS_Mutex_t *mutex;
679
 
680
   mutex = (OS_Mutex_t*)OS_HeapMalloc(NULL, sizeof(OS_Mutex_t));
681
   if(mutex == NULL)
682
      return NULL;
683
   mutex->semaphore = OS_SemaphoreCreate(Name, 1);
684
   if(mutex->semaphore == NULL)
685
      return NULL;
686
   mutex->thread = NULL;
687
   mutex->count = 0;
688
   return mutex;
689
}
690
 
691
 
692
/******************************************/
693
void OS_MutexDelete(OS_Mutex_t *Mutex)
694
{
695
   OS_SemaphoreDelete(Mutex->semaphore);
696
   OS_HeapFree(Mutex);
697
}
698
 
699
 
700
/******************************************/
701
void OS_MutexPend(OS_Mutex_t *Mutex)
702
{
703
   OS_Thread_t *thread;
704
 
705
   assert(Mutex);
706
   thread = OS_ThreadSelf();
707
   if(thread == Mutex->thread)
708
   {
709
      ++Mutex->count;
710
      return;
711
   }
712
   OS_SemaphorePend(Mutex->semaphore, OS_WAIT_FOREVER);
713
   Mutex->thread = thread;
714
   Mutex->count = 1;
715
}
716
 
717
 
718
/******************************************/
719
void OS_MutexPost(OS_Mutex_t *Mutex)
720
{
721
   assert(Mutex);
722
   assert(Mutex->thread == OS_ThreadSelf());
723
   assert(Mutex->count > 0);
724
   if(--Mutex->count <= 0)
725
   {
726
      Mutex->thread = NULL;
727
      OS_SemaphorePost(Mutex->semaphore);
728
   }
729
}
730
 
731
 
732
 
733
/***************** MQueue *****************/
734
/******************************************/
735
OS_MQueue_t *OS_MQueueCreate(const char *Name,
736
                             int MessageCount,
737
                             int MessageBytes)
738
{
739
   OS_MQueue_t *queue;
740
   int size;
741
 
742
   size = MessageBytes / sizeof(uint32);
743
   queue = (OS_MQueue_t*)OS_HeapMalloc(NULL, sizeof(OS_MQueue_t) +
744
      MessageCount * size * 4);
745
   if(queue == NULL)
746
      return queue;
747
   queue->name = Name;
748
   queue->semaphore = OS_SemaphoreCreate(Name, 0);
749
   if(queue->semaphore == NULL)
750
      return NULL;
751
   queue->count = MessageCount;
752
   queue->size = size;
753
   queue->used = 0;
754
   queue->read = 0;
755
   queue->write = 0;
756
   return queue;
757
}
758
 
759
 
760
/******************************************/
761
void OS_MQueueDelete(OS_MQueue_t *MQueue)
762
{
763
   OS_SemaphoreDelete(MQueue->semaphore);
764
   OS_HeapFree(MQueue);
765
}
766
 
767
 
768
/******************************************/
769
int OS_MQueueSend(OS_MQueue_t *MQueue, void *Message)
770
{
771
   uint32 state, *dst, *src;
772
   int i;
773
 
774
   assert(MQueue);
775
   src = (uint32*)Message;
776
   state = OS_CriticalBegin();
777
   if(++MQueue->used > MQueue->count)
778
   {
779
      --MQueue->used;
780
      OS_CriticalEnd(state);
781
      return -1;
782
   }
783
   dst = (uint32*)(MQueue + 1) + MQueue->write * MQueue->size;
784
   for(i = 0; i < MQueue->size; ++i)
785
      dst[i] = src[i];
786
   if(++MQueue->write >= MQueue->count)
787
      MQueue->write = 0;
788
   OS_CriticalEnd(state);
789
   OS_SemaphorePost(MQueue->semaphore);
790
   return 0;
791
}
792
 
793
 
794
/******************************************/
795
int OS_MQueueGet(OS_MQueue_t *MQueue, void *Message, int Ticks)
796
{
797
   uint32 state, *dst, *src;
798
   int i, rc;
799
 
800
   assert(MQueue);
801
   dst = (uint32*)Message;
802
   rc = OS_SemaphorePend(MQueue->semaphore, Ticks);
803
   if(rc)
804
      return rc;
805
   state = OS_CriticalBegin();
806
   --MQueue->used;
807
   src = (uint32*)(MQueue + 1) + MQueue->read * MQueue->size;
808
   for(i = 0; i < MQueue->size; ++i)
809
      dst[i] = src[i];
810
   if(++MQueue->read >= MQueue->count)
811
      MQueue->read = 0;
812
   OS_CriticalEnd(state);
813
   return 0;
814
}
815
 
816
 
817
 
818
/***************** Timer ******************/
819
/******************************************/
820
static void OS_TimerThread(void *Arg)
821
{
822
   uint32 timeNow;
823
   int diff, ticks;
824
   uint32 message[8];
825
   OS_Timer_t *timer;
826
   (void)Arg;
827
 
828
   timeNow = OS_ThreadTime();
829
   for(;;)
830
   {
831
      //Determine how long to sleep
832
      OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
833
      if(TimerHead)
834
         ticks = TimerHead->ticksTimeout - timeNow;
835
      else
836
         ticks = OS_WAIT_FOREVER;
837
      OS_SemaphorePost(SemaphoreLock);
838
      OS_SemaphorePend(SemaphoreTimer, ticks);
839
 
840
      //Send messages for all timed out timers
841
      timeNow = OS_ThreadTime();
842
      for(;;)
843
      {
844
         OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
845
         if(TimerHead == NULL)
846
         {
847
            OS_SemaphorePost(SemaphoreLock);
848
            break;
849
         }
850
         diff = timeNow - TimerHead->ticksTimeout;
851
         if(diff < 0)
852
         {
853
            OS_SemaphorePost(SemaphoreLock);
854
            break;
855
         }
856
         timer = TimerHead;
857
         OS_SemaphorePost(SemaphoreLock);
858
         if(timer->ticksRestart)
859
            OS_TimerStart(timer, timer->ticksRestart, timer->ticksRestart);
860
         else
861
            OS_TimerStop(timer);
862
 
863
         //Send message
864
         message[0] = MESSAGE_TYPE_TIMER;
865
         message[1] = (uint32)timer;
866
         message[2] = (uint32)timer->info;
867
         OS_MQueueSend(timer->mqueue, message);
868
      }
869
   }
870
}
871
 
872
 
873
/******************************************/
874
OS_Timer_t *OS_TimerCreate(const char *Name, OS_MQueue_t *MQueue, uint32 Info)
875
{
876
   OS_Timer_t *timer;
877
   int startThread=0;
878
 
879
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
880
   if(SemaphoreTimer == NULL)
881
   {
882
      SemaphoreTimer = OS_SemaphoreCreate("Timer", 0);
883
      startThread = 1;
884
   }
885
   OS_SemaphorePost(SemaphoreLock);
886
   if(startThread)
887
      OS_ThreadCreate("Timer", OS_TimerThread, NULL, 250, 2000);
888
 
889
   timer = (OS_Timer_t*)OS_HeapMalloc(NULL, sizeof(OS_Timer_t));
890
   if(timer == NULL)
891
      return NULL;
892
   timer->name = Name;
893
   timer->mqueue = MQueue;
894
   timer->next = NULL;
895
   timer->prev = NULL;
896
   timer->info = Info;
897
   timer->active = 0;
898
   return timer;
899
}
900
 
901
 
902
/******************************************/
903
void OS_TimerDelete(OS_Timer_t *Timer)
904
{
905
   OS_TimerStop(Timer);
906
   OS_HeapFree(Timer);
907
}
908
 
909
 
910
/******************************************/
911
//Must not be called from an ISR
912
void OS_TimerStart(OS_Timer_t *Timer, uint32 Ticks, uint32 TicksRestart)
913
{
914
   OS_Timer_t *node, *prev;
915
   int diff, check=0;
916
 
917
   assert(Timer);
918
   Ticks += OS_ThreadTime();
919
   if(Timer->active)
920
      OS_TimerStop(Timer);
921
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
922
   Timer->ticksTimeout = Ticks;
923
   Timer->ticksRestart = TicksRestart;
924
   Timer->active = 1;
925
   prev = NULL;
926
   for(node = TimerHead; node; node = node->next)
927
   {
928
      diff = Ticks - node->ticksTimeout;
929
      if(diff <= 0)
930
         break;
931
      prev = node;
932
   }
933
   Timer->next = node;
934
   Timer->prev = prev;
935
   if(node)
936
      node->prev = Timer;
937
   if(prev == NULL)
938
   {
939
      TimerHead = Timer;
940
      check = 1;
941
   }
942
   else
943
      prev->next = Timer;
944
   OS_SemaphorePost(SemaphoreLock);
945
   if(check)
946
      OS_SemaphorePost(SemaphoreTimer);
947
}
948
 
949
 
950
/******************************************/
951
//Must not be called from an ISR
952
void OS_TimerStop(OS_Timer_t *Timer)
953
{
954
   assert(Timer);
955
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
956
   if(Timer->active)
957
   {
958
      Timer->active = 0;
959
      if(Timer->prev == NULL)
960
         TimerHead = Timer->next;
961
      else
962
         Timer->prev->next = Timer->next;
963
      if(Timer->next)
964
         Timer->next->prev = Timer->prev;
965
   }
966
   OS_SemaphorePost(SemaphoreLock);
967
}
968
 
969
 
970
/***************** ISR ********************/
971
/******************************************/
972
void OS_InterruptServiceRoutine(uint32 Status)
973
{
974
   int i;
975
 
976
   //MemoryWrite(GPIO0_OUT, Status);  //Change LEDs
977
   InterruptInside = 1;
978
   i = 0;
979
   do
980
   {
981
      if(Status & 1)
982
      {
983
         if(Isr[i])
984
            Isr[i]((uint32*)i);
985
         else
986
            OS_InterruptMaskClear(1 << i);
987
      }
988
      Status >>= 1;
989
      ++i;
990
   } while(Status);
991
   InterruptInside = 0;
992
   //MemoryWrite(GPIO0_OUT, 0);
993
 
994
   if(ThreadNeedReschedule)
995
      OS_ThreadReschedule(ThreadNeedReschedule & 1);
996
}
997
 
998
 
999
/******************************************/
1000
void OS_InterruptRegister(uint32 Mask, OS_FuncPtr_t FuncPtr)
1001
{
1002
   int i;
1003
 
1004
   for(i = 0; i < 32; ++i)
1005
   {
1006
      if(Mask & (1 << i))
1007
         Isr[i] = FuncPtr;
1008
   }
1009
}
1010
 
1011
 
1012
/******************************************/
1013
//Plasma hardware dependent
1014
uint32 OS_InterruptStatus(void)
1015
{
1016
   return MemoryRead(IRQ_STATUS);
1017
}
1018
 
1019
 
1020
/******************************************/
1021
//Plasma hardware dependent
1022
uint32 OS_InterruptMaskSet(uint32 Mask)
1023
{
1024
   uint32 mask, state;
1025
   state = OS_CriticalBegin();
1026
   mask = MemoryRead(IRQ_MASK) | Mask;
1027
   MemoryWrite(IRQ_MASK, mask);
1028
   OS_CriticalEnd(state);
1029
   return mask;
1030
}
1031
 
1032
 
1033
/******************************************/
1034
//Plasma hardware dependent
1035
uint32 OS_InterruptMaskClear(uint32 Mask)
1036
{
1037
   uint32 mask, state;
1038
   state = OS_CriticalBegin();
1039
   mask = MemoryRead(IRQ_MASK) & ~Mask;
1040
   MemoryWrite(IRQ_MASK, mask);
1041
   OS_CriticalEnd(state);
1042
   return mask;
1043
}
1044
 
1045
 
1046
/**************** Init ********************/
1047
/******************************************/
1048
static volatile uint32 IdleCount;
1049
static void OS_IdleThread(void *Arg)
1050
{
1051
   (void)Arg;
1052
 
1053
   for(;;)
1054
   {
1055
      ++IdleCount;
1056
   }
1057
}
1058
 
1059
 
1060
/******************************************/
1061
#ifndef DISABLE_IRQ_SIM
1062
static void OS_IdleSimulateIsr(void *Arg)
1063
{
1064
   uint32 count=0, value;
1065
   (void)Arg;
1066
 
1067
   for(;;)
1068
   {
1069
      MemoryRead(IRQ_MASK + 4);       //calls Sleep(10)
1070
#if WIN32
1071
      while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE)
1072
         OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE);
1073
#endif
1074
      value = OS_InterruptMaskSet(0);
1075
      OS_InterruptServiceRoutine(value);
1076
      ++count;
1077
   }
1078
}
1079
#endif //DISABLE_IRQ_SIM
1080
 
1081
 
1082
/******************************************/
1083
//Plasma hardware dependent
1084
void OS_ThreadTick2(void *Arg)
1085
{
1086
   uint32 status, mask;
1087
 
1088
   status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1089
   mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT;
1090
   mask &= ~status;
1091
   MemoryWrite(IRQ_MASK, mask);
1092
   OS_ThreadTick(Arg);
1093
}
1094
 
1095
 
1096
/******************************************/
1097
void OS_Init(uint32 *HeapStorage, uint32 Bytes)
1098
{
1099
   OS_AsmInterruptInit();               //Patch interrupt vector
1100
   OS_InterruptMaskClear(0xffffffff);   //Disable interrupts
1101
   HeapArray[0] = OS_HeapCreate("Default", HeapStorage, Bytes);
1102
   SemaphoreSleep = OS_SemaphoreCreate("Sleep", 0);
1103
   SemaphoreLock = OS_SemaphoreCreate("Lock", 1);
1104
   OS_ThreadCreate("Idle", OS_IdleThread, NULL, 0, 256);
1105
#ifndef DISABLE_IRQ_SIM
1106
   if((OS_InterruptStatus() & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT)) == 0)
1107
   {
1108
      //Detected that running in simulator so create SimIsr thread
1109
      UartPrintfCritical("SimIsr\n");
1110
      OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
1111
   }
1112
#endif //DISABLE_IRQ_SIM
1113
 
1114
   //Plasma hardware dependent
1115
   OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTick2);
1116
   OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1117
}
1118
 
1119
 
1120
/******************************************/
1121
void OS_Start(void)
1122
{
1123
   ThreadSwapEnabled = 1;
1124
   OS_ThreadReschedule(1);
1125
}
1126
 
1127
 
1128
/******************************************/
1129
//Place breakpoint here
1130
void OS_Assert(void)
1131
{
1132
}
1133
 
1134
 
1135
/************** WIN32 Support *************/
1136
#ifdef WIN32
1137
//Support RTOS inside Windows
1138
extern int kbhit();
1139
extern int getch(void);
1140
extern int putch(int);
1141
extern void __stdcall Sleep(unsigned long value);
1142
 
1143
static uint32 Memory[8];
1144
 
1145
uint32 MemoryRead(uint32 Address)
1146
{
1147
   Memory[2] |= IRQ_UART_WRITE_AVAILABLE;
1148
   switch(Address)
1149
   {
1150
   case UART_READ:
1151
      if(kbhit())
1152
         Memory[0] = getch();
1153
      Memory[2] &= ~IRQ_UART_READ_AVAILABLE; //clear bit
1154
      return Memory[0];
1155
   case IRQ_MASK:
1156
      return Memory[1];
1157
   case IRQ_MASK + 4:
1158
      Sleep(10);
1159
      return 0;
1160
   case IRQ_STATUS:
1161
      if(kbhit())
1162
         Memory[2] |= IRQ_UART_READ_AVAILABLE;
1163
      return Memory[2];
1164
   }
1165
   return 0;
1166
}
1167
 
1168
void MemoryWrite(uint32 Address, uint32 Value)
1169
{
1170
   switch(Address)
1171
   {
1172
   case UART_WRITE:
1173
      putch(Value);
1174
      break;
1175
   case IRQ_MASK:
1176
      Memory[1] = Value;
1177
      break;
1178
   case IRQ_STATUS:
1179
      Memory[2] = Value;
1180
      break;
1181
   }
1182
}
1183
 
1184
uint32 OS_AsmInterruptEnable(uint32 EnableInterrupt)
1185
{
1186
   return EnableInterrupt;
1187
}
1188
 
1189
void OS_AsmInterruptInit(void)
1190
{
1191
}
1192
#endif  //WIN32
1193
 
1194
 
1195
/**************** Example *****************/
1196
#ifndef NO_MAIN
1197
static uint8 HeapSpace[1024*512];
1198
 
1199
int main(void)
1200
{
1201
   UartPrintfCritical("Starting RTOS\n");
1202
   OS_Init((uint32*)HeapSpace, sizeof(HeapSpace));
1203
   UartInit();
1204
   OS_ThreadCreate("Main", MainThread, 0, 100, 64000);
1205
   OS_Start();
1206
   return 0;
1207
}
1208
#endif
1209
 

powered by: WebSVN 2.1.0

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