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

Subversion Repositories plasma

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

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 146 rhoads
   OS_Thread_t *thread;
655 138 rhoads
 
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 146 rhoads
      OS_ThreadReschedule(0);
667 138 rhoads
   }
668
   OS_CriticalEnd(state);
669
}
670
 
671
 
672
 
673
/***************** Mutex ******************/
674
/******************************************/
675
OS_Mutex_t *OS_MutexCreate(const char *Name)
676
{
677
   OS_Mutex_t *mutex;
678
 
679
   mutex = (OS_Mutex_t*)OS_HeapMalloc(NULL, sizeof(OS_Mutex_t));
680
   if(mutex == NULL)
681
      return NULL;
682
   mutex->semaphore = OS_SemaphoreCreate(Name, 1);
683
   if(mutex->semaphore == NULL)
684
      return NULL;
685
   mutex->thread = NULL;
686
   mutex->count = 0;
687
   return mutex;
688
}
689
 
690
 
691
/******************************************/
692
void OS_MutexDelete(OS_Mutex_t *Mutex)
693
{
694
   OS_SemaphoreDelete(Mutex->semaphore);
695
   OS_HeapFree(Mutex);
696
}
697
 
698
 
699
/******************************************/
700
void OS_MutexPend(OS_Mutex_t *Mutex)
701
{
702
   OS_Thread_t *thread;
703
 
704
   assert(Mutex);
705
   thread = OS_ThreadSelf();
706
   if(thread == Mutex->thread)
707
   {
708
      ++Mutex->count;
709
      return;
710
   }
711
   OS_SemaphorePend(Mutex->semaphore, OS_WAIT_FOREVER);
712
   Mutex->thread = thread;
713
   Mutex->count = 1;
714
}
715
 
716
 
717
/******************************************/
718
void OS_MutexPost(OS_Mutex_t *Mutex)
719
{
720
   assert(Mutex);
721
   assert(Mutex->thread == OS_ThreadSelf());
722
   assert(Mutex->count > 0);
723
   if(--Mutex->count <= 0)
724
   {
725
      Mutex->thread = NULL;
726
      OS_SemaphorePost(Mutex->semaphore);
727
   }
728
}
729
 
730
 
731
 
732
/***************** MQueue *****************/
733
/******************************************/
734
OS_MQueue_t *OS_MQueueCreate(const char *Name,
735
                             int MessageCount,
736
                             int MessageBytes)
737
{
738
   OS_MQueue_t *queue;
739
   int size;
740
 
741
   size = MessageBytes / sizeof(uint32);
742
   queue = (OS_MQueue_t*)OS_HeapMalloc(NULL, sizeof(OS_MQueue_t) +
743
      MessageCount * size * 4);
744
   if(queue == NULL)
745
      return queue;
746
   queue->name = Name;
747
   queue->semaphore = OS_SemaphoreCreate(Name, 0);
748
   if(queue->semaphore == NULL)
749
      return NULL;
750
   queue->count = MessageCount;
751
   queue->size = size;
752
   queue->used = 0;
753
   queue->read = 0;
754
   queue->write = 0;
755
   return queue;
756
}
757
 
758
 
759
/******************************************/
760
void OS_MQueueDelete(OS_MQueue_t *MQueue)
761
{
762
   OS_SemaphoreDelete(MQueue->semaphore);
763
   OS_HeapFree(MQueue);
764
}
765
 
766
 
767
/******************************************/
768
int OS_MQueueSend(OS_MQueue_t *MQueue, void *Message)
769
{
770
   uint32 state, *dst, *src;
771
   int i;
772
 
773
   assert(MQueue);
774
   src = (uint32*)Message;
775
   state = OS_CriticalBegin();
776
   if(++MQueue->used > MQueue->count)
777
   {
778
      --MQueue->used;
779
      OS_CriticalEnd(state);
780
      return -1;
781
   }
782
   dst = (uint32*)(MQueue + 1) + MQueue->write * MQueue->size;
783
   for(i = 0; i < MQueue->size; ++i)
784
      dst[i] = src[i];
785
   if(++MQueue->write >= MQueue->count)
786
      MQueue->write = 0;
787
   OS_CriticalEnd(state);
788
   OS_SemaphorePost(MQueue->semaphore);
789
   return 0;
790
}
791
 
792
 
