adding in ecen425 RTOS final lab
This commit is contained in:
+206
@@ -0,0 +1,206 @@
|
||||
#include "clib.h"
|
||||
#include "yakk.h"
|
||||
#include "yaku.h"
|
||||
#include "PriorityQueue.h"
|
||||
#include "DelayQueue.h"
|
||||
|
||||
//User Accessible Variables
|
||||
unsigned int YKCtxSwCount = 0;
|
||||
unsigned int YKIdleCount = 0;
|
||||
unsigned int YKTickCounter = 0;
|
||||
|
||||
//Kernel Accessible Variables
|
||||
static unsigned int ISRCallDepth = 0;
|
||||
TCB* currentTask = null;
|
||||
PriorityQueue readyQueue;
|
||||
DelayQueue delayQueue;
|
||||
static TaskBlock taskBlock;
|
||||
static SemBlock semBlock;
|
||||
static MsgQueueBlock msgQueueBlock;
|
||||
static int idleTaskStack[IDLETASKSTACKSIZE];
|
||||
static enum KernelState kernelState = K_BLOCKED;
|
||||
|
||||
unsigned int getYKCtxSwCount() {
|
||||
return YKCtxSwCount;
|
||||
}
|
||||
|
||||
unsigned int getYKIdleCount() {
|
||||
return YKIdleCount;
|
||||
}
|
||||
|
||||
unsigned int getYKTickNum() {
|
||||
return YKTickCounter;
|
||||
}
|
||||
|
||||
void setYKIdleCount(int value) {
|
||||
YKIdleCount = value;
|
||||
}
|
||||
|
||||
void setYKCtxSwCount(int value) {
|
||||
YKCtxSwCount = value;
|
||||
}
|
||||
|
||||
void YKEnterISR(void) {
|
||||
YKEnterMutex();
|
||||
ISRCallDepth++;
|
||||
YKExitMutex();
|
||||
}
|
||||
|
||||
void YKExitISR(void) {
|
||||
YKEnterMutex();
|
||||
ISRCallDepth--;
|
||||
if (ISRCallDepth == 0) {
|
||||
YKExitMutex();
|
||||
YKScheduler();
|
||||
}
|
||||
YKExitMutex();
|
||||
}
|
||||
|
||||
unsigned int YKGetISRCallDepth(void) {
|
||||
|
||||
return ISRCallDepth;
|
||||
}
|
||||
|
||||
void YKInitialize(void) {
|
||||
|
||||
YKEnterMutex();
|
||||
|
||||
//Set up queues
|
||||
initializePriorityQueue(&readyQueue);
|
||||
initializeDelayQueue();
|
||||
|
||||
//Set up Task Block
|
||||
taskBlock.nextFreeTCB == 0;
|
||||
//
|
||||
|
||||
//Set up Idle Task
|
||||
YKNewTask(YKIdleTask, &idleTaskStack[IDLETASKSTACKSIZE], 100);
|
||||
//
|
||||
|
||||
YKExitMutex();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void YKScheduler(void) {
|
||||
|
||||
TCB* readyTask;
|
||||
YKEnterMutex();
|
||||
if (kernelState == K_BLOCKED) return;
|
||||
readyTask = peekPriorityQueue(&readyQueue);
|
||||
if (readyTask == null) exit(READY_QUEUE_EMPTY);
|
||||
if (readyTask != currentTask) {
|
||||
currentTask = readyTask;
|
||||
currentTask->state = T_READY;
|
||||
YKCtxSwCount++;
|
||||
readyTask->state = T_RUNNING;
|
||||
YKDispatcher(readyTask);
|
||||
YKExitMutex();
|
||||
return;
|
||||
}
|
||||
YKExitMutex();
|
||||
return;
|
||||
}
|
||||
|
||||
void YKNewTask(void (*task)(void), void* taskStack, unsigned char priority) {
|
||||
|
||||
TCB* newTask;
|
||||
|
||||
//Obtain a TCB
|
||||
newTask = getNewTCB();
|
||||
if (newTask == null) exit(NEW_TASK_FAILED);
|
||||
|
||||
//Fill TCB
|
||||
newTask->tid = 0;
|
||||
newTask->priority = priority;
|
||||
newTask->stackPointer = ((void*)((int*) taskStack - 12));
|
||||
newTask->state = T_READY;
|
||||
newTask->delayCount = 0;
|
||||
newTask->next = null;
|
||||
newTask->prev = null;
|
||||
|
||||
//Set up Stack
|
||||
asm("push bx");
|
||||
asm("push cx");
|
||||
asm("mov bx, [bp+6]"); //Get address of stack
|
||||
asm("mov cx, [bp+4]"); //Get address of function pointer
|
||||
asm("mov [bx-2], word 0x0200"); //Move flag register onto the stack
|
||||
asm("mov [bx-4], word 0x0");
|
||||
asm("mov [bx-6], cx");
|
||||
asm("pop cx");
|
||||
asm("pop bx");
|
||||
|
||||
insertPriorityQueue(&readyQueue, newTask);
|
||||
asm("int 0x20");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
TCB* getNewTCB(void) {
|
||||
|
||||
TCB* task;
|
||||
if (taskBlock.nextFreeTCB < MAX_TASKS + 1) {
|
||||
task = &taskBlock.TCBPool[taskBlock.nextFreeTCB++];
|
||||
return task;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
YKSEM* getNewSem(void) {
|
||||
|
||||
YKSEM* semaphore;
|
||||
if (semBlock.nextFreeSem < MAX_SEMS) {
|
||||
semaphore = &semBlock.SemPool[semBlock.nextFreeSem++];
|
||||
return semaphore;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
YKQ* getNewQueue(void) {
|
||||
|
||||
YKQ* messageQueue;
|
||||
if (msgQueueBlock.nextFreeQueue < MAX_QUEUES) {
|
||||
messageQueue = &msgQueueBlock.QueuePool[msgQueueBlock.nextFreeQueue++];
|
||||
return messageQueue;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void YKRun(void) {
|
||||
|
||||
YKEnterMutex();
|
||||
kernelState = K_RUNNING;
|
||||
YKScheduler();
|
||||
YKExitMutex();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void YKDelayTask(unsigned int count) {
|
||||
|
||||
TCB* delayedTask;
|
||||
|
||||
if (count == 0) return;
|
||||
|
||||
delayedTask = removePriorityQueue(&readyQueue);
|
||||
delayedTask->state = T_BLOCKED;
|
||||
delayedTask->delayCount = count;
|
||||
insertDelayQueue(delayedTask);
|
||||
asm("int 0x20");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void YKTickHandler(void) {
|
||||
|
||||
tickClock();
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user