Embedded System Lab. II MicroC/OS-II MicroC/OS-II Structure Structure 경경경경경 경경경경경경 경 경 경
Embedded System Lab. II
MicroC/OS-II MicroC/OS-II Structure Structure
경희대학교 컴퓨터공학과조 진 성
Embedded System Lab. II 2
ContentsContents Introduction Kernel Structure Task Management Time Management Event Control Block Semaphore Management Mutual Exclusive Semaphore Event Flags Management Message Mail Box Management Message Queue Management Memory Management MicroC/OS-II Porting
Embedded System Lab. II
IntroductionIntroduction
Embedded System Lab. II 4
MicroC/OS-II 개요 1992 년 Jean J. Labrosse 가 만든 실시간 운영체제 학교나 개인의 교육과 같은 비상업적 목적에 한해 자유로이 사용 가능한
공개소스로서 , 소스코드의 수정 및 커널의 내부 구조를 이해하기 용이함 . 용도 : 각종 장비 개발이 가능 공식 사이트 : http://www.ucos-ii.com( 소스 다운로드 가능 )
상업적인 목적에 사용될 경우 라이센스를 따로 얻어야 함 .
IntroductionIntroduction
Embedded System Lab. II 5
MicroC/OS-II 는 Multitasking 이 가능한 Preemptive Real time Kernel MicroC/OS-II 는 태스크를 64 개까지 관리할 수 있다 .
최상위 , 최하위 4 개는 예약된 우선순위이므로 56 개의 Task 사용가능 엄격하게 관리할 수 있다면 OS_LOWEST_PRIO 를 제외하고 모든 우선순위
사용 가능하다 . Portable
이식성이 높은 ANSI-C 로 작성되었고 , 일부 프로세서에 의존적인 부분만어셈블리어로 작성됨 .
8Bit, 16Bit, 32Bit 및 64Bit, DSP 로도 Porting 할 수 있다 . Realiable
안정 - 결정적인 시스템에 사용할 수 있을 정도로 강인하고 안전한 운영체제 FAA(Federal Aviation Administration) 에서 승인됨 .(2000 년 7 월 )
Romable Scalable
Introduction (Cont’d)Introduction (Cont’d)
Embedded System Lab. II 6
임베디드 운영체제로써 대표적인 비 - 상용 공개형 커널 신뢰성과 안정성을 가진다 .
작은 사이즈 – 많은 시스템에 적용가능 작은 임베디드 시스템에 탑재 가능하며 임베디드 시스템 중에서도 강력한 네트워크가
필요한 곳과 높은 성능 시스템에 사용하는 것이 적합 (TCP/IP 스택 및 GUI 환경 라이센스 판매 )
프로젝트에 따른 소스 코드의 절약이 가능 스택체크 , 처리시간 체크 , Mailbox, Queue, Semaphore, Memory partitio
n 등의 시스템 서비스 제공 인터럽트 관리
태스크의 수행을 일시 중지하거나 재개가 가능하다 . 인터럽트 중첩 (up to 255 levels deep)
단점 초기 개발 투자와 라이센스 등의 후처리 문제로 인해 마음대로 사용하거나 배포에
어려움이 있음
Introduction (Cont’d)Introduction (Cont’d)
Embedded System Lab. II
Kernel StructureKernel Structure
Embedded System Lab. II 8
Kernel StructureKernel StructureuC/OS-II File Structure
Embedded System Lab. II 9
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
uC/OS-II 핵심 서비스 Enabled when set to 1 in OS_CFG.HOS_ENTER_CRITICAL()
OS_EXIT_CRITICAL()
OSInit()
OSStart()
OSIntEnter()
OSIntExit()
OSSchedLock() OS_SCHED_LOCK_EN
OSSchedUnlock() OS_SCHED_LOCK_EN
OSVersion()
Embedded System Lab. II 10
Kernel Structure (Cont’d)Kernel Structure (Cont’d) Critical Section, OS_ENTER_CRITICAL() & OS_EXIT_CRITICAL()
MicroC/OS-II 는 OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL() 라는 매크로를 사용하여 Interrupt 를 비활성화 / 활성화한다 .
OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL() 은 Critical Section 을감싸기 위해 항상 다음과 같이 쌍으로 사용한다 .
OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL() 은 서로 다른 세 가지방법으로 구현된다 .(OS_CPU.H 에 정의한 OS_CRITICAL_METHOD 상수를 통해 사용 )
1.OS_ENTER_CRITICAL() 와 OS_EXIT_CRITICAL() 에 인터럽트를 비활성화 / 활성화하는 프로세서 명령을 정의하여 사용
2. 인터럽트 비활성화 / 활성화 상태를 Stack 에 저장하여 사용 3. 프로세서 상태 워드의 값을 C 함수 안의 지역변수에 저장하는 기능을 가진
컴파일러를 사용할 경우
. OS_ENTER_CRITICAL(); /* uC/OS-II critical code section */ OS_EXIT_CRITICAL(); .
Embedded System Lab. II 11
Task – Infinite loop function MicroC/OS-II 는 Task 를 64 개까지 관리할 수 있다 . MicroC/OS-II 는 8 개의 예약된 태스크 중 Idle, CPU 사용률 계산 Task 를 사용
중 작은 숫자일수록 더 높은 우선순위 .(ex. 1 -> 최상위 우선순위 ) Task 우선순위를 통해 Task 를 식별한다 .
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void YourTask (void *pdata) { for (;;){ /* USER CODE */ Call one of uC/OS-II’s services: OSFlagPend(); OSMboxPend(); OSMutexPend(); OSQPend(); OSSemPend(); OSTaskDel(OS_PRIO_SELF); OSTaskSuspend(OS_PRIO_SELF); OSTimeDly(); OSTimeDlyHMSM(); /* USER CODE */ } }
Embedded System Lab. II 12
Kernel Structure (Cont’d)Kernel Structure (Cont’d) Task 상태
Embedded System Lab. II 13
Kernel Structure (Cont’d)Kernel Structure (Cont’d) Task Control Block
Task 생성시 각 Task 별로 Task control block 인 OS_TCB 를 할당 받는다 . OS_TCB 는 RAM 에 상주하면서 태스크의 상태를 관리한다 .
주요 변수 설명 OSTCBStkPtr : Task 의 스택 꼭대기를 가리키는 포인터 .
• 어셈블리어 코드의 문맥 전환 코드 부분에서 접근하는 유일한 필드 . • 맨 위에 배치하는 것이 어셈블리 언어에서 접근하도록 하는데 좋음 .
OSTCBStat : Task 의 상태 , 이 값들은 ucos.c 에 있음 OSTCBDly : Task 가 지연될 필요가 있을 때나 일정한 timeout 을 두고 이벤트
발생을 기다릴 때 사용 . OSTCBX, OSTCBY, OSTCBBitX, OSTCBBitY : Task 가 생성되거나 우선순위가
바뀔 때 사용 OSTCBNext, OSTCBPrev : OS_TCB 를 양방향으로 링크하는데 사용 . OSTCBEventPtr : Event control block 의 포인터
Embedded System Lab. II 14
Task Control Block
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
typedef struct os_tcb { OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */
#if OS_TASK_CREATE_EXT_EN > 0 void *OSTCBExtPtr; /* Pointer to user definable data for TCB */ OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack */ INT32U OSTCBStkSize; /* Size of task stack (in number of stack) */ INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */ INT16U OSTCBId; /* Task ID (0..65535) */#endif
struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */ struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0)
OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost(
) #endif
Embedded System Lab. II 15
Task Control Block
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)#if OS_TASK_DEL_EN > 0 OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */#endif OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */#endif
INT16U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event
INT8U OSTCBStat; /* Task status */ INT8U OSTCBPrio; /* Task priority (0 == highest, 63 == lowest)*/
INT8U OSTCBX; /* Bit position in group corresponding to task priority (0..7) */ INT8U OSTCBY; /* Index into ready table corresponding to task priority */ INT8U OSTCBBitX; /*Bit mask to access bit position in ready table */ INT8U OSTCBBitY; /*Bit mask to access bit position in ready group */#if OS_TASK_DEL_EN > 0 BOOLEAN OSTCBDelReq; /* Indicates whether a task needs to delete */#endif} OS_TCB;
Embedded System Lab. II 16
Kernel Structure (Cont’d) Kernel Structure (Cont’d) Task Control Block
OSTCBNext OSTCBNext OSTCBNext
OSTCBList
0[1] 0[2] 0[3]
0[61][62][63]
.
.
OS_TCB OS_TCB OS_TCB
[0]
OSTCBNext OSTCBNext OSTCBNext
OSTCBFreeListOS_TCB OS_TCB OS_TCB
OSTCBPrev OSTCBPrev OSTCBPrev0
OSTCBCurOSTCBHighRdy가장 높은 우선 순위
현재 실행 중인 타스크
자유 리스트
ptcb지역 변수
OSTCBNextOSTCBNextOSTCBNextOSTCBNext
OSTCBNextOSTCBNextOSTCBNext
Embedded System Lab. II 17
Kernel Structure (Cont’d)Kernel Structure (Cont’d) Ready List
두 개의 변수 OSRdyGrp 과 OSRdyTbl[ ] 로 Ready 상태의 Task 를 관리
현재 ready 상태인 Task 를 효율적을 검색
OSRdyGrp Task 의 우선순위에 의해 그룹화 한 그룹 당 8 개의 우선순위 (Task ID) 를 가짐 OSRdyGrp 내의 각 비트는 해당 그룹의 Ready 여부를 표시
OSRdyTbl[ ] 지정된 우선순위의 각 태스크가 Ready 인지 여부를 표시
Embedded System Lab. II 18
Kernel Structure (Cont’d)Kernel Structure (Cont’d) Ready List
Embedded System Lab. II 19
태스크를 준비상태로 만들기
준비 리스트에서 태스크 삭제
준비 리스트에서 최상위 우선순위 찾기
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
OSRdyGrp |= OSMapTbl[prio >> 3];OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
if((OSRdyTbl[prio>>3] &= ~OSMapTbl[prio & 0x07]) == 0) OSRdyGrp &= ~OSMapTbl[prio >> 3];
y = OSUnMapTbl[OSRdyGrp];x = OSUnMapTbl[OSRdyTbl[y]];prio = (y<<3) + x;
Embedded System Lab. II 20
Kernel Structure (Cont’d)Kernel Structure (Cont’d) Ready List 에서 최상위 우선순위 태스크 찾기
Embedded System Lab. II 21
Task Scheduling MicroC/OS-II 는 준비상태의 Task 중 항상 가장 높은 우선순위의 태스크를 실행 Task 수준의 Scheduling 은 OS_Sched() 함수에 의해 이뤄진다 . ISR 수준의 Scheduling 은 OSIntExit() 함수에 의해 이뤄진다 .
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OS_Sched (void){#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;#endif INT8U y;
OS_ENTER_CRITICAL(); if ((OSIntNesting == 0) && (OSLockNesting == 0)) { y = OSUnMapTbl[OSRdyGrp]; OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); if (OSPrioHighRdy != OSPrioCur) { OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSCtxSwCtr++; OS_TASK_SW(); } } OS_EXIT_CRITICAL();}
Embedded System Lab. II 22
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
OS_TASK_SW() 호출할 때
Task 레벨 Context Switching
현재 Task 문맥 저장
Embedded System Lab. II 23
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OSCtxSw (void){ PUSH R1, R2, R3 and R4 onto the current stack; OSTCBCur->OSTCBStkPtr = SP; OSTCBCur = OSTCBHighRdy; SP = OSTCBHighRdy->OSTCBStkPtr; POP R4, R3, R2 and R1 from the new stack; Execute a return from interrupt instruction;}
현재 Task 재실행
Embedded System Lab. II 24
Scheduler 잠그기 /풀기 OSSchedLock() 과 OSSchedUnlock() 함수를 이용하여 Scheduler 를 잠그고 푼다 . MicroC/OS-II 는 255 단계까지 Scheduling 잠금을 지원한다 . OSLockNesting 이 0 이 될 때 Scheduler 가 풀린다 .
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OSSchedLock (void){#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;#endif if (OSRunning == TRUE) { OS_ENTER_CRITICAL(); if (OSLockNesting < 255) { OSLockNesting++; } OS_EXIT_CRITICAL(); }}
Embedded System Lab. II 25
Scheduler 잠그기 / 풀기Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OSSchedUnlock (void){#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;#endif if (OSRunning == TRUE) { OS_ENTER_CRITICAL(); if (OSLockNesting > 0) { OSLockNesting--; if ((OSLockNesting == 0) && (OSIntNesting == 0)) { OS_EXIT_CRITICAL(); OS_Sched(); } else { OS_EXIT_CRITICAL(); } } else { OS_EXIT_CRITICAL(); } }}
Embedded System Lab. II 26
Idle Task / OS_TaskIdle() MicroC/OS-II 는 항상 Idle Task 를 생성한다 . Idle Task 는 다른 Task 가 실행하지 않을 때 실행한다 . Idle Task 는 항상 최하위 우선순위 (OS_LOWEST_PRIO) 가 배정된다 . 응용 프로그램이 Idle Task 를 삭제할 수 없다 .
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OS_TaskIdle (void *pdata){#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;#endif pdata = pdata; for (;;) { OS_ENTER_CRITICAL(); OSIdleCtr++; OS_EXIT_CRITICAL(); OSTaskIdleHook(); }}
Embedded System Lab. II 27
통계 Task / OS_TaskStat() MicroC/OS-II 는 실행 통계를 내주는 태스크를 포함하고 있다 . OS_CFG.H 에 있는 OS_TASK_STAT_EN 설정상수를 1 로 설정하면 Task 가
생성 통계 Task 는 CPU 사용률을 1 초 마다 % 로 계산한다 . 통계 Task 를 사용한다면 시스템 초기화시 처음으로 생성된 Task 에서 통계 Tas
k 를호출하도록 해야 한다 .
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void main (void){ OSInit(); /* Initialize uC/OS-II */ /* Install uC/OS-II's context switch vector */ /* Create your startup task (for sake of discussion, TaskStart()) */ OSStart(); /* Start multitasking */}
void TaskStart (void *pdata){ /* Install and initialize uC/OS-II’s ticker */ OSStatInit(); /* Initialize statistics task */ /* Create your application task(s) */ for (;;) { /* Code for TaskStart() goes here! */ }}
Embedded System Lab. II 28
통계 Task
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
Embedded System Lab. II 29
통계 Task 초기화 / OSStatInit() OSStatInit() 은 Idle Task 외에 아무 태스크도 실행되지 않는 상태에서
Idle 카운터 (OSIdleCtr) 값을 얼마나 증가 할 수 있는지 알아내는 일을 한다 .
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OSStatInit (void){#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;#endif OSTimeDly(2); OS_ENTER_CRITICAL(); OSIdleCtr = 0L; OS_EXIT_CRITICAL(); OSTimeDly(OS_TICKS_PER_SEC); OS_ENTER_CRITICAL(); OSIdleCtrMax = OSIdleCtr; OSStatRdy = TRUE; OS_EXIT_CRITICAL();}
Embedded System Lab. II 30
통계 Task
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OS_TaskStat (void *pdata){#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;#endif INT32U run; INT32U max; INT8S usage;
pdata = pdata; while (OSStatRdy == FALSE){
OSTimeDly(2 * OS_TICKS_PER_SEC)
; } max = OSIdleCtrMax / 100L;
for (;;) { OS_ENTER_CRITICAL(); OSIdleCtrRun = OSIdleCtr;
run = OSIdleCtr; OSIdleCtr = 0L; OS_EXIT_CRITICAL(); if (max > 0L) { usage = (INT8S)(100L - run / max);
if (usage >= 0) { OSCPUUsage = usage; } else { OSCPUUsage = 0; } } else { OSCPUUsage = 0; max = OSIdleCtrMax / 100L; } OSTaskStatHook();
OSTimeDly(OS_TICKS_PER_SEC);
}}
Embedded System Lab. II 31
MicroC/OS-II 의 Interrupt MicroC/OS-II 에서는 어셈블리로 Interrupt Service Routine (ISR) 을 작성해야
하나 C 컴파일러가 Inline 어셈블러를 지원한다면 C 소스코드에 ISR 을 작성해도 된다 .
Interrupt 관련 함수 OSIntEnter(), OSIntExit(), OSIntCtxSW()
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
YourISR: Save all CPU registers; Call OSIntEnter() or, increment OSIntNesting directly; if (OSIntNesting == 1) { OSTCBCur->OSTCBStkPtr = SP; } Clear interrupting device; Re-enable interrupts (optional) Execute user code to service ISR; Call OSIntExit(); Restore all CPU registers; Execute a return from interrupt instruction;
의사코드
Embedded System Lab. II 32
MicroC/OS-II 의 Interrupt
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
Embedded System Lab. II 33
Clock Tick / OSTimeTick() MicroC/OS-II 에서 타임 아웃 기능과 시간지연 기능 등을 위해 Clock Tick 을 사용 Multitasking 을 시작한 뒤 즉 반드시 OSStart() 를 호출한 뒤에 Clock Tick
Interrupt 를 활성화 해야 한다 . Clock Tick 관련 함수
OSTimeTick(), OSTickISR()
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void OSTickISR(void){ Save processor registers; Call OSIntEnter() or increment OSIntNesting; if (OSIntNesting == 1) { OSTCBCur->OSTCBStkPtr = SP; }
Post a 'dummy' message (e.g. (void *)1) to the tick mailbox;
Call OSIntExit(); Restore processor registers; Execute a return from interrupt instruction;}
Embedded System Lab. II 34
MicroC/OS-II 초기화 MicroC/OS-II 의 시스템 서비스를 사용하기 위해서는 가장 먼저 OSInit() 를 호출 다음 장의 그림은 OSInit() 을 호출해서 초기화한 MicroC/OS-II 의 모든 변수와
자료구조를 나타내고 있고 OS_CFG.H 에 있는 #define 상수를 다음과 같이설정했다고 가정한다 .
OS_TASK_STAT_EN 을 1 로 설정 OS_FLAG_EN 을 1 로 설정 OS_LOWEST_PRIO 를 63 으로 설정 OS_MAX_TASKS 를 62 로 설정
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
Embedded System Lab. II 35
MicroC/OS-II 초기화
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
Embedded System Lab. II 36
MicroC/OS-II 초기화
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
Embedded System Lab. II 37
MicroC/OS-II 시작
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
void main (void){ OSInit(); /* Initialize uC/OS-II */ . . Create at least 1 task using either OSTaskCreate() or OSTaskCreateExt(); . . OSStart(); /* Start multitasking! OSStart() will not return */}
void OSStart (void){ INT8U y; INT8U x; if (OSRunning == FALSE) { y = OSUnMapTbl[OSRdyGrp]; x = OSUnMapTbl[OSRdyTbl[y]]; OSPrioHighRdy = (INT8U)((y << 3) + x); OSPrioCur = OSPrioHighRdy; OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; OSTCBCur = OSTCBHighRdy; OSStartHighRdy(); }}
Embedded System Lab. II 38
MicroC/OS-II 시작
Kernel Structure (Cont’d)Kernel Structure (Cont’d)
Embedded System Lab. II
Task ManagementTask Management
Embedded System Lab. II 40
Task ManagementTask Management Task Management
Task 는 일반적으로 그 형태가 무한루프 함수이거나 작업이 끝나면 스스로를삭제하는 형태를 갖는 함수이다 . 이때 , 태스크의 코드를 메모리에서 삭제하는것은 아니다 .
void YourTask (void *pdata) { for (;;) { /* USER CODE */ Call one of uC/OS-II's services: OSFlagPend(); OSMboxPend(); OSMutexPend(); OSQPend(); OSSemPend(); OSTaskSuspend(OS_PRIO_SELF
); OSTimeDly(); OSTimeDlyHMSM(); /* USER CODE */ } }
void YourTask (void *pdata){ /* USER CODE */ OSTaskDel(OS_PRIO_SELF);}
Embedded System Lab. II 41
Task Management (Cont’d)Task Management (Cont’d) Task 생성 / OSTaskCreate() or OSTaskCreateExt()
Task 는 Multitasking 을 시작하기 전에 초기화 코드에서 생성하거나 ,Multitasking 을 시작한 뒤 실행 중인 다른 태스크가 생성할 수도 있다 .
Multitasking 을 시작하기 전 (OSStart() 호출 이전 ), 최소한 하나 이상의 Task 를 생성 해야만 한다 .
참고 ) Interrupt Service Routine 내에서는 Task 를 생성할 수 없다 . OSTaskCreate( void (*task) (void *pd), void *pdata, OS_STK *ptos, INT8U pri
o ) 첫 번째 전달인자 : 생성하고자 하는 Task 의 시작번지 두 번째 전달인자 : 생성하려는 Task 로 넘겨줄 전달인자 세 번째 전달인자 : 생성하고자 하는 Task 에 할당한 Stack 사용 시작 번지 네 번째 전달인자 : Task 의 우선 순위
OSTaskCreateExt() 함수는 전달인자가 9 개이며 , 이는 참고서적을 통해서확인해보기 바란다 .
Embedded System Lab. II 42
Task Management (Cont’d)Task Management (Cont’d) Task 생성 / OSTaskCreate() or OSTaskCreateExt()
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio){#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;#endif void *psp; INT8U err;
#if OS_ARG_CHK_EN > 0 if (prio > OS_LOWEST_PRIO) {
return (OS_PRIO_INVALID); }#endif
OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {
OSTCBPrioTbl[prio] = (OS_TCB *)1;
OS_EXIT_CRITICAL();
psp = (void *)OSTaskStkInit(task, pdata, ptos, 0);
err = OS_TCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0);
if (err == OS_NO_ERR) {
OS_ENTER_CRITICAL(); OSTaskCtr++;
OS_EXIT_CRITICAL(); if (OSRunning == TRUE) {
OS_Sched();
} } else { OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0;
OS_EXIT_CRITICAL(); } return (err); } OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST);}
Embedded System Lab. II 43
Task Management (Cont’d)Task Management (Cont’d) Task Stack
각 Task 는 고유한 Stack 공간이 있어야 하며 , 이는 OS_STK 타입으로 정의하며연속된 메모리공간을 확보해야 한다 .
Stack 을 위한 공간은 정적으로 ( 컴파일 할 때 ) 할당하거나 동적으로 (실행시 )할당할 수 있다 .
static OS_STK MyTaskStack[stack_size];OS_STK MyTaskStack[stack_size];
OS_STK *pstk;pstk = (OS_STK *)malloc(stack_size);if (pstk != (OS_STK *)0) { /* Make sure malloc() has enough space */ Create the task;}
Static Stack
Using malloc() to allocate stack space for a task
Embedded System Lab. II 44
Task Management (Cont’d)Task Management (Cont’d) Task Stack
Stack 을 위한 공간은 C 컴파일러의 malloc() 함수를 사용해서 동적으로 할당할수 있지만 메모리 단편화 (Fragmentation) 현상이 발생할 수 있음으로 유의
Free heap
(3Kb)
A (1Kb)
B (1Kb)
C (1Kb)
Free(1Kb)
B (1Kb)
Free(1Kb)
할당 전 할당 후 A, C 반환 후 (단편화 발생 )
Embedded System Lab. II 45
Task Management (Cont’d)Task Management (Cont’d) Task Stack 사용방향
스택을 하위 메모리서 상위 매모리 순서로 쓸 경우 (OS_STK_GROWTH = 0)OS_STK TaskStk[TASK_STK_SIZE];OSTaskCreate(task, pdata, &TaskStk[0], prio);
스택을 상위 메모리서 하위 메모리 순서로 쓸 경우 (OS_STK_GROWTH = 1)OS_STK TaskStk[TASK_STK_SIZE];OSTaskCreate(task, pdata, &TaskStk[TASK_STK_SIZE-1], prio);
상 , 하향 방식 스택을 모두 지원하는 코드OS_STK TaskStk[TASK_STK_SIZE];#if OS_STK_GROWTH == 0 OSTaskCreate(task, pdata, &TaskStk[0], prio);#else OSTaskCreate(task, pdata, &TaskStk[TASK_STK_SIZE-1], prio);#endif
Embedded System Lab. II 46
Task Management (Cont’d)Task Management (Cont’d) Stack 점검 / OSTaskStkChk()
Task 에서 실제로 얼마만큼의 Stack 공간을 사용하는지 검사 검사결과를 바탕으로 Stack 공간에 필요이상의 메모리를 할당하는 것을 방지 전달 인자
prio : 태스크 우선순위 pdata : OS_STK_DATA 타입의 구조체를 가리키는 포인터 .
스택에서 사용한 바이트 수 , 사용하지 않는 바이트 수 (uCOS_II.H 참조 )
Embedded System Lab. II 47
Task Management (Cont’d)Task Management (Cont’d) Stack 점검 / OSTaskStkChk()
Embedded System Lab. II 48
Task Management (Cont’d)Task Management (Cont’d) Task 삭제 요청 / OSTaskDelReq()
공유자원을 소유하고 있는 Task 로 하여금 자원을 반환하고 , 스스로를삭제하도록 알려 주는 방식의 함수
Task 삭제를 요청하는 함수와 삭제되는 함수 양쪽에서 모두 OSTaskDelReq()함수를 호출해야 한다 .
전달 인자 prio : 삭제 요구를 하기 위한 우선 순위void RequestorTask (void *pdata)
{ INT8U err; pdata = pdata; for (;;) { /* Application code */ if ('TaskToBeDeleted()' needs to be deleted) { while (OSTaskDelReq(TASK_TO_DEL_PRIO) != OS_TASK_NOT_EXIST) { OSTimeDly(1); } } /* Application code */ }}
Task 를 스스로 삭제하도록 요청하는 코드
Embedded System Lab. II 49
Task Management (Cont’d)Task Management (Cont’d) Task 삭제 요청 / OSTaskDelReq()
OSTaskDel() 실행 과정 조건 검사 : Idle Task 삭제 시도 여부 , 삭제 태스크의 존재 여부 OS_TCB 삭제
• Ready list 로부터 삭제• MailBox, Queue, Semaphore 에 대기중인 OS_TCB 삭제
지연 카운트를 0 으로 설정 : Task 가 인터럽트 재개시까지 tick ISR 이 준비되지 않게 하기 위해
OSTCBStat 플래그를 OS_STAT_RDY 로 설정 사용자 정의 확장 TCB 를 반납 OSTaskDelHook() Task 카운터 감소 OS_TCB 삭제
• 우선 순위 테이블에서 삭제• OSTCBList 에서 시작하는 OS_TCB 리스트에서 삭제• free OS_TCB list 로 OS_TCB 반환
스케줄러를 호출 : OSTaskDel() 실행 중 ISR 에 의해 생성된 높은 우선순위의 태스크가 있을 시
Embedded System Lab. II 50
Task Management (Cont’d)Task Management (Cont’d) Task 삭제 요청 / OSTaskDelReq()
자신을 삭제하도록 요청하는 Task
void TaskToBeDeleted (void *pdata){ INT8U err; pdata = pdata; for (;;) { /* Application code */ if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) { Release any owned resources; De-allocate any dynamic memory; OSTaskDel(OS_PRIO_SELF); } else { /* Application code */ } }}
Embedded System Lab. II 51
Task Management (Cont’d)Task Management (Cont’d) Task 우선순위 변경 / OSTaskChangePrio()
우선순위를 Run Time 시에 이 함수를 이용하여 동적으로 변경할 수 있다 . 주의 ) 새로 지정한 우선순위를 이미 사용하고 있지 않아야 한다 . 전달인자
Oldprio: 이전 우선순위 Newprio: 새로 지정하는 우선순위
우선순위 변화 과정 Task 가 실행 준비가 되면 ready list 에서 제거되고 Task 가 새 우선 순위를 할당
받으면 ready list 에 놓여진다 . Task 가 실행 준비가 되지 않으면 태스크는 새 우선 순위에서 실행될 준비가 되지 않는다 .
Task 가 이벤트 발생을 기다리면 태스크는 event waiting list 에서 제거되고 새 우선 순위의 waiting list 에 놓여진다 .
Task 가 OS_TCB 체인에서 제거되어 새 우선 순위를 받는 동안 OSTimeTick() 에 의하여 태스크가 실행 준비가 되는 것을 방지한다 .
인터럽트가 enabled 면 OS_TCB 의 OSTCBX, OSTCBBitX, OSTCBY, OSTCBBitY 가 재계산 된다 .
Embedded System Lab. II 52
Task Management (Cont’d)Task Management (Cont’d) Task 일시 중단 / OSTaskSuspend()
태스크를 일시 중단하는 함수 . 주의 ) 이 함수에 의해 중단된 태스크는 OSTaskResume 함수를 통해서만
중단상태에서 빠져 나올 수 있다 . 주의 ) 이벤트 ( 메시지 , 세마포어 , 큐 등 )를 대기중인 태스크에 대해 이
함수를 호출하면 이벤트가 발생했을 경우 처리할 수 없을 것이다 .
전달인자 prio: 중단하려는 태스크의 우선순위 .
OSTaskSuspend() 실행 과정 해당 Task 가 Idle 상태인지 검사 해당 Task 의 priority 가 유효한지 검사 해당 Task 가 존재하면 실행 Ready List 에서 삭제 OS_TCB 의 OS_STAT_SUSPEND 플래그를 설정한다 . 스케줄러를 호출한다 .
Embedded System Lab. II 53
Task Management (Cont’d)Task Management (Cont’d) Task 일시 중단 / OSTaskResume()
일시 중단한 태스크를 재실행시킨다 . 주의 ) 일시 중단한 태스크를 재실행할 수 있는 유일한 함수 (OSTaskSuspend) 전달인자
prio: 재실행하고자 하는 태스크의 우선순위 . OSTaskResume() 실행 과정
해당 Task 가 Idle 상태인지 검사 OSTCBStat 필드 (OS_TCB) 의 OS_STAT_SUSPEND 를 해제 OSTCBDly 를 0 으로 설정 : 시간 종료를 기다리고 있지 않은 Task 이므로 재개된
Task 가 현재 Task보다 더 높은 우선순위를 가지면 스케줄러를 호출한다 .
Embedded System Lab. II 54
Task Management (Cont’d)Task Management (Cont’d) Task 정보 알아내기 / OSTaskQuery()
자기 자신이나 다른 응용 Task 에 대한 정보를 알아낼 수 있다 . 해당 태스크의 TCB 사본을 얻어온다 . 주의 ) 복사본의 정보를 사용할 때 , 특히 OSTCBNext, OSTCBPrev 같은
태스크 컨트롤 블록 내의 링크 포인터가 가르키는 블록을 주의한다 . 전달인자
prio: 상태를 얻고자 하는 태스크의 우선순위 Pdata: 태스크에 대한 상태를 저장할 태스크 구조체
void MyTask (void *pdata){ OS_TCB MyTaskData;
pdata = pdata; for (;;) { /* User code */ err = OSTaskQuery(10, &MyTaskData); /* Examine error code .. */ /* User code */ }}
Embedded System Lab. II
Time ManagementTime Management
Embedded System Lab. II 56
Time Management Time Management Time Management
Time management configuration constants in OS_CFG.H.
uC/OS-II Time Management Service Enabled when set to 1 in OS_CFG.H
OSTimeDly()
OSTimeDlyHMSM() OS_TIME_DLY_HMSM_EN
OSTimeDlyResume() OS_TIME_DLY_RESUME_EN
OSTimeGet() OS_TIME_GET_SET_EN
OSTimeSet() OS_TIME_GET_SET_EN
Embedded System Lab. II 57
Time Management (Cont’d)Time Management (Cont’d) Task 지연 / OSTimeDly()
사용자가 지정한 Clock tick(1~65535) 동안 태스크를 지연할 수 있는 기능을 제공한다 .
실행 중이던 태스크 다음으로 우선순위가 높은 태스크를 실행 지정시간이 끝나거나 OSTimeDlyResume() 함수가 호출 시 준비상태가 된다 . 전달인자
Ticks: 지연 Clock tick
Embedded System Lab. II 58
Time Management (Cont’d)Time Management (Cont’d) Task 지연 / OSTimeDly()
Embedded System Lab. II 59
Time Management (Cont’d)Time Management (Cont’d) Task 지연 / OSTimeDlyHMSM()
시간을 틱 단위가 아닌 시 (H), 분 (M), 초 (S), 그리고 밀리 초 (m) 단위로 지정할 수 있다 .
uC/OS-II 에서는 최대 256 시간까지 지연이 가능 . OS_TIME_DLY_HMSM_EN == 1 일 경우 사용가능 . (OS_CFG.H) 전달인자
Hours: 지연할 시간 Minutes: 지연할 분 Seconds: 지연할 초 Milli: 지연할 밀리 초
Embedded System Lab. II 60
Time Management (Cont’d)Time Management (Cont’d) 지연된 Task 의 재개 / OSTimeDlyResume()
지연하고 있는 Task 를 재개하는 기능을 제공 지정된 지연 시간이 만료되는 것 말고 , 다른 Task 가 시간지연을 취소해서
지연중인 Task 를 다시 준비상태로 만든다 . 이 함수는 65,535틱 이상의 시간지연을 재개할 수 없다 . 지연시간이 끝나기를 기다려야 한다 .
OS_TIME_DLY_RESUME_EN == 1 일 때 사용가능 전달인자
prio: 재개할 Taks 의 우선순위
Embedded System Lab. II 61
Time Management (Cont’d)Time Management (Cont’d) 시스템 시간 / OSTimeGet(), OSTimeSet()
MicroC/OS-II 는 Clock Tick Interrupt 가 발생할 때마다 32bit 카운터 값을 증가
카운터 값은 처음 OSStart() 함수를 호출해서 멀티캐스팅을 시작할 때 0 으로초기화되어 증가하기 시작하고 , 4,294,967,295 Tick 이후에 다시 0 이 된다 .
OSTimeGet(): 카운터의 현재 값을 가져온다 . OSTimeSet(): 카운터의 값을 바꾼다 .
Embedded System Lab. II
Event Control BlockEvent Control Block
Embedded System Lab. II 63
Event Control BlockEvent Control Block Event Control Block
Task 와 ISR 은 Event Control Block(ECB) 이라는 Kernel Object 를 사용해서Task 로 신호를 보낸다 .
Embedded System Lab. II 64
Event Control Block (Cont’d)Event Control Block (Cont’d)
typedef struct { INT8U OSEventType; /* Event type */ INT8U OSEventGrp; /* Group for wait list */ INT16U OSEventCnt; /* Count (when event is a semaphore) */ void *OSEventPtr; /* Ptr to message or queue structure */ INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* Wait list for event to occur */} OS_EVENT;
Event Control Block Structure
Embedded System Lab. II 65
Event Control Block (Cont’d)Event Control Block (Cont’d) Wait List
Embedded System Lab. II 66
Event Control Block (Cont’d)Event Control Block (Cont’d) Wait List Operation
Making a task wait for an event.
pevent->OSEventGrp |= OSMapTbl[prio >> 3]; pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
Removing a task from a wait list.if ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) { pevent->OSEventGrp &= ~OSMapTbl[prio >> 3];}
Finding the highest priority task waiting for the event. y = OSUnMapTbl[pevent->OSEventGrp]; x = OSUnMapTbl[pevent->OSEventTbl[y]]; prio = (y << 3) + x;
Embedded System Lab. II 67
Event Control Block (Cont’d)Event Control Block (Cont’d) Wait List Example
Embedded System Lab. II 68
Event Control Block (Cont’d)Event Control Block (Cont’d) List of Free ECBs
Embedded System Lab. II 69
Event Control Block (Cont’d)Event Control Block (Cont’d) Event Control Block 초기화 / OS_EventWaitListInit()
Semaphore, Mutex, Mailbox, Message Queue 를 생성할 때 공통적으로호출하는 함수이다 .
이 함수는 해당 Event Control Block 에 대기하고 있는 Task 가 하나도 없도록해준다 .
void OS_EventWaitListInit (OS_EVENT *pevent){ INT8U *ptbl;
pevent->OSEventGrp = 0x00; ptbl = &pevent->OSEventTbl[0];
#if OS_EVENT_TBL_SIZE > 0 *ptbl++ = 0x00;#endif#if OS_EVENT_TBL_SIZE > 1 *ptbl++ = 0x00;#endif#if OS_EVENT_TBL_SIZE > 2 *ptbl++ = 0x00;#endif
#if OS_EVENT_TBL_SIZE > 3 *ptbl++ = 0x00;#endif#if OS_EVENT_TBL_SIZE > 4 *ptbl++ = 0x00;#endif#if OS_EVENT_TBL_SIZE > 5 *ptbl++ = 0x00;#endif#if OS_EVENT_TBL_SIZE > 6 *ptbl++ = 0x00;#endif#if OS_EVENT_TBL_SIZE > 7 *ptbl = 0x00;#endif}
Embedded System Lab. II 70
Event Control Block (Cont’d)Event Control Block (Cont’d) Task 를 준비상태로 만들기 / OS_EventTaskRdy()
이 함수는 Event Control Block 에 대기 중인 Task 중에서 가장 우선순위가높은 Task 를 준비상태로 만드는 것이다 .
Task 를 이벤트 대기 상태로 만들기 / OS_EventTaskWait() 이 함수는 현재 Task 를 MicroC/OS-II 의 준비 리스트에서 삭제하고 , 해당
Event Control Block 의 대기 리스트에 삽입한다 .
타임아웃으로 Task 를 준비상태로 만들기 / OS_EventTO() 지정된 시간 안에 이벤트를 받지 못한 경우에 호출하는 것이다 . OSTimeTick() 이 Task 를 준비상태로 만들 경우 , OSSemPend(),
OSMboxPend(), OSQPend() 함수에서 호출한다 .
Embedded System Lab. II
Semaphore ManagementSemaphore Management
Embedded System Lab. II 72
Semaphore Management Semaphore Management Semaphore Management
Semaphore configuration constants in OS_CFG.H
uC/OS-II Semaphore Service Enabled when set to 1 in OS_CFG.H
OSSemAccept() OS_SEM_ACCEPT_EN
OSSemCreate()
OSSemDel() OS_SEM_DEL_EN
OSSemPend()
OSSemPost()
OSSemQuery() OS_SEM_QUERY_EN
Embedded System Lab. II 73
Semaphore Management (Cont’d)Semaphore Management (Cont’d) Task, ISR, Semaphore 의 관계
Embedded System Lab. II 74
Semaphore Management (Cont’d)Semaphore Management (Cont’d) Semaphore 생성 / OSSemCreate()
이 함수를 사용하여 Semaphore 를 생성할 수 있는데 , 생성시 0 ~ 65535사이의 Semaphore 초기값을 지정해야 한다 .
이벤트가 발생한 것을 알려주는 목적으로 Semaphore 를 사용할 경우Semaphore 의 초기값을 0 을 지정한다 .
공유자원에 대한 액세스를 제어할 목적으로 사용할 경우 Semaphore 의초기값을 1 을 준다 .
전달인자 cnt: Semaphore 를 사용하기 위해 초기화할 값
Embedded System Lab. II 75
Semaphore Management (Cont’d)Semaphore Management (Cont’d) OSSemCreate() 이 리턴하기 직전의 ECB
Embedded System Lab. II 76
Semaphore Management (Cont’d)Semaphore Management (Cont’d) Semaphore 삭제 / OSSemDel()
Semaphore 를 삭제하려면 그 Semaphore 를 액세스할 수 있는 모든 Task 를먼저 삭제해야 할 것이다 .
Semaphore 대기 / OSSemPend() Semaphore 를 기다리는 함수이다 . 전달인자
Pevent: 해당 Semaphore 의 ECB 을 가리키는 포인터 . Timeout: 옵션 타임아웃 기간 (Clock Tick 단위 ). Err: 에러코드를 저장할 메모리를 가리키는 포인터 .
Embedded System Lab. II 77
Semaphore Management (Cont’d)Semaphore Management (Cont’d) Semaphore 반환 / OSSemPost()
Semaphore 를 반환하는 함수이다 . 전달인자
Pevent: 해당 Semaphore 의 ECB 을 가리키는 포인터 .
대기없이 Semaphore 얻기 / OSSemAccept() Semaphore 가 가용하지 않을 경우 Task 를 대기하지 않도록 하면서
Semaphore 를 얻을 수 있도록 하는 함수 전달인자
Pevent: 해당 Semaphore 의 ECB 을 가리키는 포인터
Embedded System Lab. II 78
Semaphore Management (Cont’d)Semaphore Management (Cont’d) Semaphore 상태 얻기 / OSSemQuery()
Semaphore 로 사용하는 ECB 의 현재 상태를 얻을 수 있도록 한다 . 전달인자
Pevent: 해당 Semaphore 의 ECB 을 가리키는 포인터 Pdata: Semaphore 에 대한 정보를 저장할 구조체를 가리키는 포인터
Embedded System Lab. II
Mutual Exclusive SemaphoreMutual Exclusive Semaphore
Embedded System Lab. II 80
Mutual Exclusive SemaphoreMutual Exclusive Semaphore Mutual Exclusive Semaphore
Task 가 자원에 대한 독점적인 액세스를 얻고자 할 때 사용한다 . Mutex 는 MicroC/OS-II 가 일반적으로 제공하는 Semaphore 메커니즘에
부가적인 기능을 추가한 Binary Semaphore 이다 . 우선순위 전도 문제를 줄이기 위해 사용
Mutex configuration constants in OS_CFG.H
uC/OS-II Mutex Service Enabled when set to 1 in OS_CFG.H
OSMutexAccept() OS_MUTEX_ACCEPT_EN
OSMutexCreate()
OSMutexDel() OS_MUTEX_DEL_EN
OSMutexPend()
OSMutexPost()
OSMutexQuery() OS_MUTEX_QUERY_EN
Embedded System Lab. II
Event Flags ManagementEvent Flags Management
Embedded System Lab. II 82
Event Flags ManagementEvent Flags Management Event Flags Management
Event Flags 는 2 가지 요소로 구성된다 . 그룹의 현재 이벤트 상태를 나타내는 비트열 이벤트 상태를 나타내는 비트가 켜지거나 꺼지기를 기다리는 Task 들의 리스트
Event Flags 는 Task 를 여러 개의 이벤트 발생에 대해 동기화 할 필요가 있을 때 사용
Event Flags configuration constants in OS_CFG.H
uC/OS-II Event Flags Service Enabled when set to 1 in OS_CFG.H
OSFlagAccept() OS_FLAG_ACCEPT_EN
OSFlagCreate()
OSFlagDel() OS_FLAG_DEL_EN
OSFlagPend()
OSFlagPost()
OSFlagQuery() OS_FLAG_QUERY_EN
Embedded System Lab. II 83
Event Flags Management (Cont’d)Event Flags Management (Cont’d) Event Flags Service
태스크
ISR
태스크
ISR
OSFlagCreat( )OSFlagDel( )OSFlagPost( )
OSFlagAccept( )OSFlagPend( )OSFlagQuery( )
OSFlagPost( ) OSFlagAccept( )OSFlagQuery( )
Embedded System Lab. II 84
Event Flags Management (Cont’d)Event Flags Management (Cont’d) Event Flags 의 내부
Event Flags Group Structure typedef struct { /* Event Flag Group */ INT8U OSFlagType; /* Should be set to OS_EVENT_TYPE_FLAG */ void *OSFlagWaitList; /* Pointer to first NODE of task waiting on event flag*/ OS_FLAGS OSFlagFlags; /* 8, 16 or 32 bit flags */} OS_FLAG_GRP;
Event Flags Group Node Structure
typedef struct { /* Event Flag Wait List Node */ void *OSFlagNodeNext; /* Pointer to next NODE in wait list */ void *OSFlagNodePrev; /* Pointer to previous NODE in wait list */ void *OSFlagNodeTCB; /* Pointer to TCB of waiting task */ void *OSFlagNodeFlagGrp; /* Pointer to Event Flag Group */ OS_FLAGS OSFlagNodeFlags; /* Event flag to wait on */ INT8U OSFlagNodeWaitType; /* Type of wait: */} OS_FLAG_NODE;
Embedded System Lab. II 85
Event Flags Management (Cont’d)Event Flags Management (Cont’d) Event Flags Group, Event Flags Node, TCB 사이의 관계
●
OS_EVENT_TYPE_FLAG
●
AND 또는 OR
●●
●
●NULL
●
AND 또는 OR
●●
●
●
NULL
OS_FLAG_NODEOS_FLAG_GRP
Embedded System Lab. II 86
Event Flags Management (Cont’d)Event Flags Management (Cont’d) Event Flags Group 생성 / OSFlagsCreate()
Event Flags Group 을 생성한다 .
Event Flags Group 삭제 / OSFlagsDel() Event Flags Group 을 삭제한다 .
Event 대기 / OSFlagPend() Event Flags Group 에서 특정 이벤트를 기다린다 .
Event Flags Group 에 있는 이벤트 켜고 끄기 / OSFlagPost() Event Flags Group 에 있는 비트를 켜고 끈다 .
Event Flags Group 정보얻기 / OSFlagQuery() Event Flags Group 의 현재 값을 얻을 수 있다 .
Embedded System Lab. II
Message MailboxMessage Mailbox
Embedded System Lab. II 88
Message Mailbox ManagementMessage Mailbox Management Message Mailbox
Message Mailbox 는 MicroC/OS-II 에서 제공하는 Kernel Object 로써 , Task또는 ISR 에서 다른 Task 로 포인터 변수를 전송하는 역할을 한다 .
Mailbox configuration constants in OS_CFG.H
MicroC/OS-II Mail Box Service Enabled when set to 1 in OS_CFG.H
OSMboxAccept() OS_MBOX_ACCEPT_EN
OSMboxCreate()
OSMboxDel() OS_MBOX_DEL_EN
OSMboxPend()
OSMboxPost() OS_MBOX_POST_EN
OSMboxPostOpt() OS_MBOX_POST_OPT_EN
OSMboxQuery() OS_MBOX_QUERY_EN
Embedded System Lab. II 89
Message Mailbox Management (Cont’d)Message Mailbox Management (Cont’d) Task, ISR, Mailbox 사이의 관계
Embedded System Lab. II 90
Message Mailbox Management (Cont’d)Message Mailbox Management (Cont’d) Mailbox 생성 / OSMboxCreate()
이벤트의 발생을 알리는 목적으로 Mailbox 를 사용할 경우 , Mailbox 를 NULL 포인터로 초기화해야 한다 .
공유자원 액세스 제어의 목적으로 사용하고자 할 때는 NULL 이 아닌 값으로Mailbox 를 초기화한다 .
전달인자 Msg: Mailbox 에 송부하고자 하는 메시지에 대한 포인터
Embedded System Lab. II 91
Message Mailbox Management (Cont’d)Message Mailbox Management (Cont’d) OSMboxCreate() 이 리턴하기 직전의 ECB
Embedded System Lab. II 92
Message Mailbox Management (Cont’d)Message Mailbox Management (Cont’d) Mailbox 삭제 / OSMboxDel()
Mailbox 를 삭제하려면 그 Mailbox 를 액세스할 수 있는 모든 Task 를 먼저삭제해야 할 것이다 .
Mailbox 에서 메시지 대기 / OSMboxPend() Mailbox 에 메시지가 도착하기를 기다린다 . 전달인자
Pevent: 해당 Mailbox 의 ECB 에 대한 포인터 Timeout: 옵션 타임아웃 값 (Clock Tick 단위 ) err: 에러코드를 저장할 메모리를 가리키는 포인터
Embedded System Lab. II 93
Message Mailbox Management (Cont’d)Message Mailbox Management (Cont’d) Mailbox 로 메시지 보내기 / OSMboxPost()
Mailbox 로 메시지를 전송한다 . 전달인자
Pevent: 해당 Mailbox 의 ECB 에 대한 포인터 Msg: 보내려는 메시지에 대한 포인터
Mailbox 로 메시지 보내기 / OSMboxPostOpt() Mailbox 에 대기 중인 모든 Task 에게 메시지를 Broadcast 할 수 있는 기능 추가
전달인자 Pevent: 해당 Mailbox 의 ECB 에 대한 포인터 Timeout: 옵션 타임아웃 값 (Clock Tick 단위 )
Embedded System Lab. II 94
Message Mailbox Management (Cont’d)Message Mailbox Management (Cont’d) 대기없이 메시지 얻기 / OSMboxAccept()
호출 Task 를 대기상태로 만들지 않고 메시지를 받을 수 있다 . 전달인자
Pevent: 해당 Mailbox 의 ECB 에 대한 포인터
Mailbox 의 상태얻기 / OSMboxQuery() Mailbox 로 사용하는 ECB 의 현재 상태를 얻을 수 있다 . 전달인자
Pevent: 해당 Mailbox 의 ECB 에 대한 포인터 Pdata: Message Mailbox 에 대한 정보를 저장할 구조체를 가리키는 포인터
Embedded System Lab. II
Message Queue MailboxMessage Queue Mailbox
Embedded System Lab. II 96
Message Queue ManagementMessage Queue Management Message Queue
Message Queue 는 포인터 크기의 변수를 Task 나 ISR 에서 다른 Task 로 전달할 수 있도록 하는 Kernel Object 이다 . 이때 , 사용하는 포인터는 일반적으로 응용 프로그램에서 정의하는 ‘메시지’ 자료형을 가르킨다 .
Message queue configuration constants in OS_CFG.H.
uC/OS-II Event Flag Service Enabled when set to 1 in OS_CFG.H
OSQAccept() OS_Q_ACCEPT_EN
OSQCreate()
OSQDel() OS_Q_DEL_EN
OSQFlush() OS_Q_FLUSH_EN
OSQPend()
OSQPost() OS_Q_POST_EN
OSQPostFront() OS_Q_POST_FRONT_EN
OSQPostOpt() OS_Q_POST_OPT_EN
OSQQuery() OS_Q_QUERY_EN
Embedded System Lab. II 97
Message Queue Management (Cont’d)Message Queue Management (Cont’d) Task, ISR, Message Queue 의 관계
Embedded System Lab. II 98
Message Queue Management (Cont’d)Message Queue Management (Cont’d) Message Queue Structure
Embedded System Lab. II 99
Message Queue Management (Cont’d)Message Queue Management (Cont’d) List of free queue control blocks
Embedded System Lab. II 100
Message Queue Management (Cont’d)Message Queue Management (Cont’d) A message queue as a circular buffer of pointers
Embedded System Lab. II 101
Message Queue Management (Cont’d)Message Queue Management (Cont’d) Message Queue 생성 / OSQCreate()
Message Queue 를 생성할 경우 , 먼저 Message Queue 가 메시지를 보관하는데 사용할 메모리를 할당한 뒤 OSQCreate() 함수에 넘겨줘야 한다 .
전달인자 Start: 큐에서 메시지 저장 영역의 기준 어드레스를 가리키는 포인터
저장 영역은 다음과 같이 void 형 포인터의 배열로 선언해야 한다 . void *MessageStorage[size] Size: 저장 영역의 요소 수
Message Queue 삭제 / OSQDel () Message Queue 를 삭제할 경우 , 그 Message Queue 를 액세스할 수 있는
모든 Task 를 먼저 삭제해야 할 것이다 .
Embedded System Lab. II 102
Message Queue Management (Cont’d)Message Queue Management (Cont’d) Message Queue 대기 / OSQPend()
Message Queue 에 메시지가 도착하기를 기다린다 . 전달인자
Pevent: 해당 큐의 ECB 을 가리키는 포인터 Timeout: 옵션 타임아웃 기간 (Clock Tick 단위 ) Err: 에러코드를 저장할 메모리를 가리키는 포인터
FIFO 방식으로 큐에 메시지 보내기 / OSQPost() FIFO 방식으로 Message Queue 에 메시지를 넣는다 . 전달인자
Pevent: 해당 큐의 ECB 을 가리키는 포인터 Msg: 전송할 메시지를 가리키는 포인터 . NULL 을 지정하면 안된다 .
Embedded System Lab. II 103
Message Queue Management (Cont’d)Message Queue Management (Cont’d) LIFO 방식으로 큐에 메시지 보내기 / OSQPostFront()
LIFO 방식으로 Message Queue 에 메시지를 넣는다 . 전달인자
Pevent: 해당 큐의 ECB 을 가리키는 포인터 Msg: 전송할 메시지를 가리키는 포인터 . NULL 을 지정하면 안된다 .
FIFO 또는 LIFO 방식으로 큐에 메시지 보내기 / OSQPostOpt() OSQPostOpt() 는 OSQPost() 와 OSQPostFront() 를 하나로 대치할 수
있는 함수이다 . 이 함수는 큐에 대기 중인 모든 Task 로 메시지를 Broadcast 할 수 있다 .
Embedded System Lab. II 104
Message Queue Management (Cont’d)Message Queue Management (Cont’d) 대기 없이 큐에서 메시지 얻기 / OSQAccept()
큐에서 메시지를 받을 수 있다 . OSQPend() 와 큐가 비어있는 경우라도 Task 를 대기 상태로 만들지 않는
것이 다르다 . 전달인자
Pevent: 해당 큐의 ECB 을 가리키는 포인터
Message Queue 비우기 / OSQFlush() Message Queue 안의 메시지를 모두 버리고 , 막 생성된 큐 상태로 만든다 .
Message Queue 의 상태 얻기 / OSQQuery() Message Queue 의 현재 상태를 가져올 수 있도록 한다 . 전달인자
Pevent: 해당 큐의 ECB 을 가리키는 포인터 Pdata: Message Queue 에 대한 정보를 저장할 구조체를 가리키는 포인터
Embedded System Lab. II 105
Message Queue Management (Cont’d)Message Queue Management (Cont’d) 아날로그 입력을 읽기 위해 Message Queue 사용
Embedded System Lab. II
Memory ManagementMemory Management
Embedded System Lab. II 107
Memory ManagementMemory Management Memory Management
응용 프로그램에서 동적으로 메모리를 할당하고 해제하는데 malloc() 과free() 함수를 사용할 수 있다 . 그러나 이는 메모리 단편화 현상을 초래한다 .
MicroC/OS-II 에서는 malloc() 과 free() 함수 대신 연속된 메모리 공간으로구성된 파티션에서 고정 크기의 메모리 블록을 할당할 수 있는 다른 방법을제공한다 .
Memory management configuration constants in OS_CFG.H
uC/OS-II Memory Service Enabled when set to 1 in OS_CFG.H
OSMemCreate()
OSMemGet()
OSMemPut()
OSMemQuery() OS_MEM_QUERY_EN
Embedded System Lab. II 108
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) Memory Control Block
Memory Control Block Data Structure
Typedef struct { void *OSMemAddr; // 메모리 파티션의 처음을 가르키는 포인터 void *OSMemFreeList; // 자유 메모리 블록 리스트를 가르키는 포인터 INT32U OSMemBlkSize; // 각 메모리 블록의 바이트 단위 크기 INT32U OSMemNBlks; // 이 파티션에서의 총 메모리 바이트 수 INT32U OSMemNFree; // 이 파티션에서 남아있는 자유 메모리 블록 수} OS_MEM;
Embedded System Lab. II 109
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) Memory Partition
Memory Partition 여러 개의 Memory Partition
Embedded System Lab. II 110
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d)
Free Memory Control Block List
Embedded System Lab. II 111
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) 파티션 생성 / OSMemCreate()
메모리 파티션을 생성하는 함수 밑의 소스는 32 바이트 블록이 100 개 있는 메모리 파티션을 생성하는 예
OS_MEM *CommTxBuf;INT8U CommTxPart[100][32];void main (void){ INT8U err; OSInit(); . . CommTxBuf = OSMemCreate(CommTxPart, 100, 32, &err); . . OSStart();}
Embedded System Lab. II 112
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) OSMemCreate() 으로 생성한 메모리 파티션
Embedded System Lab. II 113
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) 메모리 블록 할당 / OSMemGet()
생성된 메모리 파티션으로부터 메모리 블록을 할당받는다 . 전달인자
Pmem: 메모리 파티션 컨트롤 블록을 가리키는 포인터 Err: 에러 코드를 저장할 메모리를 가리키는 포인터
메모리 블록의 반환 / OSMemPut() 응용 프로그램에서 메모리 블록의 사용을 마치면 처음 할당받은 파티션으로
해당 블록을 반환해야 한다 . 전달인자
Pmem: 메모리 파티션 컨트롤 블록을 가리키는 포인터 Pblk: 해제하려는 메모리 블록을 가리키는 포인터
Embedded System Lab. II 114
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) 메모리 파티션의 상태 얻기 / OSMemQuery()
메모리 파티션에서 사용한 메모리 블록 수와 자유 메모리 블록 수를 알아낸다 . 전달인자
Pmem: 메모리 파티션 컨트롤 블록을 가리키는 포인터 Pdata: 메모리 파티션에 대한 정보를 저장할 구조체를 가리키는 포인터
Embedded System Lab. II 115
Memory Queue Management (Cont’d)Memory Queue Management (Cont’d) 메모리 파티션의 사용
Embedded System Lab. II
MicroC/OS-II PortingMicroC/OS-II Porting
Embedded System Lab. II 117
MicroC/OS-II PortingMicroC/OS-II Porting Porting
Real Time kernel 을 마이크로 프로세서나 마이크로 컨트롤러에서 사용할수 있도록 하는 작업을 말한다 .즉 , MicroC/OS-II 를 다른 프로세서에서 사용하기 위한 일반적인 작업임 .
Porting 관점에서의 MicroC/OS-II 대부분의 MicroC/OS-II 의 코드는 이식성을 고려하여 C 언어로 작성되어
있음 . 일부는 프로세서 의존적인 C 코드와 어셈블리어로 작성되어 있음 .
MicroC/OS-II 를 사용할 수 있는 프로세서의 사항 재진입을 지원하는 코드를 생성할 수 있는 C 컴파일러 C 언어에서 인터럽트 비활성화 , 활성화 지원 인터럽트 지원 및 일정한 주기로 발생하는 타이밍 인터럽트를 제공 프로세서 수준에서 지원하는 적정크기의 하드웨어 스택 기능 스택 포인터 또는 레지스터의 내용을 스택이나 메모리로 저장하고 가져올
수 있는 프로세서 명령어
Embedded System Lab. II 118
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d)uC/OS-II File Structure
Embedded System Lab. II 119
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d)프로세서 의존적인 파일파일명 설명OS_CPU.H 프로세서 의존적인 혹은 구현방법에 의존적인 #define 문과 매크로 , 형 정의OS_CPU_A.ASM 프로세서에 의존적이면서 C 언어로는 작성할 수 없는 저수준 (Low-Level) 함수나
매크로를 작성하는 어셈블리 파일이 파일을 수정하기 위해서는 해당 프로세서와 어셈블리에 대한 지식이 있어야 한다 .
OS_CPU_C.C 프로세서에 의존적이면서 C 언어로 작성할 수 있는 함수나 매크로를 작성하는C 소스 파일
응용 프로그램 의존적인 파일파일명 설명OS_CFG.H MicroC/OS-II 의 모든 기능을 응용 프로그램에 따라 설정하는 파일
INCLUDES.H 모든 C 소스에서 사용하는 마스터 헤더 파일로써 , 필요한 모든 헤더 파일은 모두이 파일에 포함되어 있으므로 어떤 헤더 파일을 포함할지 신경 쓸 필요가 없다 .
Embedded System Lab. II 120
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OS_CPU.H
프로세서 , 컴파일러의 종류에 따라 C 언어에서 사용하는 변수타입의 크기가다르므로 이식성을 보장해 주는 변수 타입을 정의한다 .
Ex) 16 비트 프로세서의 경우 , Integer 타입의 변수는 16 비트 크기 이지만 32 비트프로세서의 경우 , Integer 타입의 변수는 32 비트 크기이다 .
typedef unsigned char BOOLEAN;typedef unsigned char INT8U; /* 무부호 8 비트 데이터 */typedef signed char INT8S; /* 부호있는 8 비트 데이터 */typedef unsigned int INT16U; /* 무부호 16 비트 데이터 */typedef signed int INT16S; /* 부호있는 16 비트 데이터 */typedef unsigned long INT32U; /* 무부호 32 비트 데이터 */typedef signed long INT32S; /* 부호있는 32 비트 데이터 */typedef float FP32; /* 단정도 부동소수 데이터 */typedef double FP64; /* 배정도 부동소수 데이터 */
typedef unsigned int OS_STK; /* 각 스택 요소는 16 비트 크기임 */
Embedded System Lab. II 121
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OS_CPU.H
OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL() MicroC/OS-II 는 Critical Section 에 들어가기 전에 인터럽트를 비활성화하고
코드 수행을 마친 뒤 다시 활성화하는 방법을 사용 OS_CPU.H 에는 OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL() 을 구현하는
세 가지 방법이 포함되어 있지만 이들 중 한 가지만 선택해서 사용하면 된다 .
{ . OS_ENTER_CRITICAL(); /* MicroC/OS-II Critical Section Code */ OS_EXIT_CRITICAL(); .}
Embedded System Lab. II 122
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL()
OS_CRITICAL_METHOD == 1 OS_ENTER_CRITICAL(): 프로세서의 인터럽트 비활성화 명령 수행 OS_EXIT_CRITICA(): 프로세서의 인터럽트 활성화 명령 수행 문제점 : 인터럽트가 비활성화된 상태에서 MicroC/OS-II 함수를 호출할 경우
함수가종료해서 리턴할 때 인터럽트는 활성화 상태가 된다 .
OS_CRITICAL_METHOD == 2 OS_ENTER_CRITICAL(): 인터럽트 비활성화 상태를 스택에 저장 OS_EXIT_CRITICAL(): 스택에서 꺼내 이전 상태로 복귀하도록 처리
#define OS_ENTER_CRITICAL() disable_int() /* 인터럽트 비활성화 */#define OS_EXIT_CRITICAL() enable_int() /* 인터럽트 활성화 */
#define OS_ENTER_CRITICAL() \ asm(“ PUSH PSW”); \ asm(“ DI”);#define OS_EXIT_CRITICAL() \ asm(“POP PSW”);
Embedded System Lab. II 123
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OS_ENTER_CRITICAL() 과 OS_EXIT_CRITICAL()
OS_CRITICAL_METHOD == 3 몇몇 컴파일러는 현재 PSW 의 값을 읽어서 C 함수에서 선언한 지역변수에 저장할수 있는 확장 기능을 제공한다 .
#define OS_ENTER_CRITICAL() \ cpu_sr = get_processor_psw(); disalble_interrupts();#define OS_EXIT_CRITICAL() \ set_processor_psw(cpu_sr);
Embedded System Lab. II 124
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OS_CPU_C.C
프로세서에 의존적이지만 C 언어로 작성하는 것이 가능한 함수나 매크로를작성하는 파일로써 , 아래의 10 개의 간단한 C 함수를 작성해야 하지만 필수함수는 OSTaskStkInit() 뿐이다 .
OSTaskStkInit() OSTaskCreateHook() OSTaskDelHook() OSTaskSwHook() OSTaskIdleHook() OSTaskStatHook() OSTimeTickHook() OSInitHookBegin() OSInitHookEnd() OSTCBInitHook()
Embedded System Lab. II 125
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OSTaskStkInit()
OSTaskStkInit() 함수는 OSTaskCreate() 함수나 OSTaskCreateExt()함수에서생성하고자 하는 태스크의 스택 프레임을 인터럽트가 발생했을 때 처럼초기화하기 위해 호출한다 .
OS_STK *OSTaskStkInit ( void (*task) (void *pd), void *pdata, OS_STK *ptos, INT16U opt ){ (1) 전달인자 (pdata) 와 함께 함수를 호출한 것처럼 만들어준다 (2) ISR 벡터 모사 ; (3) 모든 레지스터의 내용을 스택에 저장한 것처럼 만들어 준다 . (4) 마지막으로 스택 포인터가 가리키고 있는 위치를 리턴한다 .}
OSTaskStkInit() 함수 의사코드
Embedded System Lab. II 126
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OS_CPU_A.ASM
프로세서에 의존적이면서 저수준의 함수나 매크로가 정의되어 있는 어셈블리파일로써 , 아래의 4 개의 간단한 어셈블리 함수를 포함한다 .
컴파일러가 인라인 어셈블리 기능을 지원한다면 , 이 4 개의 함수들을 별도의어셈블리 파일이 아닌 C 소스 파일로 작성할 수도 있다 .
OSStartHighRdy() OSCtxSw() OSIntCtxSw() OSTickISR()
Embedded System Lab. II 127
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OSStartHighRdy()
OSStartHighRdy() 함수는 OSStart() 에서 현재 우선 순위가 가장 높은 Task 를 수행하기 위해 호출하는 함수이다 .
아래의 의사코드는 실제 해당 프로세서의 어셈블리어로 작성되어야 한다 .
void OSStartHighRdy(){ (1) 사용자 정의 함수 OSTaskSwHook() 을 호출한다 ; (2) OSRunning = TRUE; (3) 재실행할 Task 의 스택 포인터를 얻어온다 : Stack pointer = OSTCBHighRdy->OSTCBStkPtr; (4) 새 Task 의 스택으로부터 모든 레지스터를 복구한다 ; (5) 인터럽트 복귀 명령을 실행한다 ;}
Embedded System Lab. II 128
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OSCtxSw()
Task 수준 문맥 전환 작업은 소프트웨어 인터럽트 명령이나 프로세서에따라서는 TRAP 명령어로 수행한다 . 이때 ISR, TRAP 핸들러 혹은 예외 핸들러가 OSCtxSw() 를 실행하도록 설정해야 한다 .
OSCtxSw() 함수는 수행 중인 Task 에서 더 높은 우선 순위의 Task 를 실행가능한 상태로 만드는 MicroC/OS-II 서비스 함수를 호출한 경우에 호출된다 .Void OSCtxSw(void){ (1) 프로세서 레지스터 저장 ; (2) 현재 Task 의 스택 포인터를 현재 Task 의 TCB 에 저장 OSTCBCur->OSTCBStkPtr = 스택 포인터 ; (3) OSTaskSwHook(); (4) OSTCBCur = OSTCBHighRdy; (5) OSPrioCur = OSPrioHighRdy; (6) 재실행할 Task 의 스택 포인터 복구 : 스택 포인터 = OSTCBHighRdy->OSTCBStkPtr; (7) 재실행할 Task 의 스택으로부터 프로세서 레지스터 복구 ; (8) 인터럽트 복귀 명령 스택 ;}
Embedded System Lab. II 129
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OSTickISR()
MicroC/OS-II 은 시간 지연 기능과 타임아웃 기능 구현을 위해 일정한 주기의타이머를 사용한다 .
Void OSTickISR(void){ (1) 프로세서 레지스터 저장 ; (2) OSIntEnter() 호출 또는 OSIntNesting 값을 1 증가 ; (3) if( OSIntNesting == 1) { OSTCBCur->OSTCBStkPtr = 스택 포인터 ; } (4) 타이머 인터럽트 발생장치 클리어 ; (5) 인터럽트 재활성화 ( 선택사항 ); (6) OSTimeTick(); (7) OSIntExit(); (8) 프로세서 레지스터 복구 ; (9) 인터럽트 복귀 명령 실행 ;}
Embedded System Lab. II 130
MicroC/OS-II Porting (Cont’d)MicroC/OS-II Porting (Cont’d) OSIntCtxSw()
OSIntCtxSw() 함수는 OSIntExit() 함수에서 ISR 종료시 문맥전환을 위해 호출
Void OSIntCtxSw(void){ (1) 사용자 정의 함수 OSTaskSwHook() 을 호출한다 ; (2) OSTCBCur = OSTCBHighRdy(); (3) OSPrioCur = OSPrioHighRdy(); (4) 재실행할 Task 의 스택 포인터 복구 : 스택 포인터 = OSTCBHighRdy->OSTCBStkPtr; (5) 재실행할 Task 의 스택으로부터 프로세서 레지스터 복구 ; (6) 인터럽트 복귀 명령 실행}