793
/******************************************/
794
int OS_MQueueGet(OS_MQueue_t *MQueue, void *Message, int Ticks)
795
{
796
   uint32 state, *dst, *src;
797
   int i, rc;
798
 
799
   assert(MQueue);
800
   dst = (uint32*)Message;
801
   rc = OS_SemaphorePend(MQueue->semaphore, Ticks);
802
   if(rc)
803
      return rc;
804
   state = OS_CriticalBegin();
805
   --MQueue->used;
806
   src = (uint32*)(MQueue + 1) + MQueue->read * MQueue->size;
807
   for(i = 0; i < MQueue->size; ++i)
808
      dst[i] = src[i];
809
   if(++MQueue->read >= MQueue->count)
810
      MQueue->read = 0;
811
   OS_CriticalEnd(state);
812
   return 0;
813
}
814
 
815
 
816
 
817
/***************** Timer ******************/
818
/******************************************/
819
static void OS_TimerThread(void *Arg)
820
{
821
   uint32 timeNow;
822
   int diff, ticks;
823
   uint32 message[8];
824
   OS_Timer_t *timer;
825
   (void)Arg;
826
 
827
   timeNow = OS_ThreadTime();
828
   for(;;)
829
   {
830
      //Determine how long to sleep
831
      OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
832
      if(TimerHead)
833
         ticks = TimerHead->ticksTimeout - timeNow;
834
      else
835
         ticks = OS_WAIT_FOREVER;
836
      OS_SemaphorePost(SemaphoreLock);
837
      OS_SemaphorePend(SemaphoreTimer, ticks);
838
 
839
      //Send messages for all timed out timers
840
      timeNow = OS_ThreadTime();
841
      for(;;)
842
      {
843
         OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
844
         if(TimerHead == NULL)
845
         {
846
            OS_SemaphorePost(SemaphoreLock);
847
            break;
848
         }
849
         diff = timeNow - TimerHead->ticksTimeout;
850
         if(diff < 0)
851
         {
852
            OS_SemaphorePost(SemaphoreLock);
853
            break;
854
         }
855
         timer = TimerHead;
856
         OS_SemaphorePost(SemaphoreLock);
857
         if(timer->ticksRestart)
858
            OS_TimerStart(timer, timer->ticksRestart, timer->ticksRestart);
859
         else
860
            OS_TimerStop(timer);
861
 
862
         //Send message
863
         message[0] = MESSAGE_TYPE_TIMER;
864
         message[1] = (uint32)timer;
865
         message[2] = (uint32)timer->info;
866
         OS_MQueueSend(timer->mqueue, message);
867
      }
868
   }
869
}
870
 
871
 
872
/******************************************/
873
OS_Timer_t *OS_TimerCreate(const char *Name, OS_MQueue_t *MQueue, uint32 Info)
874
{
875
   OS_Timer_t *timer;
876
   int startThread=0;
877
 
878
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
879
   if(SemaphoreTimer == NULL)
880
   {
881
      SemaphoreTimer = OS_SemaphoreCreate("Timer", 0);
882
      startThread = 1;
883
   }
884
   OS_SemaphorePost(SemaphoreLock);
885
   if(startThread)
886
      OS_ThreadCreate("Timer", OS_TimerThread, NULL, 250, 2000);
887
 
888
   timer = (OS_Timer_t*)OS_HeapMalloc(NULL, sizeof(OS_Timer_t));
889
   if(timer == NULL)
890
      return NULL;
891
   timer->name = Name;
892
   timer->mqueue = MQueue;
893
   timer->next = NULL;
894
   timer->prev = NULL;
895
   timer->info = Info;
896
   timer->active = 0;
897
   return timer;
898
}
899
 
900
 
901
/******************************************/
902
void OS_TimerDelete(OS_Timer_t *Timer)
903
{
904
   OS_TimerStop(Timer);
905
   OS_HeapFree(Timer);
906
}
907
 
908
 
909
/******************************************/
910
//Must not be called from an ISR
911
void OS_TimerStart(OS_Timer_t *Timer, uint32 Ticks, uint32 TicksRestart)
912
{
913
   OS_Timer_t *node, *prev;
914
   int diff, check=0;
915
 
916
   assert(Timer);
917
   Ticks += OS_ThreadTime();
918
   if(Timer->active)
919
      OS_TimerStop(Timer);
920
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
921
   Timer->ticksTimeout = Ticks;
922
   Timer->ticksRestart = TicksRestart;
923
   Timer->active = 1;
924
   prev = NULL;
925
   for(node = TimerHead; node; node = node->next)
926
   {
927
      diff = Ticks - node->ticksTimeout;
928
      if(diff <= 0)
929
         break;
930
      prev = node;
931
   }
932
   Timer->next = node;
933
   Timer->prev = prev;
934
   if(node)
935
      node->prev = Timer;
936
   if(prev == NULL)
937
   {
938
      TimerHead = Timer;
939
      check = 1;
940
   }
941
   else
942
      prev->next = Timer;
943
   OS_SemaphorePost(SemaphoreLock);
944
   if(check)
945
      OS_SemaphorePost(SemaphoreTimer);
946
}
947
 
