URL
https://opencores.org/ocsvn/plasma/plasma/trunk
Subversion Repositories plasma
Compare Revisions
- This comparison shows the changes necessary to convert path
/plasma
- from Rev 395 to Rev 396
- ↔ Reverse comparison
Rev 395 → Rev 396
/trunk/kernel/rtos.c
129,8 → 129,8
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 int ThreadSwapEnabled; |
static uint32 ThreadTime; |
static void *NeedToFree; |
static uint32 ThreadTime; //Number of ~10ms ticks since reboot |
static void *NeedToFree; //Closed but not yet freed thread |
static OS_Semaphore_t SemaphoreReserved[SEM_RESERVED_COUNT]; |
static OS_Semaphore_t *SemaphoreSleep; |
static OS_Semaphore_t *SemaphoreRelease; |
168,7 → 168,7
|
|
/******************************************/ |
//Modified from K&R |
//Modified from Kernighan & Ritchie "The C Programming Language" |
void *OS_HeapMalloc(OS_Heap_t *heap, int bytes) |
{ |
HeapNode_t *node, *prevp; |
395,7 → 395,7
threadNext = ThreadHead; |
while(threadNext && threadNext->cpuLock != -1 && |
threadNext->cpuLock != cpuIndex) |
threadNext = threadNext->next; |
threadNext = threadNext->next; //Skip CPU locked threads |
if(threadNext == NULL) |
return; |
threadCurrent = ThreadCurrent[cpuIndex]; |
516,9 → 516,10
env->sp = (uint32)stack + stackSize - 24; //minimum stack frame size |
env->pc = (uint32)OS_ThreadInit; |
|
//Add thread to linked list of ready to run threads |
state = OS_CriticalBegin(); |
OS_ThreadPriorityInsert(&ThreadHead, thread); |
OS_ThreadReschedule(0); |
OS_ThreadReschedule(0); //run highest priority thread |
OS_CriticalEnd(state); |
return thread; |
} |
531,6 → 532,7
|
for(;;) |
{ |
//Free the memory for closed but not yet freed threads |
OS_SemaphorePend(SemaphoreRelease, OS_WAIT_FOREVER); |
if(NeedToFree) |
OS_HeapFree(NeedToFree); |
552,6 → 554,7
|
|
/******************************************/ |
//Return currently running thread |
OS_Thread_t *OS_ThreadSelf(void) |
{ |
return ThreadCurrent[OS_CpuIndex()]; |
559,6 → 562,7
|
|
/******************************************/ |
//Sleep for ~10 msecs ticks |
void OS_ThreadSleep(int ticks) |
{ |
OS_SemaphorePend(SemaphoreSleep, ticks); |
566,6 → 570,7
|
|
/******************************************/ |
//Return the number of ~10 msecs ticks since reboot |
uint32 OS_ThreadTime(void) |
{ |
return ThreadTime; |
573,6 → 578,7
|
|
/******************************************/ |
//Save thread unique values |
void OS_ThreadInfoSet(OS_Thread_t *thread, uint32 index, void *Info) |
{ |
if(index < INFO_COUNT) |
621,7 → 627,8
|
|
/******************************************/ |
//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) |
{ |
OS_Thread_t *thread; |
629,7 → 636,7
int diff; |
(void)Arg; |
|
++ThreadTime; |
++ThreadTime; //Number of ~10 msec ticks since reboot |
while(TimeoutHead) |
{ |
thread = TimeoutHead; |
636,6 → 643,8
diff = ThreadTime - thread->ticksTimeout; |
if(diff < 0) |
break; |
|
//The thread has timed out waiting for a semaphore |
OS_ThreadTimeoutRemove(thread); |
semaphore = thread->semaphorePending; |
++semaphore->count; |
644,7 → 653,7
OS_ThreadPriorityRemove(&semaphore->threadHead, thread); |
OS_ThreadPriorityInsert(&ThreadHead, thread); |
} |
OS_ThreadReschedule(1); |
OS_ThreadReschedule(1); //Run highest priority thread |
} |
|
|
651,6 → 660,7
|
/***************** Semaphore **************/ |
/******************************************/ |
//Create a counting semaphore |
OS_Semaphore_t *OS_SemaphoreCreate(const char *name, uint32 count) |
{ |
OS_Semaphore_t *semaphore; |
681,6 → 691,7
|
|
/******************************************/ |
//Sleep the number of ticks (~10ms) until the semaphore is acquired |
int OS_SemaphorePend(OS_Semaphore_t *semaphore, int ticks) |
{ |
uint32 state, cpuIndex; |
689,9 → 700,10
|
assert(semaphore); |
assert(InterruptInside[OS_CpuIndex()] == 0); |
state = OS_CriticalBegin(); |
state = OS_CriticalBegin(); //Disable interrupts |
if(--semaphore->count < 0) |
{ |
//Semaphore not available |
if(ticks == 0) |
{ |
++semaphore->count; |
698,26 → 710,31
OS_CriticalEnd(state); |
return -1; |
} |
|
//Need to sleep until the semaphore is available |
cpuIndex = OS_CpuIndex(); |
thread = ThreadCurrent[cpuIndex]; |
assert(thread); |
thread->semaphorePending = semaphore; |
thread->ticksTimeout = ticks + OS_ThreadTime(); |
|
//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); |
thread->state = THREAD_PEND; |
if(ticks != OS_WAIT_FOREVER) |
OS_ThreadTimeoutInsert(thread); |
OS_ThreadTimeoutInsert(thread); //Check every ~10ms for timeouts |
assert(ThreadHead); |
OS_ThreadReschedule(0); |
returnCode = thread->returnCode; |
OS_ThreadReschedule(0); //Run highest priority thread |
returnCode = thread->returnCode; //Will be -1 if timed out |
} |
OS_CriticalEnd(state); |
OS_CriticalEnd(state); //Re-enable interrupts |
return returnCode; |
} |
|
|
/******************************************/ |
//Release a semaphore and possibly wake up a blocked thread |
void OS_SemaphorePost(OS_Semaphore_t *semaphore) |
{ |
uint32 state; |
727,6 → 744,7
state = OS_CriticalBegin(); |
if(++semaphore->count <= 0) |
{ |
//Wake up a thread that was waiting for this semaphore |
thread = semaphore->threadHead; |
OS_ThreadTimeoutRemove(thread); |
OS_ThreadPriorityRemove(&semaphore->threadHead, thread); |
742,6 → 760,7
|
/***************** Mutex ******************/ |
/******************************************/ |
//Create a mutex (a thread aware semaphore) |
OS_Mutex_t *OS_MutexCreate(const char *name) |
{ |
OS_Mutex_t *mutex; |
801,6 → 820,7
|
/***************** MQueue *****************/ |
/******************************************/ |
//Create a message queue |
OS_MQueue_t *OS_MQueueCreate(const char *name, |
int messageCount, |
int messageBytes) |
808,6 → 828,7
OS_MQueue_t *queue; |
int size; |
|
assert((messageBytes & 3) == 0); |
size = messageBytes / sizeof(uint32); |
queue = (OS_MQueue_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_MQueue_t) + |
messageCount * size * 4); |
835,6 → 856,7
|
|
/******************************************/ |
//Send a message that is messageBytes long (defined during create) |
int OS_MQueueSend(OS_MQueue_t *mQueue, void *message) |
{ |
uint32 state, *dst, *src; |
842,25 → 864,28
|
assert(mQueue); |
src = (uint32*)message; |
state = OS_CriticalBegin(); |
state = OS_CriticalBegin(); //Disable interrupts |
if(++mQueue->used > mQueue->count) |
{ |
//The message queue is full so discard the message |
--mQueue->used; |
OS_CriticalEnd(state); |
return -1; |
} |
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]; |
if(++mQueue->write >= mQueue->count) |
mQueue->write = 0; |
OS_CriticalEnd(state); |
OS_SemaphorePost(mQueue->semaphore); |
OS_CriticalEnd(state); //Re-enable interrupts |
OS_SemaphorePost(mQueue->semaphore); //Wakeup the receiving thread |
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) |
{ |
uint32 state, *dst, *src; |
867,18 → 892,18
int i, rc; |
|
assert(mQueue); |
dst = (uint32*)message; |
rc = OS_SemaphorePend(mQueue->semaphore, ticks); |
rc = OS_SemaphorePend(mQueue->semaphore, ticks); //Wait for message |
if(rc) |
return rc; |
state = OS_CriticalBegin(); |
return rc; //Request timed out so rc = -1 |
state = OS_CriticalBegin(); //Disable interrupts |
--mQueue->used; |
dst = (uint32*)message; |
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]; |
if(++mQueue->read >= mQueue->count) |
mQueue->read = 0; |
OS_CriticalEnd(state); |
OS_CriticalEnd(state); //Re-enable interrupts |
return 0; |
} |
|
890,6 → 915,7
static OS_MQueue_t *jobQueue; |
static OS_Thread_t *jobThread; |
|
//This thread waits for jobs that request a function to be called |
static void JobThread(void *arg) |
{ |
uint32 message[4]; |
905,6 → 931,7
|
|
/******************************************/ |
//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) |
{ |
uint32 message[4]; |
928,6 → 955,7
|
/***************** Timer ******************/ |
/******************************************/ |
//This thread polls the list of timers to see if any have timed out |
static void OS_TimerThread(void *arg) |
{ |
uint32 timeNow; |
936,7 → 964,7
OS_Timer_t *timer; |
(void)arg; |
|
timeNow = OS_ThreadTime(); |
timeNow = OS_ThreadTime(); //Number of ~10 msec ticks since reboot |
for(;;) |
{ |
//Determine how long to sleep |
984,6 → 1012,7
|
|
/******************************************/ |
//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 *timer; |
1027,6 → 1056,7
|
/******************************************/ |
//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) |
{ |
OS_Timer_t *node, *prev; |
1068,7 → 1098,7
prev->next = timer; |
OS_SemaphorePost(SemaphoreLock); |
if(check) |
OS_SemaphorePost(SemaphoreTimer); |
OS_SemaphorePost(SemaphoreTimer); //Wakeup OS_TimerThread |
} |
|
|
1175,6 → 1205,7
|
/**************** Init ********************/ |
/******************************************/ |
//If there aren't any other ready to run threads then spin here |
static volatile uint32 IdleCount; |
static void OS_IdleThread(void *arg) |
{ |
1190,6 → 1221,7
|
/******************************************/ |
#ifndef DISABLE_IRQ_SIM |
//Simulate the hardware interrupts |
static void OS_IdleSimulateIsr(void *arg) |
{ |
uint32 count=0, value; |
1213,6 → 1245,7
|
/******************************************/ |
//Plasma hardware dependent |
//ISR called every ~10 msecs when bit 18 of the counter register toggles |
static void OS_ThreadTickToggle(void *arg) |
{ |
uint32 status, mask, state; |
1229,6 → 1262,7
|
|
/******************************************/ |
//Initialize the OS by setting up the system heap and the tick interrupt |
void OS_Init(uint32 *heapStorage, uint32 bytes) |
{ |
int i; |
1250,7 → 1284,7
OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0); |
} |
#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_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT); |
} |
1257,6 → 1291,7
|
|
/******************************************/ |
//Start thread swapping |
void OS_Start(void) |
{ |
ThreadSwapEnabled = 1; |
1290,6 → 1325,7
cpuIndex = OS_CpuIndex(); |
delay = cpuIndex + 8; |
state = OS_AsmInterruptEnable(0); |
//Spin until only this CPU has the spin lock |
do |
{ |
ok = 1; |
1298,7 → 1334,7
for(i = 0; i < OS_CPU_COUNT; ++i) |
{ |
if(i != cpuIndex && SpinLockArray[i]) |
ok = 0; |
ok = 0; //Another CPU has the spin lock |
} |
if(ok == 0) |
{ |
1340,6 → 1376,7
#include <stdlib.h> |
#include <termios.h> |
#include <unistd.h> |
//Support RTOS inside Linux |
void Sleep(unsigned int value) |
{ |
usleep(value * 1000); |
1391,6 → 1428,7
|
static uint32 Memory[8]; |
|
//Simulates device register memory reads |
uint32 MemoryRead(uint32 address) |
{ |
Memory[2] |= IRQ_UART_WRITE_AVAILABLE; //IRQ_STATUS |
1414,6 → 1452,7
return 0; |
} |
|
//Simulates device register memory writes |
void MemoryWrite(uint32 address, uint32 value) |
{ |
switch(address) |
1444,7 → 1483,7
/**************** Example *****************/ |
#ifndef NO_MAIN |
#ifdef WIN32 |
static uint8 HeapSpace[1024*512]; |
static uint8 HeapSpace[1024*512]; //For simulation on a PC |
#endif |
|
int main(int programEnd, char *argv[]) |
1454,9 → 1493,9
|
UartPrintfCritical("Starting RTOS\n"); |
#ifdef WIN32 |
OS_Init((uint32*)HeapSpace, sizeof(HeapSpace)); |
OS_Init((uint32*)HeapSpace, sizeof(HeapSpace)); //For PC simulation |
#else |
//Remaining space after program in 1MB external RAM |
//Create heap in remaining space after program in 1MB external RAM |
OS_Init((uint32*)programEnd, |
RAM_EXTERNAL_BASE + RAM_EXTERNAL_SIZE - programEnd); |
#endif |