Line 127... |
Line 127... |
static int ThreadNeedReschedule[OS_CPU_COUNT];
|
static int ThreadNeedReschedule[OS_CPU_COUNT];
|
static OS_Thread_t *ThreadCurrent[OS_CPU_COUNT]; //Currently running thread(s)
|
static OS_Thread_t *ThreadCurrent[OS_CPU_COUNT]; //Currently running thread(s)
|
static OS_Thread_t *ThreadHead; //Linked list of threads sorted by priority
|
static OS_Thread_t *ThreadHead; //Linked list of threads sorted by priority
|
static OS_Thread_t *TimeoutHead; //Linked list of threads sorted by timeout
|
static OS_Thread_t *TimeoutHead; //Linked list of threads sorted by timeout
|
static int ThreadSwapEnabled;
|
static int ThreadSwapEnabled;
|
static uint32 ThreadTime;
|
static uint32 ThreadTime; //Number of ~10ms ticks since reboot
|
static void *NeedToFree;
|
static void *NeedToFree; //Closed but not yet freed thread
|
static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT];
|
static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT];
|
static OS_Semaphore_t *SemaphoreSleep;
|
static OS_Semaphore_t *SemaphoreSleep;
|
static OS_Semaphore_t *SemaphoreRelease;
|
static OS_Semaphore_t *SemaphoreRelease;
|
static OS_Semaphore_t *SemaphoreLock;
|
static OS_Semaphore_t *SemaphoreLock;
|
static OS_Semaphore_t *SemaphoreTimer;
|
static OS_Semaphore_t *SemaphoreTimer;
|
Line 166... |
Line 166... |
OS_SemaphoreDelete(heap->semaphore);
|
OS_SemaphoreDelete(heap->semaphore);
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
//Modified from K&R
|
//Modified from Kernighan & Ritchie "The C Programming Language"
|
void *OS_HeapMalloc(OS_Heap_t *heap, int bytes)
|
void *OS_HeapMalloc(OS_Heap_t *heap, int bytes)
|
{
|
{
|
HeapNode_t *node, *prevp;
|
HeapNode_t *node, *prevp;
|
int nunits;
|
int nunits;
|
|
|
Line 393... |
Line 393... |
|
|
//Determine which thread should run
|
//Determine which thread should run
|
threadNext = ThreadHead;
|
threadNext = ThreadHead;
|
while(threadNext && threadNext->cpuLock != -1 &&
|
while(threadNext && threadNext->cpuLock != -1 &&
|
threadNext->cpuLock != cpuIndex)
|
threadNext->cpuLock != cpuIndex)
|
threadNext = threadNext->next;
|
threadNext = threadNext->next; //Skip CPU locked threads
|
if(threadNext == NULL)
|
if(threadNext == NULL)
|
return;
|
return;
|
threadCurrent = ThreadCurrent[cpuIndex];
|
threadCurrent = ThreadCurrent[cpuIndex];
|
|
|
if(threadCurrent == NULL ||
|
if(threadCurrent == NULL ||
|
Line 514... |
Line 514... |
OS_ThreadRegsInit(thread->env);
|
OS_ThreadRegsInit(thread->env);
|
env = (jmp_buf2*)thread->env;
|
env = (jmp_buf2*)thread->env;
|
env->sp = (uint32)stack + stackSize - 24; //minimum stack frame size
|
env->sp = (uint32)stack + stackSize - 24; //minimum stack frame size
|
env->pc = (uint32)OS_ThreadInit;
|
env->pc = (uint32)OS_ThreadInit;
|
|
|
|
//Add thread to linked list of ready to run threads
|
state = OS_CriticalBegin();
|
state = OS_CriticalBegin();
|
OS_ThreadPriorityInsert(&ThreadHead, thread);
|
OS_ThreadPriorityInsert(&ThreadHead, thread);
|
OS_ThreadReschedule(0);
|
OS_ThreadReschedule(0); //run highest priority thread
|
OS_CriticalEnd(state);
|
OS_CriticalEnd(state);
|
return thread;
|
return thread;
|
}
|
}
|
|
|
|
|
Line 529... |
Line 530... |
{
|
{
|
uint32 state, cpuIndex = OS_CpuIndex();
|
uint32 state, cpuIndex = OS_CpuIndex();
|
|
|
for(;;)
|
for(;;)
|
{
|
{
|
|
//Free the memory for closed but not yet freed threads
|
OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER);
|
OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER);
|
if(NeedToFree)
|
if(NeedToFree)
|
OS_HeapFree(NeedToFree);
|
OS_HeapFree(NeedToFree);
|
NeedToFree = NULL;
|
NeedToFree = NULL;
|
OS_SemaphorePost(SemaphoreRelease);
|
OS_SemaphorePost(SemaphoreRelease);
|
Line 550... |
Line 552... |
}
|
}
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Return currently running thread
|
OS_Thread_t *OS_ThreadSelf(void)
|
OS_Thread_t *OS_ThreadSelf(void)
|
{
|
{
|
return ThreadCurrent[OS_CpuIndex()];
|
return ThreadCurrent[OS_CpuIndex()];
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Sleep for ~10 msecs ticks
|
void OS_ThreadSleep(int ticks)
|
void OS_ThreadSleep(int ticks)
|
{
|
{
|
OS_SemaphorePend(SemaphoreSleep, ticks);
|
OS_SemaphorePend(SemaphoreSleep, ticks);
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Return the number of ~10 msecs ticks since reboot
|
uint32 OS_ThreadTime(void)
|
uint32 OS_ThreadTime(void)
|
{
|
{
|
return ThreadTime;
|
return ThreadTime;
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Save thread unique values
|
void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *Info)
|
void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *Info)
|
{
|
{
|
if(index < INFO_COUNT)
|
if(index < INFO_COUNT)
|
thread->info[index] = Info;
|
thread->info[index] = Info;
|
}
|
}
|
Line 619... |
Line 625... |
thread->heap = heap;
|
thread->heap = heap;
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
//Must be called with interrupts disabled
|
//Must be called with interrupts disabled every ~10 msecs
|
|
//Will wake up threads that have timed out waiting on a semaphore
|
void OS_ThreadTick(void *Arg)
|
void OS_ThreadTick(void *Arg)
|
{
|
{
|
OS_Thread_t *thread;
|
OS_Thread_t *thread;
|
OS_Semaphore_t *semaphore;
|
OS_Semaphore_t *semaphore;
|
int diff;
|
int diff;
|
(void)Arg;
|
(void)Arg;
|
|
|
++ThreadTime;
|
++ThreadTime; //Number of ~10 msec ticks since reboot
|
while(TimeoutHead)
|
while(TimeoutHead)
|
{
|
{
|
thread = TimeoutHead;
|
thread = TimeoutHead;
|
diff = ThreadTime - thread->ticksTimeout;
|
diff = ThreadTime - thread->ticksTimeout;
|
if(diff < 0)
|
if(diff < 0)
|
break;
|
break;
|
|
|
|
//The thread has timed out waiting for a semaphore
|
OS_ThreadTimeoutRemove(thread);
|
OS_ThreadTimeoutRemove(thread);
|
semaphore = thread->semaphorePending;
|
semaphore = thread->semaphorePending;
|
++semaphore->count;
|
++semaphore->count;
|
thread->semaphorePending = NULL;
|
thread->semaphorePending = NULL;
|
thread->returnCode = -1;
|
thread->returnCode = -1;
|
OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
|
OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
|
OS_ThreadPriorityInsert(&ThreadHead, thread);
|
OS_ThreadPriorityInsert(&ThreadHead, thread);
|
}
|
}
|
OS_ThreadReschedule(1);
|
OS_ThreadReschedule(1); //Run highest priority thread
|
}
|
}
|
|
|
|
|
|
|
/***************** Semaphore **************/
|
/***************** Semaphore **************/
|
/******************************************/
|
/******************************************/
|
|
//Create a counting semaphore
|
OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count)
|
OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count)
|
{
|
{
|
OS_Semaphore_t *semaphore;
|
OS_Semaphore_t *semaphore;
|
static int semCount = 0;
|
static int semCount = 0;
|
|
|
Line 679... |
Line 689... |
OS_HeapFree(semaphore);
|
OS_HeapFree(semaphore);
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Sleep the number of ticks (~10ms) until the semaphore is acquired
|
int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks)
|
int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks)
|
{
|
{
|
uint32 state, cpuIndex;
|
uint32 state, cpuIndex;
|
OS_Thread_t *thread;
|
OS_Thread_t *thread;
|
int returnCode=0;
|
int returnCode=0;
|
|
|
assert(semaphore);
|
assert(semaphore);
|
assert(InterruptInside[OS_CpuIndex()] == 0);
|
assert(InterruptInside[OS_CpuIndex()] == 0);
|
state = OS_CriticalBegin();
|
state = OS_CriticalBegin(); //Disable interrupts
|
if(--semaphore->count < 0)
|
if(--semaphore->count < 0)
|
{
|
{
|
|
//Semaphore not available
|
if(ticks == 0)
|
if(ticks == 0)
|
{
|
{
|
++semaphore->count;
|
++semaphore->count;
|
OS_CriticalEnd(state);
|
OS_CriticalEnd(state);
|
return -1;
|
return -1;
|
}
|
}
|
|
|
|
//Need to sleep until the semaphore is available
|
cpuIndex = OS_CpuIndex();
|
cpuIndex = OS_CpuIndex();
|
thread = ThreadCurrent[cpuIndex];
|
thread = ThreadCurrent[cpuIndex];
|
assert(thread);
|
assert(thread);
|
thread->semaphorePending = semaphore;
|
thread->semaphorePending = semaphore;
|
thread->ticksTimeout = ticks + OS_ThreadTime();
|
thread->ticksTimeout = ticks + OS_ThreadTime();
|
|
|
//FYI: The current thread isn't in the ThreadHead linked list
|
//FYI: The current thread isn't in the ThreadHead linked list
|
|
//Place the thread into a sorted linked list of pending threads
|
OS_ThreadPriorityInsert(&semaphore->threadHead, thread);
|
OS_ThreadPriorityInsert(&semaphore->threadHead, thread);
|
thread->state = THREAD_PEND;
|
thread->state = THREAD_PEND;
|
if(ticks != OS_WAIT_FOREVER)
|
if(ticks != OS_WAIT_FOREVER)
|
OS_ThreadTimeoutInsert(thread);
|
OS_ThreadTimeoutInsert(thread); //Check every ~10ms for timeouts
|
assert(ThreadHead);
|
assert(ThreadHead);
|
OS_ThreadReschedule(0);
|
OS_ThreadReschedule(0); //Run highest priority thread
|
returnCode = thread->returnCode;
|
returnCode = thread->returnCode; //Will be -1 if timed out
|
}
|
}
|
OS_CriticalEnd(state);
|
OS_CriticalEnd(state); //Re-enable interrupts
|
return returnCode;
|
return returnCode;
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Release a semaphore and possibly wake up a blocked thread
|
void OS_SemaphorePost(OS_Semaphore_t *semaphore)
|
void OS_SemaphorePost(OS_Semaphore_t *semaphore)
|
{
|
{
|
uint32 state;
|
uint32 state;
|
OS_Thread_t *thread;
|
OS_Thread_t *thread;
|
|
|
assert(semaphore);
|
assert(semaphore);
|
state = OS_CriticalBegin();
|
state = OS_CriticalBegin();
|
if(++semaphore->count <= 0)
|
if(++semaphore->count <= 0)
|
{
|
{
|
|
//Wake up a thread that was waiting for this semaphore
|
thread = semaphore->threadHead;
|
thread = semaphore->threadHead;
|
OS_ThreadTimeoutRemove(thread);
|
OS_ThreadTimeoutRemove(thread);
|
OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
|
OS_ThreadPriorityRemove(&semaphore->threadHead, thread);
|
OS_ThreadPriorityInsert(&ThreadHead, thread);
|
OS_ThreadPriorityInsert(&ThreadHead, thread);
|
thread->semaphorePending = NULL;
|
thread->semaphorePending = NULL;
|
Line 740... |
Line 758... |
|
|
|
|
|
|
/***************** Mutex ******************/
|
/***************** Mutex ******************/
|
/******************************************/
|
/******************************************/
|
|
//Create a mutex (a thread aware semaphore)
|
OS_Mutex_t *OS_MutexCreate(const char *name)
|
OS_Mutex_t *OS_MutexCreate(const char *name)
|
{
|
{
|
OS_Mutex_t *mutex;
|
OS_Mutex_t *mutex;
|
|
|
mutex = (OS_Mutex_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Mutex_t));
|
mutex = (OS_Mutex_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Mutex_t));
|
Line 799... |
Line 818... |
|
|
|
|
|
|
/***************** MQueue *****************/
|
/***************** MQueue *****************/
|
/******************************************/
|
/******************************************/
|
|
//Create a message queue
|
OS_MQueue_t *OS_MQueueCreate(const char *name,
|
OS_MQueue_t *OS_MQueueCreate(const char *name,
|
int messageCount,
|
int messageCount,
|
int messageBytes)
|
int messageBytes)
|
{
|
{
|
OS_MQueue_t *queue;
|
OS_MQueue_t *queue;
|
int size;
|
int size;
|
|
|
|
assert((messageBytes & 3) == 0);
|
size = messageBytes / sizeof(uint32);
|
size = messageBytes / sizeof(uint32);
|
queue = (OS_MQueue_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_MQueue_t) +
|
queue = (OS_MQueue_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_MQueue_t) +
|
messageCount * size * 4);
|
messageCount * size * 4);
|
if(queue == NULL)
|
if(queue == NULL)
|
return queue;
|
return queue;
|
Line 833... |
Line 854... |
OS_HeapFree(mQueue);
|
OS_HeapFree(mQueue);
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Send a message that is messageBytes long (defined during create)
|
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
|
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message)
|
{
|
{
|
uint32 state, *dst, *src;
|
uint32 state, *dst, *src;
|
int i;
|
int i;
|
|
|
assert(mQueue);
|
assert(mQueue);
|
src = (uint32*)message;
|
src = (uint32*)message;
|
state = OS_CriticalBegin();
|
state = OS_CriticalBegin(); //Disable interrupts
|
if(++mQueue->used > mQueue->count)
|
if(++mQueue->used > mQueue->count)
|
{
|
{
|
|
//The message queue is full so discard the message
|
--mQueue->used;
|
--mQueue->used;
|
OS_CriticalEnd(state);
|
OS_CriticalEnd(state);
|
return -1;
|
return -1;
|
}
|
}
|
dst = (uint32*)(mQueue + 1) + mQueue->write * mQueue->size;
|
dst = (uint32*)(mQueue + 1) + mQueue->write * mQueue->size;
|
for(i = 0; i < mQueue->size; ++i)
|
for(i = 0; i < mQueue->size; ++i) //Copy the message into the queue
|
dst[i] = src[i];
|
dst[i] = src[i];
|
if(++mQueue->write >= mQueue->count)
|
if(++mQueue->write >= mQueue->count)
|
mQueue->write = 0;
|
mQueue->write = 0;
|
OS_CriticalEnd(state);
|
OS_CriticalEnd(state); //Re-enable interrupts
|
OS_SemaphorePost(mQueue->semaphore);
|
OS_SemaphorePost(mQueue->semaphore); //Wakeup the receiving thread
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Receive a message that is messageBytes long (defined during create)
|
|
//Wait at most ~10 msec ticks
|
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
|
int OS_MQueueGet(OS_MQueue_t *mQueue, void *message, int ticks)
|
{
|
{
|
uint32 state, *dst, *src;
|
uint32 state, *dst, *src;
|
int i, rc;
|
int i, rc;
|
|
|
assert(mQueue);
|
assert(mQueue);
|
dst = (uint32*)message;
|
rc = OS_SemaphorePend(mQueue->semaphore, ticks); //Wait for message
|
rc = OS_SemaphorePend(mQueue->semaphore, ticks);
|
|
if(rc)
|
if(rc)
|
return rc;
|
return rc; //Request timed out so rc = -1
|
state = OS_CriticalBegin();
|
state = OS_CriticalBegin(); //Disable interrupts
|
--mQueue->used;
|
--mQueue->used;
|
|
dst = (uint32*)message;
|
src = (uint32*)(mQueue + 1) + mQueue->read * mQueue->size;
|
src = (uint32*)(mQueue + 1) + mQueue->read * mQueue->size;
|
for(i = 0; i < mQueue->size; ++i)
|
for(i = 0; i < mQueue->size; ++i) //Copy message from the queue
|
dst[i] = src[i];
|
dst[i] = src[i];
|
if(++mQueue->read >= mQueue->count)
|
if(++mQueue->read >= mQueue->count)
|
mQueue->read = 0;
|
mQueue->read = 0;
|
OS_CriticalEnd(state);
|
OS_CriticalEnd(state); //Re-enable interrupts
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
|
|
Line 888... |
Line 913... |
/******************************************/
|
/******************************************/
|
typedef void (*JobFunc_t)();
|
typedef void (*JobFunc_t)();
|
static OS_MQueue_t *jobQueue;
|
static OS_MQueue_t *jobQueue;
|
static OS_Thread_t *jobThread;
|
static OS_Thread_t *jobThread;
|
|
|
|
//This thread waits for jobs that request a function to be called
|
static void JobThread(void *arg)
|
static void JobThread(void *arg)
|
{
|
{
|
uint32 message[4];
|
uint32 message[4];
|
JobFunc_t funcPtr;
|
JobFunc_t funcPtr;
|
(void)arg;
|
(void)arg;
|
Line 903... |
Line 929... |
}
|
}
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Call a function using the job thread so the caller won't be blocked
|
void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
|
void OS_Job(void (*funcPtr)(), void *arg0, void *arg1, void *arg2)
|
{
|
{
|
uint32 message[4];
|
uint32 message[4];
|
int rc;
|
int rc;
|
|
|
Line 926... |
Line 953... |
}
|
}
|
|
|
|
|
/***************** Timer ******************/
|
/***************** Timer ******************/
|
/******************************************/
|
/******************************************/
|
|
//This thread polls the list of timers to see if any have timed out
|
static void OS_TimerThread(void *arg)
|
static void OS_TimerThread(void *arg)
|
{
|
{
|
uint32 timeNow;
|
uint32 timeNow;
|
int diff, ticks;
|
int diff, ticks;
|
uint32 message[8];
|
uint32 message[8];
|
OS_Timer_t *timer;
|
OS_Timer_t *timer;
|
(void)arg;
|
(void)arg;
|
|
|
timeNow = OS_ThreadTime();
|
timeNow = OS_ThreadTime(); //Number of ~10 msec ticks since reboot
|
for(;;)
|
for(;;)
|
{
|
{
|
//Determine how long to sleep
|
//Determine how long to sleep
|
OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
|
OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
|
if(TimerHead)
|
if(TimerHead)
|
Line 982... |
Line 1010... |
}
|
}
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Create a timer that will send a message upon timeout
|
OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info)
|
OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info)
|
{
|
{
|
OS_Timer_t *timer;
|
OS_Timer_t *timer;
|
|
|
OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
|
OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER);
|
Line 1025... |
Line 1054... |
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
//Must not be called from an ISR
|
//Must not be called from an ISR
|
|
//In ~10 msec ticks send a message (or callback)
|
void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart)
|
void OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart)
|
{
|
{
|
OS_Timer_t *node, *prev;
|
OS_Timer_t *node, *prev;
|
int diff, check=0;
|
int diff, check=0;
|
|
|
Line 1066... |
Line 1096... |
}
|
}
|
else
|
else
|
prev->next = timer;
|
prev->next = timer;
|
OS_SemaphorePost(SemaphoreLock);
|
OS_SemaphorePost(SemaphoreLock);
|
if(check)
|
if(check)
|
OS_SemaphorePost(SemaphoreTimer);
|
OS_SemaphorePost(SemaphoreTimer); //Wakeup OS_TimerThread
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
//Must not be called from an ISR
|
//Must not be called from an ISR
|
Line 1173... |
Line 1203... |
}
|
}
|
|
|
|
|
/**************** Init ********************/
|
/**************** Init ********************/
|
/******************************************/
|
/******************************************/
|
|
//If there aren't any other ready to run threads then spin here
|
static volatile uint32 IdleCount;
|
static volatile uint32 IdleCount;
|
static void OS_IdleThread(void *arg)
|
static void OS_IdleThread(void *arg)
|
{
|
{
|
(void)arg;
|
(void)arg;
|
|
|
Line 1188... |
Line 1219... |
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
#ifndef DISABLE_IRQ_SIM
|
#ifndef DISABLE_IRQ_SIM
|
|
//Simulate the hardware interrupts
|
static void OS_IdleSimulateIsr(void *arg)
|
static void OS_IdleSimulateIsr(void *arg)
|
{
|
{
|
uint32 count=0, value;
|
uint32 count=0, value;
|
(void)arg;
|
(void)arg;
|
|
|
Line 1211... |
Line 1243... |
#endif //DISABLE_IRQ_SIM
|
#endif //DISABLE_IRQ_SIM
|
|
|
|
|
/******************************************/
|
/******************************************/
|
//Plasma hardware dependent
|
//Plasma hardware dependent
|
|
//ISR called every ~10 msecs when bit 18 of the counter register toggles
|
static void OS_ThreadTickToggle(void *arg)
|
static void OS_ThreadTickToggle(void *arg)
|
{
|
{
|
uint32 status, mask, state;
|
uint32 status, mask, state;
|
|
|
//Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT
|
//Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT
|
Line 1227... |
Line 1260... |
OS_SpinUnlock(state);
|
OS_SpinUnlock(state);
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Initialize the OS by setting up the system heap and the tick interrupt
|
void OS_Init(uint32 *heapStorage, uint32 bytes)
|
void OS_Init(uint32 *heapStorage, uint32 bytes)
|
{
|
{
|
int i;
|
int i;
|
if((int)OS_Init > 0x10000000) //Running from DDR?
|
if((int)OS_Init > 0x10000000) //Running from DDR?
|
OS_AsmInterruptInit(); //Patch interrupt vector
|
OS_AsmInterruptInit(); //Patch interrupt vector
|
Line 1248... |
Line 1282... |
//Detected that running in simulator so create SimIsr thread
|
//Detected that running in simulator so create SimIsr thread
|
UartPrintfCritical("SimIsr\n");
|
UartPrintfCritical("SimIsr\n");
|
OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
|
OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0);
|
}
|
}
|
#endif //DISABLE_IRQ_SIM
|
#endif //DISABLE_IRQ_SIM
|
//Plasma hardware dependent
|
//Plasma hardware dependent (register for OS tick interrupt every ~10 msecs)
|
OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTickToggle);
|
OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTickToggle);
|
OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
|
OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);
|
}
|
}
|
|
|
|
|
/******************************************/
|
/******************************************/
|
|
//Start thread swapping
|
void OS_Start(void)
|
void OS_Start(void)
|
{
|
{
|
ThreadSwapEnabled = 1;
|
ThreadSwapEnabled = 1;
|
(void)OS_SpinLock();
|
(void)OS_SpinLock();
|
OS_ThreadReschedule(1);
|
OS_ThreadReschedule(1);
|
Line 1288... |
Line 1323... |
uint32 state, cpuIndex, i, j, ok, delay;
|
uint32 state, cpuIndex, i, j, ok, delay;
|
|
|
cpuIndex = OS_CpuIndex();
|
cpuIndex = OS_CpuIndex();
|
delay = cpuIndex + 8;
|
delay = cpuIndex + 8;
|
state = OS_AsmInterruptEnable(0);
|
state = OS_AsmInterruptEnable(0);
|
|
//Spin until only this CPU has the spin lock
|
do
|
do
|
{
|
{
|
ok = 1;
|
ok = 1;
|
if(++SpinLockArray[cpuIndex] == 1)
|
if(++SpinLockArray[cpuIndex] == 1)
|
{
|
{
|
for(i = 0; i < OS_CPU_COUNT; ++i)
|
for(i = 0; i < OS_CPU_COUNT; ++i)
|
{
|
{
|
if(i != cpuIndex && SpinLockArray[i])
|
if(i != cpuIndex && SpinLockArray[i])
|
ok = 0;
|
ok = 0; //Another CPU has the spin lock
|
}
|
}
|
if(ok == 0)
|
if(ok == 0)
|
{
|
{
|
SpinLockArray[cpuIndex] = 0;
|
SpinLockArray[cpuIndex] = 0;
|
for(j = 0; j < delay; ++j) //wait a bit
|
for(j = 0; j < delay; ++j) //wait a bit
|
Line 1338... |
Line 1374... |
#define UartScanf UartScanf2
|
#define UartScanf UartScanf2
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <termios.h>
|
#include <termios.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
|
//Support RTOS inside Linux
|
void Sleep(unsigned int value)
|
void Sleep(unsigned int value)
|
{
|
{
|
usleep(value * 1000);
|
usleep(value * 1000);
|
}
|
}
|
|
|
Line 1389... |
Line 1426... |
extern void __stdcall Sleep(unsigned long value);
|
extern void __stdcall Sleep(unsigned long value);
|
#endif
|
#endif
|
|
|
static uint32 Memory[8];
|
static uint32 Memory[8];
|
|
|
|
//Simulates device register memory reads
|
uint32 MemoryRead(uint32 address)
|
uint32 MemoryRead(uint32 address)
|
{
|
{
|
Memory[2] |= IRQ_UART_WRITE_AVAILABLE; //IRQ_STATUS
|
Memory[2] |= IRQ_UART_WRITE_AVAILABLE; //IRQ_STATUS
|
switch(address)
|
switch(address)
|
{
|
{
|
Line 1412... |
Line 1450... |
return Memory[2];
|
return Memory[2];
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
//Simulates device register memory writes
|
void MemoryWrite(uint32 address, uint32 value)
|
void MemoryWrite(uint32 address, uint32 value)
|
{
|
{
|
switch(address)
|
switch(address)
|
{
|
{
|
case UART_WRITE:
|
case UART_WRITE:
|
Line 1442... |
Line 1481... |
|
|
|
|
/**************** Example *****************/
|
/**************** Example *****************/
|
#ifndef NO_MAIN
|
#ifndef NO_MAIN
|
#ifdef WIN32
|
#ifdef WIN32
|
static uint8 HeapSpace[1024*512];
|
static uint8 HeapSpace[1024*512]; //For simulation on a PC
|
#endif
|
#endif
|
|
|
int main(int programEnd, char *argv[])
|
int main(int programEnd, char *argv[])
|
{
|
{
|
(void)programEnd; //Pointer to end of used memory
|
(void)programEnd; //Pointer to end of used memory
|
(void)argv;
|
(void)argv;
|
|
|
UartPrintfCritical("Starting RTOS\n");
|
UartPrintfCritical("Starting RTOS\n");
|
#ifdef WIN32
|
#ifdef WIN32
|
OS_Init((uint32*)HeapSpace, sizeof(HeapSpace));
|
OS_Init((uint32*)HeapSpace, sizeof(HeapSpace)); //For PC simulation
|
#else
|
#else
|
//Remaining space after program in 1MB external RAM
|
//Create heap in remaining space after program in 1MB external RAM
|
OS_Init((uint32*)programEnd,
|
OS_Init((uint32*)programEnd,
|
RAM_EXTERNAL_BASE + RAM_EXTERNAL_SIZE - programEnd);
|
RAM_EXTERNAL_BASE + RAM_EXTERNAL_SIZE - programEnd);
|
#endif
|
#endif
|
UartInit();
|
UartInit();
|
OS_ThreadCreate("Main", MainThread, NULL, 100, 4000);
|
OS_ThreadCreate("Main", MainThread, NULL, 100, 4000);
|