URL
https://opencores.org/ocsvn/plasma/plasma/trunk
Subversion Repositories plasma
Compare Revisions
- This comparison shows the changes necessary to convert path
/plasma/trunk
- from Rev 404 to Rev 405
- ↔ Reverse comparison
Rev 404 → Rev 405
/kernel/rtos_ex.c
0,0 → 1,164
/*-------------------------------------------------------------------- |
* TITLE: Plasma Real Time Operating System Extensions |
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com) |
* DATE CREATED: 12/17/05 |
* FILENAME: rtos_ex.c |
* PROJECT: Plasma CPU core |
* COPYRIGHT: Software placed into the public domain by the author. |
* Software 'as is' without warranty. Author liable for nothing. |
* DESCRIPTION: |
* Support simulation under Windows. |
* Support simulating multiple CPUs using symmetric multiprocessing. |
*--------------------------------------------------------------------*/ |
#include "plasma.h" |
#include "rtos.h" |
|
/************** WIN32 Simulation Support *************/ |
#ifdef WIN32 |
#undef kbhit |
#undef getch |
#undef putch |
extern int kbhit(void); |
extern int getch(void); |
extern int putch(int); |
unsigned int __stdcall GetCurrentThreadId(void); |
typedef void (*LPTHREAD_START_ROUTINE)(void *lpThreadParameter); |
void * __stdcall CreateThread(void *lpsa, unsigned int dwStackSize, |
LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, |
unsigned int dwCreationFlags, unsigned int *pdwThreadId); |
|
#if OS_CPU_COUNT > 1 |
static unsigned int ThreadId[OS_CPU_COUNT]; |
|
//PC simulation of multiple CPUs |
void OS_InitSimulation(void) |
{ |
|
int i; |
ThreadId[0] = GetCurrentThreadId(); |
for(i = 1; i < OS_CPU_COUNT; ++i) |
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)OS_Start, NULL, 0, &ThreadId[i]); |
} |
#endif |
|
static uint32 Memory[8]; |
|
//Simulates device register memory reads |
uint32 MemoryRead(uint32 address) |
{ |
Memory[2] |= IRQ_UART_WRITE_AVAILABLE; //IRQ_STATUS |
switch(address) |
{ |
case UART_READ: |
if(kbhit()) |
Memory[0] = getch(); //UART_READ |
Memory[2] &= ~IRQ_UART_READ_AVAILABLE; //clear bit |
return Memory[0]; |
case IRQ_MASK: |
return Memory[1]; //IRQ_MASK |
case IRQ_MASK + 4: |
Sleep(10); |
return 0; |
case IRQ_STATUS: |
if(kbhit()) |
Memory[2] |= IRQ_UART_READ_AVAILABLE; |
return Memory[2]; |
} |
return 0; |
} |
|
//Simulates device register memory writes |
void MemoryWrite(uint32 address, uint32 value) |
{ |
switch(address) |
{ |
case UART_WRITE: |
putch(value); |
break; |
case IRQ_MASK: |
Memory[1] = value; |
break; |
case IRQ_STATUS: |
Memory[2] = value; |
break; |
} |
} |
|
uint32 OS_AsmInterruptEnable(uint32 enableInterrupt) |
{ |
return enableInterrupt; |
} |
|
void OS_AsmInterruptInit(void) |
{ |
} |
#endif //WIN32 |
|
|
#if OS_CPU_COUNT > 1 |
static volatile uint8 SpinLockArray[OS_CPU_COUNT]; |
/******************************************/ |
uint32 OS_CpuIndex(void) |
{ |
#ifdef WIN32 |
int i; |
unsigned int threadId=GetCurrentThreadId(); |
for(i = 0; i < OS_CPU_COUNT; ++i) |
{ |
if(threadId == ThreadId[i]) |
return i; |
} |
#endif |
return 0; //0 to OS_CPU_COUNT-1; Read a CPU specific GPIO value |
} |
|
|
/******************************************/ |
//Symmetric Multiprocessing Spin Lock Mutex |
uint32 OS_SpinLock(void) |
{ |
uint32 state, cpuIndex, i, ok, delay; |
volatile uint32 keepVar; |
|
cpuIndex = OS_CpuIndex(); |
state = OS_AsmInterruptEnable(0); //disable interrupts |
if(++SpinLockArray[cpuIndex] > 1) //check for nesting |
return state; |
delay = (4 + cpuIndex) << 2; |
|
//Spin until only this CPU has the spin lock |
for(;;) |
{ |
ok = 1; |
for(i = 0; i < OS_CPU_COUNT; ++i) |
{ |
if(i != cpuIndex && SpinLockArray[i]) |
ok = 0; //Another CPU has the spin lock |
} |
if(ok) |
return state; |
SpinLockArray[cpuIndex] = 0; |
OS_AsmInterruptEnable(state); //re-enable interrupts |
for(i = 0; i < delay; ++i) //wait a bit |
++ok; |
keepVar = ok; //don't optimize away the delay loop |
if(delay < 128) |
delay <<= 1; |
state = OS_AsmInterruptEnable(0); //disable interrupts |
SpinLockArray[cpuIndex] = 1; |
} |
} |
|
|
/******************************************/ |
void OS_SpinUnlock(uint32 state) |
{ |
uint32 cpuIndex; |
cpuIndex = OS_CpuIndex(); |
if(--SpinLockArray[cpuIndex] == 0) |
OS_AsmInterruptEnable(state); |
|
assert(SpinLockArray[cpuIndex] < 10); |
} |
#endif //OS_CPU_COUNT > 1 |
|