// ******** OS_Kill ************ // kill the currently running thread, release its TCB memory // input: none // output: none void OS_Kill(void) { int id; tcbType *temp; // Starting critical section to delete TCB OS_DisableInterrupts(); NumThreads--; id = (*RunPt).id; // Make TCB invalid tcbs[id].valid = INVALID; // Remove TCB from linked list temp = tcbs[id].prev; (*temp).next = tcbs[id].next; temp = tcbs[id].next; (*temp).prev = tcbs[id].prev; // Check if thread is Head or Tail if(&tcbs[id] == Head) { Head = tcbs[id].next; } else if(&tcbs[id] == Tail) { Tail = tcbs[id].prev; } // Trigger threadswitch OS_Suspend(); while(1) { } // Never leave }
// ******** OS_Init ************ // initialize operating system, disable interrupts until OS_Launch // initialize OS controlled I/O: systick, 50 MHz PLL // input: none // output: none void OS_Init(void){ OS_DisableInterrupts(); PLL_Init(); // set processor clock to 50 MHz NVIC_ST_CTRL_R = 0; // disable SysTick during setup NVIC_ST_CURRENT_R = 0; // any write to current clears it NVIC_SYS_PRI3_R =(NVIC_SYS_PRI3_R&0x00FFFFFF)|0xE0000000; // priority 7 }
int OS_AddThread(void(*task)(void), unsigned long stackSize, unsigned long priority) { uint32_t status; status = OS_StartCritical(); //we will take the first thread from the dead pool if(DeadPt == '\0') { OS_DisableInterrupts(); while(1){} } (DeadPt)->id = uniqueId; //unique id (DeadPt)->active = 1; (DeadPt)->sleepState = 0; //flag (DeadPt)->priority = priority; (DeadPt)->blockedState = 0; //flag (DeadPt)->needToWakeUp = 0; //flag SetInitialStack(DeadPt, stackSize); (DeadPt)->stack[stackSize - 2] = (uint32_t)task; //push PC uniqueId++; addDeadToScheduler(&DeadPt); if(higherPriorityAdded == 1) { OS_Suspend(); } OS_EndCritical(status); return 1; }
// ******** OS_Suspend ************ // suspend execution of currently running thread // scheduler will choose another thread to execute // Can be used to implement cooperative multitasking // Same function as OS_Sleep(0) // input: none // output: none void OS_Suspend(void) { long curPriority; unsigned long curTimeSlice; volatile int i; OS_DisableInterrupts(); // Determines NextPt Scheduler(); // Get priority of next thread and calculate timeslice curPriority = (*NextPt).priority; curTimeSlice = calcTimeSlice(curPriority); // Sets next systick period, does not rest counting SysTickPeriodSet(curTimeSlice); // Write to register forces systick to reset counting NVIC_ST_CURRENT_R = 0; IntPendSet(FAULT_PENDSV); OS_EnableInterrupts(); return; }
// ******** OS_Sleep ************ // place this thread into a dormant state // input: number of msec to sleep // output: none // You are free to select the time resolution for this function // Sleep time is a multiple of context switch time period // OS_Sleep(0) implements cooperative multitasking void OS_Sleep(unsigned long sleepTime) { OS_DisableInterrupts(); threadRemover(&SleepPt, sleepTime * 2); sleepCount++; switched = 1; OS_Suspend(); OS_EnableInterrupts(); }
// ******** OS_Kill ************ // kill the currently running thread, release its TCB and stack // input: none // output: none void OS_Kill(void) { OS_DisableInterrupts(); threadRemover(&DeadPt, 0); //parameter 0 will be ignored deadCount++; switched = 1; OS_Suspend(); OS_EnableInterrupts(); }
int OS_AddPeriodicThread(void(*task)(void), unsigned long period, unsigned long priority){ int32_t status; status = OS_StartCritical(); //now need to add to linked list if(DeadPeriodicPt == '\0') //cant add this thread { OS_DisableInterrupts(); while(1){}; } removeAndAddToSingleList(&DeadPeriodicPt, period, task, priority); EndCritical(status ); return 0; //added sucesfully }
void TriggerSensor0(void) { int i; OS_DisableInterrupts(); GPIO_PORTB0 = 0x01; // delay 5 us for (i = 0; i < 75; i++); GPIO_PORTB0 = 0x00; GPIO_PORTB_DIR_R &= ~0x01; // make PB0 in GPIO_PORTB_IM_R |= 0x01; // enable PB0 interrupts OS_EnableInterrupts(); }
// ******** OS_Wait ************ // decrement semaphore // Lab2 spinlock // Lab3 block if less than zero // input: pointer to a counting semaphore // output: none void OS_Wait(Sema4Type *semaPt) { uint32_t status; status = OS_StartCritical(); (*semaPt).Value--; //decrease count if((*semaPt).Value < 0) { OS_Block(semaPt); //block and put into semaphore blocked list OS_Suspend(); OS_EnableInterrupts(); OS_DisableInterrupts(); } OS_EndCritical(status); }
// ******** OS_bWait ************ // Lab2 spinlock, set to 0 // Lab3 block if less than zero // input: pointer to a binary semaphore // output: none void OS_bWait(Sema4Type *semaPt) { int32_t status; status = OS_StartCritical(); while((*semaPt).Value == 0) { OS_Block(semaPt); //block and put into semaphore blocked list OS_Suspend(); OS_EnableInterrupts(); OS_DisableInterrupts(); } //while someone has the semaphor (*semaPt).Value = 0; //take the semaphore EndCritical(status ); }
BOOL FIFO_Get(TFIFO * const FIFO, uint8_t * const dataPtr) { OS_DisableInterrupts(); //Enter Critical Section if (FIFO->NbBytes != 0) { FIFO->NbBytes--; *dataPtr = FIFO->Buffer[FIFO->Start]; FIFO->Start = (FIFO->Start + 1) % FIFO_SIZE; OS_EnableInterrupts(); return (bTRUE); } OS_EnableInterrupts(); return (bFALSE); }
BOOL FIFO_Put(TFIFO * const FIFO, const uint8_t data) { OS_DisableInterrupts(); //Enter Critical Section if (FIFO->NbBytes < FIFO_SIZE) //Ensure that the buffer is not full before putting data within it { FIFO->NbBytes++; //Increment data counter FIFO->Buffer[FIFO->End] = data; //Store data in the buffer FIFO->End = (FIFO->End + 1) % FIFO_SIZE; //increment end pointer within FIFO_SIZE OS_EnableInterrupts(); return (bTRUE); } OS_EnableInterrupts(); return (bFALSE); }
void Ping_Init(void) { volatile unsigned long delay; OS_DisableInterrupts(); SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOB; // activate port B delay = SYSCTL_RCGC2_R; // **** Port B Edge Trigger Initialization **** GPIO_PORTB_DIR_R |= 0x03; // make PB0-1 out GPIO_PORTB_DEN_R |= 0x03; // enable digital I/O on PB0-1 GPIO_PORTB_PUR_R |= 0x03; // enable pull up on PB0-1 GPIO_PORTB_IEV_R |= 0x03; // make PB0-1 rising edge triggered GPIO_PORTB_IS_R &= ~0x03; // make PB0-1 edge-sensitive GPIO_PORTB_ICR_R = 0x03; // clear flag NVIC_PRI0_R = (NVIC_PRI1_R&0xFFFF00FF)|0x00006000; // priority 3 NVIC_EN0_R |= NVIC_EN0_INT1; OS_InitSemaphore(&Sensor0Free, 1); OS_InitSemaphore(&Sensor1Free, 1); OS_InitSemaphore(&Sensor0DataAvailable, 0); OS_InitSemaphore(&Sensor1DataAvailable, 0); OS_EnableInterrupts(); }
// ******** OS_Init ************ // initialize operating system, disable interrupts until OS_Launch // initialize OS controlled I/O: serial, ADC, systick, LaunchPad I/O and timers // input: none // output: none void OS_Init() { uint8_t counter = 0; Timer2_Init(80000000); //timer2 keeps track oftime OS_DisableInterrupts(); PLL_Init(Bus80MHz); //ADC_Init(0); UART_Init(); // initialize UART //construct linked list for (counter = 0; counter<NUMBEROFTHREADS - 1; counter++) { threadPool[counter].nextTCB = &threadPool[(counter + 1)]; //address of next TCB } threadPool[NUMBEROFTHREADS - 1].nextTCB = '\0'; //lab3 linked list for periodic threads for (counter = 0; counter<NUMBEROFPERIODICTHREADS - 1; counter++) { periodicPool[counter].nextPeriodicThread = &periodicPool[(counter + 1)]; //address of next TCB } periodicPool[NUMBEROFPERIODICTHREADS - 1].nextPeriodicThread = '\0'; DeadPt = &threadPool[0]; //point to first element of not active threads DeadPeriodicPt = &periodicPool[0]; deadCount = NUMBEROFTHREADS; deadPeriodicCount = NUMBEROFPERIODICTHREADS; RunPt = '\0'; SchedulerPt = '\0'; SleepPt = '\0'; PeriodPt = '\0'; //Timer2_Init(20000); //1 ms period for taking time!!!!!! NVIC_ST_CTRL_R = 0; // disable SysTick during setup NVIC_ST_CURRENT_R = 0; // any write to current clears it NVIC_SYS_PRI3_R =(NVIC_SYS_PRI3_R&0x00FFFFFF)|0xE0000000; // priority 7 on systick NVIC_SYS_PRI3_R = (NVIC_SYS_PRI3_R & 0xFF1FFFFF) | 0x00E00000; //priority 7 on pendsv }
// ************ OS_Init ****************** // initialize operating system, disable interrupts until OS_Launch // initialize OS controlled I/O: serial, ADC, systick, select switch and timer2 // input: none // output: non void OS_Init(void) { int i; // Used for indexing // Disable interrupts OS_DisableInterrupts(); // Setting the clock to 50 MHz SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ); // Initialze peripherals UART0_Init(); ADC_Open(); Output_Init(); // Select switch SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_1); GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_RISING_EDGE); GPIOPinIntClear(GPIO_PORTF_BASE, GPIO_PIN_1); // Down switch SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_1); GPIOPadConfigSet(GPIO_PORTE_BASE, GPIO_PIN_1, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); GPIOIntTypeSet(GPIO_PORTE_BASE, GPIO_PIN_1, GPIO_RISING_EDGE); GPIOPinIntClear(GPIO_PORTE_BASE, GPIO_PIN_1); // Initialize Timer2A and Timer2B: Periodic Background Threads SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2); TimerDisable(TIMER2_BASE, TIMER_A | TIMER_B); TimerConfigure(TIMER2_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PERIODIC); // Initialize Timer0B: Used for time keeping TimerDisable(TIMER0_BASE, TIMER_B); TimerConfigure(TIMER0_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PERIODIC); TimerIntDisable(TIMER0_BASE, TIMER_TIMB_TIMEOUT); TimerLoadSet(TIMER0_BASE, TIMER_B, 65535); TimerPrescaleSet(TIMER0_BASE, TIMER_B, 5); // One unit is 100ns TimerEnable(TIMER0_BASE, TIMER_B); // Initialize Timer1A: Used for sleep decrementing SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); TimerDisable(TIMER1_BASE, TIMER_A); TimerConfigure(TIMER1_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PERIODIC | TIMER_CFG_B_PERIODIC); TimerIntDisable(TIMER1_BASE, TIMER_TIMA_TIMEOUT); TimerLoadSet(TIMER1_BASE, TIMER_A, 50000); // Every interrupt is 1ms // Setting priorities for all interrupts // To add more, look up correct names in inc\hw_ints.h IntPrioritySet(FAULT_PENDSV, (0x07 << 5)); IntPrioritySet(FAULT_SYSTICK, (0x06 << 5)); IntPrioritySet(INT_TIMER1A, (0x02 << 5)); IntPrioritySet(INT_UART0, (0x03 << 5)); IntPrioritySet(INT_ADC0SS0, (0x01 << 5)); IntPrioritySet(INT_ADC0SS3, (0x01 << 5)); // Initializing TCBs for(i = 0; i < MAXTHREADS; i++) { tcbs[i].valid = INVALID; tcbs[i].blockedState = '\0'; } RunPt = &tcbs[0]; // Thread 0 will run first }
void addThreadToBlocked(struct TCB ** toAdd) { struct TCB * removed; struct TCB * temp; (*RunPt).active = 0; (*RunPt).blockedState = 1; //remove from active temp = SchedulerPt; if(RunPt == temp) //first element { if(schedulerCount == 0) { OS_DisableInterrupts(); while(1){}; } if(schedulerCount == 1) { OS_DisableInterrupts(); removed = SchedulerPt; //store before we remove SchedulerPt = '\0'; while(1){}; } else //remove and fix { while((*temp).nextTCB != (SchedulerPt)) { temp = (*temp).nextTCB; } //now at end of Scheduler pool (*temp).nextTCB = (*SchedulerPt).nextTCB; removed = SchedulerPt; //store before we remove SchedulerPt = (*SchedulerPt).nextTCB; nextBeforeSwitch = SchedulerPt; //hax } } else //not the first element, could be middle or end (theres no end in circular) { while((*temp).nextTCB != (RunPt)) { temp = (*temp).nextTCB; } nextBeforeSwitch = temp->nextTCB->nextTCB; //hax removed = (*temp).nextTCB; (*temp).nextTCB = (*(*temp).nextTCB).nextTCB; //remove from linked list } //now we have the node we took out in the "removed" variable temp = *toAdd; if(temp == '\0') { *toAdd = removed; (*removed).nextTCB = '\0'; } else { struct TCB * temp = (*toAdd); if((*removed).priority < (*(*toAdd)).priority) // gonna be added at beginning { temp = (*(*toAdd)).nextTCB; //save before removing which node should be the first after removal (*toAdd) = removed; (*removed).nextTCB = temp; //point node to first element of where it will be added } else { while( ((*temp).nextTCB != '\0') && ((*removed).priority >= (*(*temp).nextTCB).priority)) { temp = (*temp).nextTCB; } //now we are at the priority where we want to add to struct TCB * nextBeforeAdding = (*temp).nextTCB; //save before rerouting to restore at end (*temp).nextTCB = removed; temp = (*temp).nextTCB; //temp now equals thread (*temp).nextTCB = nextBeforeAdding; //restore connection } } schedulerCount--; }
static void threadRemover(struct TCB ** toAdd, unsigned long sleepTime) { struct TCB * removed; struct TCB * temp; (*RunPt).active = 0; //remove from active temp = SchedulerPt; if(RunPt == temp) //first element { if(schedulerCount == 0) { OS_DisableInterrupts(); while(1){}; } if(schedulerCount == 1) { OS_DisableInterrupts(); removed = SchedulerPt; //store before we remove SchedulerPt = '\0'; while(1){}; } else //remove and fix { while((*temp).nextTCB != (SchedulerPt)) { temp = (*temp).nextTCB; } //now at end of Scheduler pool (*temp).nextTCB = (*SchedulerPt).nextTCB; removed = SchedulerPt; //store before we remove SchedulerPt = (*SchedulerPt).nextTCB; nextBeforeSwitch = SchedulerPt; //hax } } else //not the first element, could be middle or end (theres no end in circular) { while((*temp).nextTCB != (RunPt)) { temp = (*temp).nextTCB; } nextBeforeSwitch = temp->nextTCB->nextTCB; //hax removed = (*temp).nextTCB; (*temp).nextTCB = (*(*temp).nextTCB).nextTCB; //remove from linked list } //now we have the node we took out in the "removed" variable if(*toAdd == SleepPt) //if putting thread to sleep need to update flag { (*removed).sleepState = sleepTime; if(sleepTime == 0) { (*removed).needToWakeUp = 1; } } temp = *toAdd; if(temp != '\0') { while((*temp).nextTCB != '\0') { temp = (*temp).nextTCB; } (*temp).nextTCB = removed; temp = (*temp).nextTCB; (*temp).nextTCB = '\0'; } else { *toAdd = removed; (*removed).nextTCB = '\0'; } schedulerCount--; }