948
 
949
/******************************************/
950
//Must not be called from an ISR
951
void OS_TimerStop(OS_Timer_t *Timer)
952
{
953
   assert(Timer);
954
   OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
955
   if(Timer->active)
956
   {
957
      Timer->active = 0;
958
      if(Timer->prev == NULL)
959
         TimerHead = Timer->next;
960
      else
961
         Timer->prev->next = Timer->next;
962
      if(Timer->next)
963
         Timer->next->prev = Timer->prev;
964
   }
965
   OS_SemaphorePost(SemaphoreLock);
966
}
967
 
968
 
969
/***************** ISR ********************/
970
/******************************************/
971
void OS_InterruptServiceRoutine(uint32 Status)
972
{
973
   int i;
974
 
975
   //MemoryWrite(GPIO0_OUT, Status);  //Change LEDs
976
   InterruptInside = 1;
977
   i = 0;
978
   do
979
   {
980
      if(Status & 1)
981
      {
982
         if(Isr[i])
983
            Isr[i]((uint32*)i);
984
         else
985
            OS_InterruptMaskClear(1 << i);
986
      }
987
      Status >>= 1;
988
      ++i;
989
   } while(Status);
990
   InterruptInside = 0;
991
   //MemoryWrite(GPIO0_OUT, 0);
992
 
993
   if(ThreadNeedReschedule)
994
      OS_ThreadReschedule(ThreadNeedReschedule & 1);
995
}
996
 
997
 
998
/******************************************/
999
void OS_InterruptRegister(uint32 Mask, OS_FuncPtr_t FuncPtr)
1000
{
1001
   int i;
1002
 
1003
   for(i = 0; i < 32; ++i)
1004
   {
1005
      if(Mask & (1 << i))
1006
         Isr[i] = FuncPtr;
1007
   }
1008
}
1009
 
1010
 
1011
/******************************************/
1012
//Plasma hardware dependent
1013
uint32 OS_InterruptStatus(void)
1014
{
1015
   return MemoryRead(IRQ_STATUS);
1016
}
1017
 
1018
 
1019
/******************************************/
1020
//Plasma hardware dependent
1021
uint32 OS_InterruptMaskSet(uint32 Mask)
1022
{
1023
   uint32 mask, state;
1024
   state = OS_CriticalBegin();
1025
   mask = MemoryRead(IRQ_MASK) | Mask;
1026
   MemoryWrite(IRQ_MASK, mask);
1027
   OS_CriticalEnd(state);
1028
   return mask;
1029
}
1030
 
1031
 
1032
/******************************************/
1033
//Plasma hardware dependent
1034
uint32 OS_InterruptMaskClear(uint32 Mask)
1035
{
1036
   uint32 mask, state;
1037
   state = OS_CriticalBegin();
1038
   mask = MemoryRead(IRQ_MASK) & ~Mask;
1039
   MemoryWrite(IRQ_MASK, mask);
1040
   OS_CriticalEnd(state);
1041
   return mask;
1042
}
1043
 
1044
 
1045
/**************** Init ********************/
1046
/******************************************/
1047
static volatile uint32 IdleCount;
1048
static void OS_IdleThread(void *Arg)
1049
{
1050
   (void)Arg;
1051
 
1052
   for(;;)
1053
   {
1054
      ++IdleCount;
1055
   }
1056
}
1057
 
1058
 
1059
/******************************************/
1060
#ifndef DISABLE_IRQ_SIM
1061
static void OS_IdleSimulateIsr(void *Arg)
1062
{
1063
   uint32 count=0, value;
1064
   (void)Arg;
1065
 
1066
   for(;;)
1067
   {
1068
      MemoryRead(IRQ_MASK + 4);       //calls Sleep(10)
1069
#if WIN32
1070
      while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE)
1071
         OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE);
1072
#endif
1073
      value = OS_InterruptMaskSet(0);
1074
      OS_InterruptServiceRoutine(value);
1075
      ++count;
