English

커널구조-OS_TCBInit() #4

2008.02.26 10:46

권오용 Views:8945 Recommend:40



OS_TCBInit()함수는 태스크생 성시 OS_TCB 즉, 태스크컨트롤 블록을 초기화하며, Task생성함수 OSTaskCreate() 또는



OSTaskCreateExt() 함수에서 호출한다. OSTCBInit()함수는 다음과같이 7개의 인자를 전달받는다.



1. prio : 태스크 우선순위

2. ptos : CPU.C 파일에 OSTaskStkInit()함수가 초기화한 스택의 시작위치를 가리키는 포인터, 이값은 Task 컨트롤 블럭의

             OSTCBStkPtr 필드에 저장된다.

3. pbos : 스택의 끝부분을 가리키는 포인터 이 값은 Task 컨트롤 블럭의 OSTCBStkBottom 필드에 저장된다.

4. id : 태스크의 ID(식별자), Task 컨트롤 블럭의 OSTCBId 필드에 저장된다.

5. stk_size : 스택의 전체크기. Task 컨트롤 블럭의 OSTCBStkSize 필드에 저장됨

6. pext : Task 컨트롤 블럭의 OSTCBExtPtr 필드에 두기위한 포인터.

7. opt : 선택사항을 알려주는 값 Task 컨트롤 블럭의 OSTCBOpt 필드에 저장됨



다음은 OTCBInit()함수의 소스코드와 이를 분석한 자료이다.

/*----------------------------------------------------------------------------------------------*/

INT8U OS_TCBInit(INT8U prio,    OS_STK *ptos, OS_STK *pbos, INT16U id,
         INT32U stk_size, void   *pext, INT_16U opt)
{
#if OS_CRITICAL_METHOD  == 3  // CPU.H 파일에서 이값이 3으로 정의되있으면
    OS_CPU_SR  cpu_sr       //OS_CPU_SR 형 변수 cpu_sr을 선언하고
#endif
    
   OS_TCB  *ptcb;       // Task 컨트롤 블럭구조체의 포인터 변수를 하나 선언
  
   OS_ENTER_CRITICAL(); //이영역이후는 크리티컬섹션(임계영역)이므로 인터럽트 Disable과
                        //현상태에 상태레지스터(CPSR)을 저장하는 역할을 함
  
   //크리티컬 섹션(=임계영역)
   ptcb=OSTCBFreeList; ---------------------------------------(1)
     if(ptcb != (OS_TCB *)0){ -----------------------------------(2)
         OSTCBFreeList      = ptcb->OSTCBNext;
         OS_EXIT_CRITICAL();
         ptcb->OSTCBStkPtr   = ptos;-----------------------------(3)
         ptcb->OSTCBPrio   = (INT8U)prio;
         ptcb->OSTCBStat   = OS_STAT_RDY;
         ptcb->OSTCBDly    = 0;
        
#if OS_TASK_CREATE_EXT_EN > 0
     ptcb->OSTCBExtptr  = pext;---------------------------------(4)
     ptcb->OSTCBStkSize  = stk_size;
     ptcb->OSTCBStkBottom = pbos;
     ptcb->OSTCBOpt    = opt;
     ptcb->OSTCBId    = id;

#else  
     pext         = pext;
     stk_size       = stk_size;
     pbos         = pbos;
     opt         = opt;
     id          = id;
#endif

#if OS_TASK_DEL_EN > 0
    ptcb->OSTCBDelReq     = OS_NO_ERR;;--------------------------------(5)

#endif

    ptcb->OSTCBY         = prio >> 3; ;-------------------------------------(6)

    ptcb->OSTCBBitY      = OSMapTbl[ptcb->OSTCBY];
    ptcb->OSTCBX       = prio & 0x07;
    ptcb->OSTCBBitX      = OSMAPTbl[ptcb->OSTCBX];

#if OS_EVENT_EN > 0  
  ptcb->OSTCBEventPtr    = (OS_EVENT *)0;-------------------------------(7)
#endif

#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEN_EN > 0)
  ptcb->OSTCBFlagNode    = (OS_FLAG_NODE *)0;-------------------------(8)
#endif

#if OS_VERSION >= 204
  OSTCBInitHook(ptcb);--------------------------------------------------(9)
#endif
  
  OSTaskCreateHook(ptcb);----------------------------------------------(10)


  OS_ENTER_CRITICAL();------------------------------------------------(11)

  OSTCBPrioTbl[prio]    = ptcb;-------------------------------------------(12)
  ptcb->OSTCBNext      = OSTCBList;
  ptcb->OSTCBPrev      = (OS_TCB *)0;
  if(OSTCBList != (OS_TCB *)0){
   OSTCBList->OSTDBPrev  = ptcb;
  }
  OSTCBList         = ptcb;
  OSRdyGrp         |= ptcb->OSTCBBitY;-----------------------------------(13)
  OSRdyTbl[ptcb->OSTCBY]  |= ptcb->OSTCBBitX;
  OS_EXIT_CRITICAL();  
  return (OS_NO_ERR);---------------------------------------------------(14)
}
OS_EXIT_CRITICAL();
  return (OS_NO_MORE_TCB);
}

