Micro C/OS-II 2. Task Management 아이티즌 기술연구소 ITISN Technical Lab
태스크의 이해(TASK) 1/3 태스크 태스크의 구성 요소 태스크의 5가지 상태 자기자신이 CPU를 독점하고 있다고 생각하는 단순한 프로그램 스레드(thread), 프로세스(process)등 태스크의 구성 요소 우선순위 + CPU 레지스터 세트 + 스택영역 태스크의 5가지 상태 수면, 준비, 실행, 대기, 인터럽트 서비스 루틴(ISR) 상태 각각의 상태에서 무한루프 수행 대기상태 waiting 수면상태 dormant 준비상태 ready 실행상태 running ISR OSTaskCreate OSTaskstart ITISN Technical Lab
태스크의 이해(TASK) 2/3 태스크 1 태스크 2 태스크 n 문맥 전환 (context switching = task switching) 현재 작업 중인 CPU 내용을 Task control block에 저장 다음 작업 내용을 CPU 레지스터로 가져와 실행 Stack 태스크 1 Task control block Status SP Priority . 태스크 2 태스크 n 메모리 CPU ( CPU 레지스터 ) 문맥(context) 교환(switching) stackpointer 현재 실행시킬 data ITISN Technical Lab
태스크의 이해(TASK) 3/3 재진입 가능 함수 비재진입 함수 재진입 가능 함수 (Reentrant Functions) 데이터의 손상 없이 여러 개의 태스크가 사용 가능 void swap(int *x, int *y) { int temp; // 지역변수!! temp = *x; *x = *y; *y = temp; } int temp; // 전역변수의 문제점 void swap(int *x, int *y) { temp = *x; *x = *y; *y = temp; } 재진입 가능 함수 비재진입 함수 ITISN Technical Lab
태스크 관리 1/4 최대 태스크 수: 64 우선순위: 태스크 식별 수단 우선순위 범위: 0 ~ OS_LOWEST_PRIO(63) OS_LOWEST_PRIO : OS_CFG.H에 정의된 상수 예약된 우선순위(8개)는 제외 0, 1, 2, 3, OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2, OS_LOWEST_PRIO-1, OS_LOWEST_PRIO 사용 가능한 우선순위 개수는 56 ITISN Technical Lab
Micro C/OS-II 태스크 상태 전이 다이어그램 태스크 관리 2/4 Micro C/OS-II 태스크 상태 전이 다이어그램 태스크 대기상태 태스크 수면상태 태스크 실행상태 ISR 실행상태 태스크 준비상태 OSTaskdel() 인터럽트 OSTaskSuspend() OSTaskResume() OSTaskCreate() OSStart() 태스크 선점 OSIntExit 항상 하나 프로그램 메모리 존재 사용 메모리 할당 인터럽트 발생 시 실행 중이던 태스크 중단 ITISN Technical Lab
태스크 관리 3/4 테스크 초기화 및 OS_TCBInit() 호출 태스크 컨트롤 블록(OS_TCB) 태스크를 생성할 때 태스크 컨트롤 블록 할당 태스크가 선점될 때 해당 태스크의 상태를 유지하는 구조체 태스크가 다시 CPU 사용권을 받을 때 이곳에 저장했던 데이터 를 이용해서 마지막으로 실행했던 부분부터 수행 TCB 구조체의 특징 RAM 영역에 존재 각 멤버의 논리적 그룹화 유지 TCB 관련 함수 OS_TCBInit() : TCB를 초기화하는 함수 OSTaskCreate() 또는 OSTaskCreateExt()가 호출 테스크 초기화 및 OS_TCBInit() 호출 ITISN Technical Lab
태스크 관리 4/5 OS_TCB 구조체의 내부 (uCOS_II.H 370line) typedef struct os_tcb { ... //마지막으로 사용한 스택의 위치를 가리키는 포인터 OS_STK * OSTCBStkPtr; //이중 연결 리스트로 관리하기 위한 포인터 struct os_tcb * OSTCBNext; struct os_tcb * OSTCBPrev; //태스크를 일정 시간 지연 또는 타임아웃과 관련 INT16U OSTCBDly; INT8U OSTCBStat; // 태스크의 상태 INT8U OSTCBPrio; // 태스크의 우선순위 INT8U OSTCBX; // = prio >> 3 INT8U OSTCBY; // = OSMapTbl[prio >> 3] INT8U OSTCBBitX; // = prio & 0x07 INT8U OSTCBBitY; // = OSMapTbl[prio & 0x07] ... } OS_TCB; ITISN Technical Lab
태스크 관리 4/4 : 태스크 자유리스트 uCOS_II.H 파일에 전역변수로 선언됨 자유리스트(FreeList)를 이용한 미사용 태스크의 빠른 관리 태스크 생성 시 노드 1개 빼서 제공 태스크 종료 시 노드를 리스트에 추가 자유리스트의 크기 태스크 최대 개수는 OS_CFC.H 에 정의 단방향 연결리스트의 노드를 최대 개수만큼 생성해 둠 OSTCBTbl[0] OSTCBTbl[1] OSTCBFreeList OSTCBNext OSTCBNext OSTCBNext OSTCBPrev OSTCBPrev OSTCBPrev /* Pointer to list of free TCBs*/ OS_EXT OS_TCB *OSTCBFreeList; /* Table of TCBs*/ OS_EXT OS_TCB OSTCBTbl [ OS_MAX_TASKS + OS_N_SYS_TASKS ]; uCOS_II.H 파일에 전역변수로 선언됨 ITISN Technical Lab
태스크 준비리스트(우선순위 관리) 준비 리스트(Ready List): 우선순위 관리용 자료구조 태스크 우선순위 그룹화 8개의 우선순위 그룹 지정 빠른 작업 계획 가능 준비리스트 = OSRdyGrp(8단계 색인) + OSRdyTbl(상세 값) OSRdyGrp 변수 우선순위 그룹별 작업 여부 확인 각 비트는 우선순위 그룹에 대응 각 비트를 통해 실행할 작업 존재 여부 확인 OSRdyTbl[] 준비 테이블 모든 우선순위의 작업 존재 여부를 비트 단위로 설정함 가장 높은 우선순위(가장 낮은 비트) 값에 해당하는 비트를 찾음 8~15 0~7 (OSRdyGrp) 7 6 5 4 3 2 1 가장 덜 중요한 일 가장 중요한 일 ITISN Technical Lab
태스크 준비리스트(태스크 등록 과정) OSRdyGrp |= OSMapTbl[prio >> 3]; // 8로 나누어 그룹 등록 OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07]; // 상세 정보 등록 예제)우선순위 26을 등록할 경우 1 7 6 5 4 3 2 011 = 3 010 = 2 1 7 6 5 4 3 2 준비그룹 (OSRdyGrp) OSMapTbl[i] 7 6 5 4 3 2 1 7 6 5 1 4 3 2 i 비트마스크(2진수) 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 2 0 0 0 0 0 1 0 0 3 0 0 0 0 1 0 0 0 4 0 0 0 1 0 0 0 0 5 0 0 1 0 0 0 0 0 6 0 1 0 0 0 0 0 0 7 1 0 0 0 0 0 0 0 [0] [1] 15 14 13 12 11 10 9 8 [2] 23 22 21 20 19 18 1 17 16 [3] 31 30 29 28 27 1 26 25 24 [4] 39 38 37 36 35 34 33 32 [5] 47 46 45 44 43 42 41 40 [6] 55 54 53 52 51 50 49 48 [7] 1 63 62 61 60 59 58 57 56 준비테이블 (OSRdyTbl) ITISN Technical Lab
태스크 준비리스트(태스크 삭제 과정) if( ( OSRdyTbl[ prio>>3 ] &= ~OSMapTbl[prio & 0x07] ) == 0 ) OSRdyGrp &= ~OSMapTbl[prio >> 3]; // 그룹 정보 삭제 예제)우선순위 26을 삭제할 경우 1 7 6 5 4 3 2 011 = 3 010 = 2 1 7 6 5 4 3 2 준비그룹 (OSRdyGrp) OSMapTbl[i] 7 6 5 4 3 2 1 7 6 5 1 4 3 2 i 비트마스크(2진수) 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 2 0 0 0 0 0 1 0 0 3 0 0 0 0 1 0 0 0 4 0 0 0 1 0 0 0 0 5 0 0 1 0 0 0 0 0 6 0 1 0 0 0 0 0 0 7 1 0 0 0 0 0 0 0 [0] [1] 15 14 13 12 11 10 9 8 [2] 23 22 21 20 19 18 1 17 16 [3] 31 30 29 28 27 26 25 24 [4] 39 38 37 36 35 34 33 32 [5] 47 46 45 44 43 42 41 40 [6] 55 54 53 52 51 50 49 48 [7] 1 63 62 61 60 59 58 57 56 준비테이블 (OSRdyTbl) ITISN Technical Lab
태스크 준비리스트(최우선태스크 찾기) y = OSUnMapTbl[ OSRdyGrp ]; // 우선순위 그룹에서 상위 값 추출 x = OSUnMapTbl[ OSRdyTbl[y] ]; // 우선순위 테이블에서 하위 값 추출 prio = (y << 3) + x; // 준비리스트 등록을 역으로 연산 1 7 6 5 4 3 2 준비그룹 (OSRdyGrp) = 0xA8 INT8U const OSUnMapTbl[] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F*/ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F*/ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF*/ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF*/ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF*/ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */ }; ITISN Technical Lab
태스크 제어 실습 1. 태스크 생성 2. 확장 태스크 생성 3. 태스크 스택 4. 스택 점검 5. 태스크 삭제 6. 태스크 삭제 요청 7. 태스크 우선순위 변경 8. 태스크 일시 중단 9. 태스크 동작 재개 10. 태스크 정보 알아내기 ITISN Technical Lab
1. 태스크 생성 태스크의 생성 시점 초기화 코드에서 생성 실행 중인 다른 태스크가 생성 초기화 코드에서 최소 하나 이상의 태스크를 생성해야 함 태스크 함수 항상 void형으로 리턴 64개중 56개의 태스크를 사용자가 생성 가능 무한 루프나 스스로를 삭제하는 함수로 구성 8개는 예약되어이서 사용불가 ITISN Technical Lab
1. 태스크 생성 OS_CPU.H OSTaskCreate() 함수 INT8U OSTaskCreate( void (*task) (void *pd), // 태스크 함수 이름 void *pdata, // 전달 인자 OS_STK *ptos, // 스택 사용 시작 번지 INT8U prio); // 태스크 우선 순위 OS_CPU.H OS_STK Task1Stk[1024]; Void main(void) { INT8U err; OSInit(); OSTaskCrate(Task1, (void *)0, &Task1Stk[1023], 25); OSStart(); } Void Task1 (void *pdata) { pdata=pdata; for(;;) {} ITISN Technical Lab
1. 태스크 생성 OSTaskCreate() 함수의 내부 실행 과정 요구하는 우선순위의 타당성 검사합당하면 우선순위 할당 같은 우선순위를 가지는 태스크가 있는지 검사 태스크의 스택을 생성 OSTaskStkInit() 태스크의 OS_TCB를 초기화 OSTCBInit() OS_TCBInit() 리턴값 검사 True : 태스크의 카운터(OSTaskCtr) 를 증가 False : 우선순위 예약 해제 태스크에서 OSTaskCreate() 를 호출했을시 스케줄러를 호출 생성된 태스크가 가장 우선순위가 높은 태스크이면 문맥교환 발생 멀티태스킹 전에 생성하면 스케줄러 호출하지 않음 ITISN Technical Lab
2. 확장 태스크 생성 OSTaskCreateExt() // 태스크 검사함수 등의 특수 목적으로 사용 INT8U OSTaskCreateExt( void (*task) (void *pd), // 태스크 함수명 void *pdata, // 전달 인자 OS_STK *ptos, // 스택 시작주소 INT8U prio, // 우선 순위 INT16U id, // id지정, 우선순위와 동일 입력 OS_STK *pbos, // 스택의 끝 주소 INT32U stk_size, // 스택의 크기 void *pext, // TCB 확장정보 INT16U opt // 스택 검사함수 활성화 옵션 ); // 리턴: 에러코드 ITISN Technical Lab
3. 태스크 스택 각각의 태스크는 고유한 스택을 가짐 OS_STK 타입으로 정의 연속된 공간을 확보 스택 공간할당 방법 정적 스택 : 함수 외부에 전역배열로 정의 동적 스택 : malloc() 함수 사용 (메모리 단편화 주의) 스택 사용 방향 결정 OS_STK_GROWTH 값이 0 이면 하위 메모리 -> 상위 메모리 1 이면 상위 메모리 -> 하위 메모리 스택의 크기는 응용프로그램에 따라 달라짐 typedef unsigned int OS_STK; 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 ITISN Technical Lab
4. 스택 점검 OSTaskStkChk() // OSTaskCreateExt()에서만 사용 가능 // 스택 사용 크기 확인 용도 INT8U OSTaskStkChk( INT8U prio, // 우선순위 OS_STK_DATA *pdata); // 스택의 시작 주소 // 준비사항 1. Os_CFG.H 파일 수정: OSTASK_CREATE_EXT 1 설정 2. OSTaskCreateExt()로 태스크 생성 3. opt 인자: OS_TASK_OPT_STK_CHK + OS_TASK_OPT_STK_CLR ITISN Technical Lab
5. 태스크 삭제 OSTaskDel() // 태스크 삭제 INT8U OSTaskDel( INT8U prio // 태스크 우선순위 ); // 리턴: 에러코드 // 에러코드 OS_NO_ERR // 태스크 삭제 성공 OS_TASK_DEL_IDLE // IDLE 태스크 삭제 불가 OS_TASK_DEL_DRR // 존재하지 않는 태스크 우선순위 OS_PRIO_INVALID // 우선순위 값이 64보다 큼 OS_TASK_DEL_ISR // ISR내에서 태스크 삭제 시도 // 주의 사항 1. 태스크 삭제 시 사용중인 공유자원을 사용해제 해야 한다. 2. 안전한 태스크 삭제 OSTaskDelReq() 함수를 이용한 처리 ITISN Technical Lab
6. 태스크 삭제 요청 OSTaskDelReq() // 삭제 전 공유자원 사용 해제 준비시간 제공 삭제 요청이 들어왓는지? INT8U OSTaskDelReq(INT8U prio) // 단, 삭제요청 측과 삭제 당하는 측에서 둘 다 호출 되어야 함 // 예제 프로그램 – 삭제 요청 측 While(OSTaskDelReq(TASK_TO_DEL_PRIO) != OS_TASK_NOT_EXIST) { OSTimeDly(1); } // 예제 프로그램 – 삭제 당하는 측 If(OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) // 공유 자원 및 동적 메모리 해제 OSTaskDel(OS_PRIO_SELF); 삭제 요청이 들어왓는지? ITISN Technical Lab
7. 태스크 우선순위 변경 OSTaskChangePrio() // 실행 중 우선순위 변경 가능 INT8U OSTaskChangePrio( INT8U oldprio, // 대상 우선순위 INT8U newprio // 새로운 우선순위 ); // 리턴: 에러코드 Void TaskX (void *data) { INT8U err; for(;;) // 기타 함수 구문 err = OSTAskChangePrio(10, 15);//우선순위 10=>>15바꾸겠다 } ITISN Technical Lab
8. 태스크 일시 중단 OSTaskSuspend() // 자신 또는 타 태스크를 일시 작업중단 시킴 INT8U OSTaskSuspend( INT8U prio // 중단할 태스크 우선순위 ); // 리턴: 에러코드 // 오로지 OSTaskResume()함수에 의해서만 재개 가능 Void TaskX (void *pdata) { INT8U err; for(;;) // 기타 처리 코드 err= OSTaskSuspend(OS_PRIO_SELF); // 현재 태스크 중단 // 자기자신을 중단시키겟다 // 다른 태스크가 OSTaskResume() 함수를 불러줘야 실행 된다. } ITISN Technical Lab
9. 태스크 동작 재개 OSTaskResume() // suspend 된 태스크의 작업을 재개한다. INT8U OSTaskResume( INT8U prio // 재개시킬 태스크의 우선순위 ); // 리턴: 에러코드 ITISN Technical Lab
10. 태스크 정보 알아내기 OSTaskQuery() // 특정 태스크의 정보 알아내기 INT8U OSTaskQuery( INT8U prio, // 태스크 지정 OS_TCB * pdata // 데이터 저장 구조체 ); // 리턴: 에러코드 ITISN Technical Lab
실습 프로그램 시나리오 전원 올리면 3개의 태스크용 스택 생성 LED 태스크 2개와 KEY 태스크 1개 생성 키 누르면 ITISN Technical Lab
소스코드 구현 1/3 ITISN Technical Lab
소스코드 구현 2/3 ITISN Technical Lab
소스코드 구현 3/3 ITISN Technical Lab
Comepile error 새로운 함수 사용 시 컴파일 에러 발생 OSTaskQuery(), OSTaskSuspend(), OSTaskTEsume()함수를 알수 없다고 함 C:\SOFTWARE\uCOS-II\SOURCE\uCOS_II.H 를 열어보자!! ITISN Technical Lab
C:\SOFTWARE\uCOS-II\SOURCE\uCOS_II.H 내부 OS_TASK_QUERY_EN를 1로 설정해야 사용할 수 있다!! ITISN Technical Lab
C:\SOFTWARE\uCOS-II\Ports\AVR\ATmega128\GNU\jlu\DK128 os_cfg.h(환경설정) 파일 수정 C:\SOFTWARE\uCOS-II\Ports\AVR\ATmega128\GNU\jlu\DK128 다음의 환경 변수 중에서 사용할 함수를 1로 설정하자 왜 함수를 골라서 쓰도록 했을까? ITISN Technical Lab