1076
   }
1077
}
1078
#endif //DISABLE_IRQ_SIM
1079
 
1080
 
1081
/******************************************/
1082
//Plasma hardware dependent
1083
void OS_ThreadTick2(void *Arg)
1084
{
1085
   uint32 status, mask;
1086
 
1087
   status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1088
   mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT;
1089
   mask &= ~status;
1090
   MemoryWrite(IRQ_MASK, mask);
1091
   OS_ThreadTick(Arg);
1092
}
1093
 
1094
 
1095
/******************************************/
1096
void OS_Init(uint32 *HeapStorage, uint32 Bytes)
1097
{
1098
   OS_AsmInterruptInit();               //Patch interrupt vector
1099
   OS_InterruptMaskClear(0xffffffff);   //Disable interrupts
1100
   HeapArray[0] = OS_HeapCreate("Default", HeapStorage, Bytes);
1101
   SemaphoreSleep = OS_SemaphoreCreate("Sleep", 0);
1102
   SemaphoreLock = OS_SemaphoreCreate("Lock", 1);
1103
   OS_ThreadCreate("Idle", OS_IdleThread, NULL, 0, 256);
1104
#ifndef DISABLE_IRQ_SIM
1105
   if((OS_InterruptStatus() & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT)) == 0)
1106
   {
1107
      //Detected that running in simulator so create SimIsr thread
1108
      UartPrintfCritical("SimIsr\n");
1109
      OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
1110
   }
1111
#endif //DISABLE_IRQ_SIM
1112
 
1113
   //Plasma hardware dependent
1114
   OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTick2);
1115
   OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
1116
}
1117
 
1118
 
1119
/******************************************/
1120
void OS_Start(void)
1121
{
1122
   ThreadSwapEnabled = 1;
1123
   OS_ThreadReschedule(1);
1124
}
1125
 
1126
 
1127
/******************************************/
1128
//Place breakpoint here
1129
void OS_Assert(void)
1130
{
1131
}
1132
 
1133
 
1134
/************** WIN32 Support *************/
1135
#ifdef WIN32
1136
//Support RTOS inside Windows
1137
extern int kbhit();
1138
extern int getch(void);
1139
extern int putch(int);
1140
extern void __stdcall Sleep(unsigned long value);
1141
 
1142
static uint32 Memory[8];
1143
 
1144
uint32 MemoryRead(uint32 Address)
1145
{
1146
   Memory[2] |= IRQ_UART_WRITE_AVAILABLE;
1147
   switch(Address)
1148
   {
1149
   case UART_READ:
1150
      if(kbhit())
1151
         Memory[0] = getch();
1152
      Memory[2] &= ~IRQ_UART_READ_AVAILABLE; //clear bit
1153
      return Memory[0];
1154
   case IRQ_MASK:
1155
      return Memory[1];
1156
   case IRQ_MASK + 4:
1157
      Sleep(10);
1158
      return 0;
1159
   case IRQ_STATUS:
1160
      if(kbhit())
1161
         Memory[2] |= IRQ_UART_READ_AVAILABLE;
1162
      return Memory[2];
1163
   }
1164
   return 0;
1165
}
1166
 
1167
void MemoryWrite(uint32 Address, uint32 Value)
1168
{
1169
   switch(Address)
1170
   {
1171
   case UART_WRITE:
1172
      putch(Value);
1173
      break;
1174
   case IRQ_MASK:
1175
      Memory[1] = Value;
1176
      break;
1177
   case IRQ_STATUS:
1178
      Memory[2] = Value;
1179
      break;
1180
   }
1181
}
1182
 
1183
uint32 OS_AsmInterruptEnable(uint32 EnableInterrupt)
1184
{
1185
   return EnableInterrupt;
1186
}
1187
 
1188
void OS_AsmInterruptInit(void)
1189
{
1190
}
1191
#endif  //WIN32
1192
 
1193
 
1194
/**************** Example *****************/
1195
#ifndef NO_MAIN
1196
static uint8 HeapSpace[1024*512];
1197
 
1198
int main(void)
1199
{
1200
   UartPrintfCritical("Starting RTOS\n");
1201
   OS_Init((uint32*)HeapSpace, sizeof(HeapSpace));
1202
   UartInit();
1203
   OS_ThreadCreate("Main", MainThread, 0, 100, 64000);
1204
   OS_Start();
1205
   return 0;
1206
}
1207
#endif
1208
 

powered by: WebSVN 2.1.0

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