(1) OS_TDBInit()함수는 자유리스트에서 Task컨트블록을 우선 1개 할당받는다.                



(2)(3) 자유리스트에서 사용할수있는 Task컨트를 블록이 존재할경우 이를 초기화함 Task컨트를 블록이 일단 할당되면

     OS_TCBInit()함수를 호출 한 태스크가 완전히 소유한것이고 다른곳에서 태스크를 생성해도 할당된 블록은 손상될

     염려가 없으므로 인터럽트를 활성한 상태에서 컨트롤 블록의 몇몇 필드를 초기화 할 수 있다.



(4) OSTaskCreateExt()함수로 태스크를 생성하겠다고 OS_CFG.H의 OS_TASK_CREATE_EXT_EN 값을 1로 설정했다면

     Task 컨트를 블록의 추가 필드도 함께 초기화함



(5) 태스크를 삭제할 일이없으면 OS_CFG.H의 OS_TASK_DEL_EN값을 비활성화하여 Task컨트를 블록의 저장영역을 절약

     할 수 있다.



(6) 스케쥴링시 시간을 절약하기위해 OS_TCBInit()함수에서 몇몇 필드를 계산해 둔다. 저장영역은 커지지만 시간은 절약됨.



(7) 세마포어, 뮤텍스, 메시지 메일박스, 메시지큐를 사용하지 않을경우 Task컨트를블록의 OSTCBEventPtr필드를 둘필요없음.



(8) OS_CFG.H의 OS_FLAGS_EN == 1 즉 , 이벤트 플래그를 활성화 했으면 이벤트 플래그 노드를 가리키는 포인터는 아무것도

     가리키지않도록 초기화한다.



(9) ucos버전이 2.04이상이면 OSTCBInitHook()함수를 호출한다. 이함수는 부동소수레지스터, MMU 레지스터의 내용, 태스크와

     관계있는 어떤것도 초기화하고 저장이 가능하다. OS_TCBInit()함수가 OSTCBInitHook()함수를 호출한땐

     인터럽트는 활성화 상태이다.



(10) 이 함수는 OSTaskCreate() 또는 OSTaskCreateExt()함수의 기능을 확장하는 사용자 정의함수이다.

       (9)(10)번함수를 모드 호출하는 이유는 각함수와 관련된 Task컨트를 블록의 필드를 쉽게 그룹화 할수 있기 떄문이다.



(11)(12) OS_TCBInit()함수는 새로생성한 Task 컨트를 블록을 이중연결리스트애 삽입할때 인터럽트를 비활성화 함

            리스트는 OSTCBList에서 시작하며 새 Task의 컨트를 블록은 항상 리스트 앞에 삽입됨.



(13)(14) 마지막으로 태스크는 실행준비상태가 된다. 그리고 OS_TCBInit()함수는 OS_TCB를 할당해 초기화했다는 값을

            가지고 호출자(OSTaskCreate() 또는 OSTaskCreateExt())로 리턴한다.