SikendeRTOS
RTOS for ARM Cortex M3+ SoCs designed and written from scratch
OS.c
Go to the documentation of this file.
1
6#include "cpu.h"
7#include "startup.h"
8#include "Timer.h"
9#include "Switch.h"
10#include "OS.h"
11
12
13// OS ASM functions
14void StartOS(void);
17
18
22static INT32U Stacks[NUMTHREADS][STACKSIZE];
23
27static INT32U NumOfThreads = 0;
28
32static INT64U OS_SystemTime = 0;
33
37static INT64U OS_SystemTimeMS;
38
42static MailBoxType MailBox;
43
44
48struct Tcb{
51 // double LL
52 struct Tcb* next;
53 struct Tcb* prev;
54 // basic properties
59 // Lab 3 blocking threads
64};
65typedef struct Tcb tcbType;
66static tcbType tcbs[NUMTHREADS];
67
72
77
81static FIFO_t OS_FIFO[FIFO_SIZE];
82static INT32U Get_Idx = 0, Put_Idx = 0;
83static Sema4Type SemaFIFO;
84
85//************* PRIORITY SCHEDULING GLOBALS AND ARRAYS**************************************************************************
86//Value > 0, else 0 if empty, change upon OS_Kill, Total number of threads in priority level
88// Array to skip threads if threas sleep/block, if 0 move to next thread, Avaliable priorities to run
90// LL for each priority level
92// Pointer to end of LL
94
95//*********************************************** Basic OS Initilization Functions ********************
96//*********************************************** Add CPU/Peripheral Functions to these if desired ********************
97
103static void SetInitialStack(INT32U i){
104 tcbs[i].sp = &Stacks[i][STACKSIZE-16]; // thread stack pointer
105 Stacks[i][STACKSIZE-1] = 0x01000000; // thumb bit
106 Stacks[i][STACKSIZE-3] = 0x14141414; // R14
107 Stacks[i][STACKSIZE-4] = 0x12121212; // R12
108 Stacks[i][STACKSIZE-5] = 0x03030303; // R3
109 Stacks[i][STACKSIZE-6] = 0x02020202; // R2
110 Stacks[i][STACKSIZE-7] = 0x01010101; // R1
111 Stacks[i][STACKSIZE-8] = 0x00000000; // R0
112 Stacks[i][STACKSIZE-9] = 0x11111111; // R11
113 Stacks[i][STACKSIZE-10] = 0x10101010; // R10
114 Stacks[i][STACKSIZE-11] = 0x09090909; // R9
115 Stacks[i][STACKSIZE-12] = 0x08080808; // R8
116 Stacks[i][STACKSIZE-13] = 0x07070707; // R7
117 Stacks[i][STACKSIZE-14] = 0x06060606; // R6
118 Stacks[i][STACKSIZE-15] = 0x05050505; // R5
119 Stacks[i][STACKSIZE-16] = 0x04040404; // R4
120}
121
126static void SetThreads(void){
127 for (INT8 i = 0; i < NUMTHREADS; i++){
128 tcbs[i].status = -1;
129 tcbs[i].id = -1;
130 tcbs[i].sleepState = 0;
131 }
132 for (INT8 i = 0; i < PRIORITYLEVELS; i++){
133 PriorityPtr[i] = 0;
134 }
135}
136
141static void OS_SleepHandler(void){
142 // increment timer for sleep
143 OS_SystemTimeMS++;
144
145 // run through list of threads and decrement sleep counter
146 for(INT32 i=0; i < NUMTHREADS; i++){
147 // check if thread not dead and sleeping
148 if(((tcbs[i].status != -1) && (tcbs[i].sleepState))){
149 tcbs[i].sleepState--;
150 if (tcbs[i].sleepState == 0){
151 PriorityAvailable[tcbs[i].priority]++;
152 }
153 }
154 }
155}
156
157/* OS_SystemTime
158 * @brief increment timer, more accurate than 1ms timer
159**/
161 OS_SystemTime++;
162}
163
168 // 1 ms timer for OS/ sleep decrement
169 Timer0A_Init(&OS_SleepHandler, TIME_1MS, 1);
170 // accurate system timer, optional
172
173}
174
179 NVIC_SYS_PRI3_R =(NVIC_SYS_PRI3_R&0x00FFFFFF)|0xD0000000; // priority 6
180 NVIC_SYS_PRI3_R =(NVIC_SYS_PRI3_R&0xFF00FFFF)|0x00E00000; // priority 7
181
182}
183
188void OS_Init(void){
191 OS_SystemTimeMS = 0;
192 OS_SystemTime = 0;
193 SetThreads();
195 RunPt = &tcbs[0];
196}
197
201void LinkTCB(tcbType* newThread){
202 // add to Doubly LL, copy pasta
203 tcbType* endPtr = RunPt->prev;
204 // increment count
205 PriorityAvailable[newThread->priority]++;
206 newThread->next = RunPt;
207 RunPt->prev = newThread;
208 newThread->prev = endPtr;
209 endPtr->next = newThread;
210
211 //increment thread count
212 NumOfThreads++;
213}
214
218void UnLinkTCB(void){
219 //do removal for double LL
220 RunPt->prev->next = RunPt->next;
221 RunPt->next->prev = RunPt->prev;
222 NumOfThreads--;
223}
224
230 // go to end of LL to add tcb or add to head, copy pasta
231 if(semaPt->blockThreads == 0){
232 semaPt->blockThreads = RunPt;
233 semaPt->blockThreads->nextBlocked = 0;
234 }else{
235 // go to end
236 tcbType* endPtr = semaPt->blockThreads;
237 while(endPtr->nextBlocked != 0){
238 endPtr = endPtr->nextBlocked;
239 }
240 endPtr->nextBlocked = RunPt;
241 endPtr->nextBlocked->nextBlocked = 0;
242 }
243}
244
251 // copy pasta ee 312,
252 tcbType* headLink = semaPt->blockThreads;
253 semaPt->blockThreads = headLink->nextBlocked;
254 return headLink;
255}
256
261void UnBlockTCB(Sema4Type* semaPt){
262 tcbType* blocked = RemoveBlockedFromSemaphore(semaPt);
263 LinkTCB(blocked);
264 blocked->sema4Blocked = 0;
265}
266
271void BlockTCB(Sema4Type* semaPt){
272 RunPt->sema4Blocked = semaPt;
274 UnLinkTCB();
275 AddBlockedToSemaphore(semaPt);
276 OS_Suspend();
277}
278
285void OS_Launch(INT32U theTimeSlice){
286 INT32 pri = 0;
287 for (pri = 0; pri < PRIORITYLEVELS; pri++){
288 if (PriorityAvailable[pri] > 0)
289 break;
290 }
291
292 RunPt = PriorityPtr[pri];
293 SysTick_Init(theTimeSlice);
294 StartOS();
295}
296
300void OS_Scheduler(void){
301 INT32 pri = 0;
303 // go through priority list, exit when next highest thread found
304 for (pri = 0; pri < PRIORITYLEVELS; pri++){
305 if (PriorityAvailable[pri] > 0)
306 break;
307 }
308
309 // check if next priority thread is the same priority
310 if (pri == RunPt->priority){
312 // Ensure next thread not sleeping
315 }
316 // run lower pri task
317 }else{
318 if (pri != PRIORITYLEVELS){
319 NextRunPt = PriorityPtr[pri];
320 // Ensure next thread not sleeping
323 }
324 }
325 }
326
327}
328
333 OS_Scheduler();
334 //go to pendSV
335 NVIC_INT_CTRL_R = NVIC_INT_CTRL_PEND_SV; // go to context switch
336 //PE1 ^= 0x02;
337}
338
343void OS_Suspend(void)
344{
345 //OS_Scheduler();
346 //NVIC_INT_CTRL_R = NVIC_INT_CTRL_PEND_SV; // go to context switch
347 NVIC_ST_CURRENT_R = 0; // clear timer
348 NVIC_INT_CTRL_R = 0x04000000; // go to SysTick Handler
349}
350
358 INT32 pri = newThread->priority;
359
360 // Add head priority task
361 if(PriorityTotal[pri] == 0){
362 PriorityPtr[pri] = newThread;
363 PriorityLastPtr[pri] = newThread;
364 newThread->nextPriority = newThread;
365 // Add thread to existing LL, put at head so O(1)
366 } else{
367 newThread->nextPriority = PriorityLastPtr[pri]->nextPriority;
368 PriorityLastPtr[pri]->nextPriority = newThread;
369 PriorityPtr[pri] = newThread;
370 }
371
372 //increment counters
373 PriorityAvailable[pri]++;
374 PriorityTotal[pri]++;
375
376}
377
386INT8 OS_AddThread(void(*task)(void), INT32U priority){
387 // check if max thread limit reached
388 if(NumOfThreads >= NUMTHREADS){
389 return 0;
390 }
391 // Start of adding thread
392 INT32U sr = StartCritical();
393
394 // search for availalbe tcb
395 INT8 idxFreeTCB = 0;
396 for(idxFreeTCB = 0; idxFreeTCB < NUMTHREADS; idxFreeTCB++){
397 //break once found
398 if(tcbs[idxFreeTCB].status == -1){
399 break;
400 }
401 }
402
403 // check if this is the only thread
404 if(NumOfThreads == 0){
405 tcbs[NumOfThreads].next = &tcbs[0];
406 tcbs[NumOfThreads].prev = &tcbs[0];
407 RunPt = &tcbs[0];
408 tcbs[0].priority = priority;
409 }
410 // add thread, treat like linked list, (code from EE312)
411 else{
412 if(RunPt->status == -1 || idxFreeTCB >= NUMTHREADS){
413 EndCritical(sr);
414 return 0;
415 }
416
417 //insertion for doubly linked list
418 tcbType* endPtr = RunPt->prev;
419 tcbs[idxFreeTCB].next = RunPt;
420 RunPt->prev = &tcbs[idxFreeTCB];
421 tcbs[idxFreeTCB].prev = endPtr;
422 endPtr->next = &tcbs[idxFreeTCB];
423 }
424 //init stack and add task to TCB
425 SetInitialStack(idxFreeTCB);
426 Stacks[idxFreeTCB][STACKSIZE-2] = (INT32)(task); // PC
427
428 // init vars of tcb
429 tcbs[idxFreeTCB].sleepState = 0;
430 tcbs[idxFreeTCB].status = 0;
431 tcbs[idxFreeTCB].id = idxFreeTCB;
432 tcbs[idxFreeTCB].priority = priority;
433
434 //increment thread count
435 NumOfThreads++;
436
437 // Go to Priority Scheduler addition
438 OS_AddPriorityThread(&tcbs[idxFreeTCB]);
439 EndCritical(sr);
440 // yay it worked, unless this is buggy, then :(
441 return 1;
442}
443
449 return RunPt->id;
450}
451
456void OS_InitSemaphore(Sema4Type *semaPt, INT32 value){ //Occurs once at the start
457 INT32U sr = StartCritical();
458 semaPt->Value = value;
459 semaPt->blockThreads = 0;
460 EndCritical(sr);
461}
462
468void OS_Wait(Sema4Type *semaPt){ // Called at run time to provide synchronization between threads
469
470 INT32U sr = StartCritical();
471 semaPt->Value--;
472 if (semaPt->Value < 0){
473 BlockTCB(semaPt);
474 }
475 EndCritical(sr);
476
477}
478
483void OS_Signal(Sema4Type *semaPt){
484 INT32U sr = StartCritical();
485 semaPt->Value++;
486
487 if(semaPt->Value < 1){
488 UnBlockTCB(semaPt);
489 }
490 EndCritical(sr);
491}
492
499void OS_bWait(Sema4Type *semaPt){
501 semaPt->Value--;
502 if (semaPt->Value < 0){
503 BlockTCB(semaPt);
504 }
506
507}
508
514void OS_bSignal(Sema4Type *semaPt){
515 INT32U sr = StartCritical();
516 semaPt->Value++;
517 if(semaPt->Value < 1){
518 UnBlockTCB(semaPt);
519 }
520 EndCritical(sr);
521}
522
528void OS_Sleep(INT32U sleepTime){
530 // add current thread to sleep list like in class
531 RunPt->sleepState = sleepTime;
532 // Priroity Scheduling
534
535 OS_Suspend();
537}
538
542void OS_Kill(void){
544 // Fix Priority Scheduler and remove TCB from all LL
545 tcbType *tmpPtr, *curPtr;
546
547 // Killed Thread is head (top) of linked list, EZ, O(1), copy past LL
551 // Remove first link in list (O(1), copy pasta LL
552 } else if (RunPt == PriorityPtr[RunPt->priority]){
555 // find thread to delete O(N)
556 } else {
557 tmpPtr = PriorityPtr[RunPt->priority];
558 curPtr = PriorityPtr[RunPt->priority];
559 // dp searjc
560 while (curPtr != RunPt){
561 tmpPtr = curPtr;
562 curPtr = curPtr->nextPriority;
563 }
564 // check to see if last link in list
567 PriorityLastPtr[RunPt->priority] = tmpPtr;
568 } else {
569 tmpPtr->nextPriority = curPtr->nextPriority;
570 }
571 }
572 // OS_Kill(Sikender); why doesnt this work?????
573 tcbs[RunPt->id].status = -1;
574 NumOfThreads--;
577
578 OS_Suspend();
580 //should never run
581 INT8U errorVar = 0;
582 while(1) errorVar++;
583}
584
593INT8 OS_AddPeriodicThread(void(*task)(void), INT32U period, INT32U priority){
594 static INT8U NumberOfPeriodicTasks = 0;
595
596 if (NumberOfPeriodicTasks == 0){
597 Timer1A_Init(task, period, priority);
598 } else if (NumberOfPeriodicTasks == 1){
599 Timer1B_Init(task, period, priority);
600 } else if (NumberOfPeriodicTasks == 2){
601 Timer2A_Init(task, period, priority);
602 } else if (NumberOfPeriodicTasks == 3){
603 Timer2B_Init(task, period, priority);
604 } else if (NumberOfPeriodicTasks == 4){
605 Timer3A_Init(task, period, priority);
606 } else if (NumberOfPeriodicTasks == 5){
607 Timer3B_Init(task, period, priority);
608 } else if (NumberOfPeriodicTasks == 6){
609 Timer4A_Init(task, period, priority);
610 } else if (NumberOfPeriodicTasks == 7){
611 Timer4B_Init(task, period, priority);
612 // no more timers dawg :(
613 }else{
614 return 0;
615 }
616 NumberOfPeriodicTasks++;
617 return 1;
618}
619
626INT8 OS_AddSW1Task(void(*task)(void), INT32U priority){
627 SW1_Init(task, priority);
628 return 1;
629}
630
638INT8 OS_AddSW2Task(void(*task)(void), INT32U priority){
639 SW2_Init(task, priority);
640 return 1;
641}
642
646void OS_Fifo_Init(void){
647 INT32U sr = StartCritical(); // is this necessary? cause idk
648 Put_Idx = Get_Idx = 0;
649 OS_InitSemaphore(&SemaFIFO, 0);
650 EndCritical(sr);
651}
652
660 // check if FiFo Full
661 if(SemaFIFO.Value == FIFO_SIZE) return 0;
662
663 // add data to FiFo
664 OS_FIFO[Put_Idx] = data;
665 Put_Idx = (Put_Idx + 1) % FIFO_SIZE;
666
667 // signal to show there's data
668 OS_Signal(&SemaFIFO);
669 return 1;
670}
671
677 OS_Wait(&SemaFIFO);
678 FIFO_t data;
679 // check if empty
680 if(Put_Idx == Get_Idx) return 0;
681 // get and return data
682 data = OS_FIFO[Get_Idx];
683 Get_Idx = (Get_Idx + 1) % FIFO_SIZE;
684 return data;
685}
686
692 //return FiFo_Size_Unused;
693 //return FIFO_SIZE;
694 INT32U size = SemaFIFO.Value;
695 return size;
696}
697
702 //MailBox.data = -1;
703 // set semaphores
704 OS_InitSemaphore(&MailBox.Empty, 1); //FML i set this wrong 4AM
706}
707
716 // wait then signal to send data, wait until FiFo has space available
718 MailBox.data = data;
720}
721
730 INT32U data;
732 data = MailBox.data;
734 return data;
735}
736
741 return TIMER0_TAR_R;
742}
743
750 if(start> stop)
751 return (start - stop);
752 else{
753 return (0xFFFFFFFF - stop + start);
754 }
755}
756
760void OS_ClearMsTime(void){
761 OS_SystemTimeMS = 0;
762}
763
768 return OS_SystemTimeMS;
769}
770
int8_t INT8
Definition: cpu_vars.h:17
int32_t INT32
Definition: cpu_vars.h:19
uint64_t INT64U
Definition: cpu_vars.h:16
uint32_t INT32U
Definition: cpu_vars.h:15
uint8_t INT8U
Definition: cpu_vars.h:13
void OS_SystemTimeHandler(void)
Definition: OS.c:160
void OS_Signal(Sema4Type *semaPt)
This function(Spinlock) will signal that a mutual exclusion is taking place in a function.
Definition: OS.c:483
INT8 OS_AddPeriodicThread(void(*task)(void), INT32U period, INT32U priority)
Adds periodic background thread. Cannot spin, sleep, die, rest, etc. cause it's ISR,...
Definition: OS.c:593
void OS_EnableInterrupts(void)
void OS_AddPriorityThread(tcbType *newThread)
This function decides next thread to run, now uses priority scheduler.
Definition: OS.c:357
INT32 PriorityTotal[PRIORITYLEVELS]
Definition: OS.c:87
void OS_bWait(Sema4Type *semaPt)
This function implements binary wait.
Definition: OS.c:499
void Peripheral_Init(void)
This function initializes extra IO used by OS, add new inits here.
Definition: OS.c:167
void OS_Suspend(void)
This function suspends current thread by forcing context switch call.
Definition: OS.c:343
void StartOS(void)
INT32U OS_Fifo_Size(void)
Gets current size of FiFo.
Definition: OS.c:691
void OS_DisableInterrupts(void)
INT8 OS_AddThread(void(*task)(void), INT32U priority)
This function decides next thread to run, now uses priority scheduler.
Definition: OS.c:386
void UnBlockTCB(Sema4Type *semaPt)
Remove TCB from blocked list.
Definition: OS.c:261
INT8 OS_Fifo_Put(FIFO_t data)
Definition: OS.c:659
tcbType * PriorityPtr[PRIORITYLEVELS]
Definition: OS.c:91
INT32U OS_IdThread(void)
Get current thread ID.
Definition: OS.c:448
tcbType * NextRunPt
Contains next thread to run.
Definition: OS.c:76
tcbType * PriorityLastPtr[PRIORITYLEVELS]
Definition: OS.c:93
void LinkTCB(tcbType *newThread)
LinkTCB Add TCB to doubly Linked List, copy pasta ee 312.
Definition: OS.c:201
INT32 PriorityAvailable[PRIORITYLEVELS]
Definition: OS.c:89
void OS_Scheduler(void)
This function runs next highest priority thread, PRIORITY SCHEDULER.
Definition: OS.c:300
void OS_MailBox_Init(void)
Initializes communication channel for OS.
Definition: OS.c:701
void OS_Fifo_Init(void)
Definition: OS.c:646
INT32U OS_ReadMsTime(void)
Definition: OS.c:767
void OS_Kill(void)
This function kill/deletes current thread from schedule.
Definition: OS.c:542
void OS_MailBox_Send(INT32U data)
This function will be called from a foreground thread It will spin/block if the MailBox contains data...
Definition: OS.c:715
INT32U OS_MailBox_Recv(void)
This function will be called from a foreground thread It will spin/block if the MailBox is empty.
Definition: OS.c:729
INT32U OS_TimeDifference(INT32U start, INT32U stop)
Definition: OS.c:749
tcbType * RunPt
Contains currently running thread.
Definition: OS.c:71
void OS_SystemPriority(void)
Set priority of Systick and PendSV (Context Switch handlers)
Definition: OS.c:178
void OS_bSignal(Sema4Type *semaPt)
This function implements binary signal.
Definition: OS.c:514
void OS_Wait(Sema4Type *semaPt)
semaphore value decrement
Definition: OS.c:468
void UnLinkTCB(void)
UnLinkTCB Remove thread form Doubly LL of TCB, copy pasta.
Definition: OS.c:218
INT8 OS_AddSW2Task(void(*task)(void), INT32U priority)
This function adds a thread to run and its priority when a button is pressed.
Definition: OS.c:638
INT32U OS_Time(void)
Definition: OS.c:740
void SysTick_Handler(void)
This function decides next thread to run.
Definition: OS.c:332
void OS_Launch(INT32U theTimeSlice)
This function starts the scheduler and enables interrupts.
Definition: OS.c:285
void OS_Sleep(INT32U sleepTime)
This function puts a thread to sleep.
Definition: OS.c:528
INT8 OS_AddSW1Task(void(*task)(void), INT32U priority)
This function adds a thread to run and its priority when a button is pressed.
Definition: OS.c:626
void OS_Init(void)
initialize operating system, disable interrupts until OS_Launch initialize OS controlled I/O: serial,...
Definition: OS.c:188
void OS_ClearMsTime(void)
Definition: OS.c:760
void AddBlockedToSemaphore(Sema4Type *semaPt)
Add TCB to blocked Linked list of semaphore.
Definition: OS.c:229
void OS_InitSemaphore(Sema4Type *semaPt, INT32 value)
Initialize semaphore to given value.
Definition: OS.c:456
void BlockTCB(Sema4Type *semaPt)
Add current TCB to blocked list then yield, ratatatat.
Definition: OS.c:271
tcbType * RemoveBlockedFromSemaphore(Sema4Type *semaPt)
Remove TCB from blocked list, assuiming thread already blocked, else rip program.
Definition: OS.c:250
FIFO_t OS_Fifo_Get(void)
Definition: OS.c:676
Functions for OS.
#define STACKSIZE
max size of stack
Definition: OSConfig.h:29
#define FIFO_SIZE
Size of OS FIFO in 32 bit words.
Definition: OSConfig.h:40
INT32 FIFO_t
Definition: OSConfig.h:42
#define PRIORITYLEVELS
number of priorities
Definition: OSConfig.h:34
#define NUMTHREADS
max number of threads
Definition: OSConfig.h:24
#define TIME_1MS
Definition: OSConfig.h:13
void SW1_Init(void(*task)(void), INT32U priority)
Definition: Switch.c:23
void SW2_Init(void(*task)(void), INT32U priority)
Definition: Switch.c:48
Periodic Timer setup for TM4c123.
void Timer0A_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:40
void Timer1B_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:101
void Timer4A_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:204
void Timer4B_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:230
void Timer2B_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:140
void Timer1A_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:80
void Timer0B_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:60
void Timer3A_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:158
void Timer3B_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:183
void Timer2A_Init(void(*task)(void), uint32_t period, uint32_t priority)
Definition: Timer.c:122
void SysTick_Init(uint32_t period)
Definition: Timer.c:31
Contains Enable/Disable Interrupts, Start/EndCritical from startup file Used to control global ISR fl...
INT32U StartCritical(void)
Start Criticat Sections, Disable Global Interrupts.
void EndCritical(INT32U sr)
End of critical section (ISR = prev ISR) @parameter sr previously saved PSR.
void EnableInterrupts(void)
Enable Global Interrupts (ISR = 0)
void DisableInterrupts(void)
Disable Global Interrupts (ISR = 1)
Definition: OS.h:27
Sema4Type Full
Definition: OS.h:29
Sema4Type Empty
Definition: OS.h:28
INT32U data
Definition: OS.h:30
Definition: OS.h:16
struct Tcb * blockThreads
Definition: OS.h:18
INT32 Value
Definition: OS.h:17
Definition: OS.c:48
struct Tcb * next
Definition: OS.c:52
struct Tcb * nextBlocked
Definition: OS.c:61
struct Tcb * nextPriority
Definition: OS.c:62
INT8U priority
Definition: OS.c:57
struct Tcb * prev
Definition: OS.c:53
INT32U sleepState
Definition: OS.c:58
INT32 status
Definition: OS.c:56
INT32 id
Definition: OS.c:55
Sema4Type * sema4Blocked
Definition: OS.c:60
INT32U * sp
Definition: OS.c:50
#define TIMER0_TAR_R
Definition: tm4c123gh6pm.h:975
#define NVIC_INT_CTRL_R
#define NVIC_ST_CURRENT_R
#define NVIC_INT_CTRL_PEND_SV
#define NVIC_SYS_PRI3_R