📄 rtos.c
字号:
uint32 message[8]; OS_Timer_t *timer; (void)arg; timeNow = OS_ThreadTime(); for(;;) { //Determine how long to sleep OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER); if(TimerHead) ticks = TimerHead->ticksTimeout - timeNow; else ticks = OS_WAIT_FOREVER; OS_SemaphorePost(SemaphoreLock); OS_SemaphorePend(SemaphoreTimer, ticks); //Send messages for all timed out timers timeNow = OS_ThreadTime(); for(;;) { timer = NULL; OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER); if(TimerHead) { diff = timeNow - TimerHead->ticksTimeout; if(diff >= 0) timer = TimerHead; } OS_SemaphorePost(SemaphoreLock); if(timer == NULL) break; if(timer->ticksRestart) OS_TimerStart(timer, timer->ticksRestart, timer->ticksRestart); else OS_TimerStop(timer); //Send message message[0] = MESSAGE_TYPE_TIMER; message[1] = (uint32)timer; message[2] = (uint32)timer->info; OS_MQueueSend(timer->mqueue, message); } }}/******************************************/OS_Timer_t *OS_TimerCreate(const char *name, OS_MQueue_t *mQueue, uint32 info){ OS_Timer_t *timer; int startThread=0; OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER); if(SemaphoreTimer == NULL) { SemaphoreTimer = OS_SemaphoreCreate("Timer", 0); startThread = 1; } OS_SemaphorePost(SemaphoreLock); if(startThread) OS_ThreadCreate("Timer", OS_TimerThread, NULL, 250, 2000); timer = (OS_Timer_t*)OS_HeapMalloc(HEAP_SYSTEM, sizeof(OS_Timer_t)); if(timer == NULL) return NULL; timer->name = name; timer->mqueue = mQueue; timer->next = NULL; timer->prev = NULL; timer->info = info; timer->active = 0; return timer;}/******************************************/void OS_TimerDelete(OS_Timer_t *timer){ OS_TimerStop(timer); OS_HeapFree(timer);}/******************************************///Must not be called from an ISRvoid OS_TimerStart(OS_Timer_t *timer, uint32 ticks, uint32 ticksRestart){ OS_Timer_t *node, *prev; int diff, check=0; assert(timer); assert(InterruptInside == 0); ticks += OS_ThreadTime(); if(timer->active) OS_TimerStop(timer); OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER); if(timer->active) { //Prevent race condition OS_SemaphorePost(SemaphoreLock); return; } timer->ticksTimeout = ticks; timer->ticksRestart = ticksRestart; timer->active = 1; prev = NULL; for(node = TimerHead; node; node = node->next) { diff = ticks - node->ticksTimeout; if(diff <= 0) break; prev = node; } timer->next = node; timer->prev = prev; if(node) node->prev = timer; if(prev == NULL) { TimerHead = timer; check = 1; } else prev->next = timer; OS_SemaphorePost(SemaphoreLock); if(check) OS_SemaphorePost(SemaphoreTimer);}/******************************************///Must not be called from an ISRvoid OS_TimerStop(OS_Timer_t *timer){ assert(timer); assert(InterruptInside == 0); OS_SemaphorePend(SemaphoreLock, OS_WAIT_FOREVER); if(timer->active) { timer->active = 0; if(timer->prev == NULL) TimerHead = timer->next; else timer->prev->next = timer->next; if(timer->next) timer->next->prev = timer->prev; } OS_SemaphorePost(SemaphoreLock);}/***************** ISR ********************//******************************************/void OS_InterruptServiceRoutine(uint32 status, uint32 *stack){ int i; uint32 state; if(status == 0 && Isr[31]) Isr[31](stack); //SYSCALL or BREAK InterruptInside = 1; i = 0; do { if(status & 1) { if(Isr[i]) Isr[i](stack); else OS_InterruptMaskClear(1 << i); } status >>= 1; ++i; } while(status); InterruptInside = 0; state = OS_SpinLock(); if(ThreadNeedReschedule) OS_ThreadReschedule(ThreadNeedReschedule & 1); OS_SpinUnlock(state);}/******************************************/void OS_InterruptRegister(uint32 mask, OS_FuncPtr_t funcPtr){ int i; for(i = 0; i < 32; ++i) { if(mask & (1 << i)) Isr[i] = funcPtr; }}/******************************************///Plasma hardware dependentuint32 OS_InterruptStatus(void){ return MemoryRead(IRQ_STATUS);}/******************************************///Plasma hardware dependentuint32 OS_InterruptMaskSet(uint32 mask){ uint32 state; state = OS_CriticalBegin(); mask |= MemoryRead(IRQ_MASK); MemoryWrite(IRQ_MASK, mask); OS_CriticalEnd(state); return mask;}/******************************************///Plasma hardware dependentuint32 OS_InterruptMaskClear(uint32 mask){ uint32 state; state = OS_CriticalBegin(); mask = MemoryRead(IRQ_MASK) & ~mask; MemoryWrite(IRQ_MASK, mask); OS_CriticalEnd(state); return mask;}/**************** Init ********************//******************************************/static volatile uint32 IdleCount;static void OS_IdleThread(void *arg){ (void)arg; //Don't block in the idle thread! for(;;) { ++IdleCount; }}/******************************************/#ifndef DISABLE_IRQ_SIMstatic void OS_IdleSimulateIsr(void *arg){ uint32 count=0, value; (void)arg; for(;;) { MemoryRead(IRQ_MASK + 4); //calls Sleep(10)#if WIN32 while(OS_InterruptMaskSet(0) & IRQ_UART_WRITE_AVAILABLE) OS_InterruptServiceRoutine(IRQ_UART_WRITE_AVAILABLE, 0);#endif value = OS_InterruptMaskSet(0) & 0xf; if(value) OS_InterruptServiceRoutine(value, 0); ++count; }}#endif //DISABLE_IRQ_SIM/******************************************///Plasma hardware dependentstatic void OS_ThreadTickToggle(void *arg){ uint32 status, mask, state; //Toggle looking for IRQ_COUNTER18 or IRQ_COUNTER18_NOT state = OS_SpinLock(); status = MemoryRead(IRQ_STATUS) & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT); mask = MemoryRead(IRQ_MASK) | IRQ_COUNTER18 | IRQ_COUNTER18_NOT; mask &= ~status; MemoryWrite(IRQ_MASK, mask); OS_ThreadTick(arg); OS_SpinUnlock(state);}/******************************************/void OS_Init(uint32 *heapStorage, uint32 bytes){ int i; OS_AsmInterruptInit(); //Patch interrupt vector OS_InterruptMaskClear(0xffffffff); //Disable interrupts HeapArray[0] = OS_HeapCreate("Default", heapStorage, bytes); HeapArray[1] = HeapArray[0]; SemaphoreSleep = OS_SemaphoreCreate("Sleep", 0); SemaphoreLock = OS_SemaphoreCreate("Lock", 1); for(i = 0; i < OS_CPU_COUNT; ++i) OS_ThreadCreate("Idle", OS_IdleThread, NULL, 0, 256);#ifndef DISABLE_IRQ_SIM if((OS_InterruptStatus() & (IRQ_COUNTER18 | IRQ_COUNTER18_NOT)) == 0) { //Detected that running in simulator so create SimIsr thread UartPrintfCritical("SimIsr\n"); OS_ThreadCreate("SimIsr", OS_IdleSimulateIsr, NULL, 1, 0); }#endif //DISABLE_IRQ_SIM //Plasma hardware dependent OS_InterruptRegister(IRQ_COUNTER18 | IRQ_COUNTER18_NOT, OS_ThreadTickToggle); OS_InterruptMaskSet(IRQ_COUNTER18 | IRQ_COUNTER18_NOT);}/******************************************/void OS_Start(void){ ThreadSwapEnabled = 1; (void)OS_SpinLock(); OS_ThreadReschedule(1);}/******************************************///Place breakpoint herevoid OS_Assert(void){}#if OS_CPU_COUNT > 1static uint8 SpinLockArray[OS_CPU_COUNT];/******************************************/uint32 OS_CpuIndex(void){ return 0; //0 to OS_CPU_COUNT-1}/******************************************///Symmetric Multiprocessing Spin Lock Mutexuint32 OS_SpinLock(void){ uint32 state, cpuIndex, i, j, ok, delay; cpuIndex = OS_CpuIndex(); delay = cpuIndex + 8; state = OS_AsmInterruptEnable(0); do { ok = 1; if(++SpinLockArray[cpuIndex] == 1) { for(i = 0; i < OS_CPU_COUNT; ++i) { if(i != cpuIndex && SpinLockArray[i]) ok = 0; } if(ok == 0) { SpinLockArray[cpuIndex] = 0; for(j = 0; j < delay; ++j) //wait a bit ++i; if(delay < 128) delay <<= 1; } } } while(ok == 0); return state;}/******************************************/void OS_SpinUnlock(uint32 state){ uint32 cpuIndex; cpuIndex = OS_CpuIndex(); if(--SpinLockArray[cpuIndex] == 0) OS_AsmInterruptEnable(state); assert(SpinLockArray[cpuIndex] < 10);}/******************************************///Must be called with interrupts disabled and spin lockeduint32 OS_SpinCountGet(void){ uint32 cpuIndex, count; cpuIndex = OS_CpuIndex(); count = SpinLockArray[cpuIndex]; return count;}/******************************************///Must be called with interrupts disabled and spin lockedvoid OS_SpinCountSet(uint32 count){ uint32 cpuIndex; cpuIndex = OS_CpuIndex(); SpinLockArray[cpuIndex] = (uint8)count; assert(count);}/******************************************/void OS_CpuInterrupt(uint32 cpuIndex, uint32 bitfield){ //Request other CPU to reschedule threads (void)cpuIndex; (void)bitfield;}/******************************************/void OS_CpuInterruptServiceRoutine(void *arg){ uint32 state; (void)arg; state = OS_SpinLock(); OS_ThreadReschedule(0); OS_SpinUnlock(state);}#endif/************** WIN32 Support *************/#ifdef WIN32//Support RTOS inside Windowsextern int kbhit();extern int getch(void);extern int putch(int);extern void __stdcall Sleep(unsigned long value);static uint32 Memory[8];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;}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/**************** Example *****************/#ifndef NO_MAINstatic uint8 HeapSpace[1024*512];int main(void){ UartPrintfCritical("Starting RTOS\n"); OS_Init((uint32*)HeapSpace, sizeof(HeapSpace)); UartInit(); OS_ThreadCreate("Main", MainThread, NULL, 100, 64000); OS_Start(); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -