OS/vxWorks VxWorks (usrInit 함수의 동작 분석)
  • 728x90
    반응형

     

     

    목차

       

      userInit() 함수의 동작 분석

      롬에서 실행되는 롬 레지던트 이미지가 아닌경우, usrInit() 함수가 최초로 램에서 실행되는 함수이다.

       

      따라서, 혹시 romStart()에서 램으로 복사한 이미지에 문제가 있을경우 이곳으로 제어권을 넘기는 순간 시스템이 비 정상적으로 동작을 하게 된다. 물론, 그런 경우엔, JATG 디버거 등을 이용해서 램을 테스트해 보거나 하는 방법이 필요할 것이다.

       

      여기서는 램에 복사된 이미지가 이상이 없다고 가정을 하고, 실행 과정을 설명하도록 하겠다.

       

      한가지 주의할 것은, romStart()에서 설명한 바와 같이, usrConfig.c 파일에 들어있는 usrInit() 함수의 경우에도, 특별한 문제가 없을 경우 수정을 할 필요가 없다는 것이다. 물론 디버깅 메시지 출력등을 위해서 LED등을 깜빡이거나, 나중에 직렬 포트가 살아난 후에 printf() 함수 등을 넣는 것은 가능하겠지만, 일반적으로 BSP 포팅 과정에서 usrInit()함수를 사용자가 직접 수정을 하게 되는 일은 없다. 따라서, 여기에서 설명하는 것은 부팅 과정을 이해하고 디버깅을 돕기위한 목적이라고 볼 수 있다.

       

      usrConfig.c

      커널이 살아나기 전까지의 초기화 과정

      void usrInit
      (
      	int startType;
      )

       

      여기서 사용되는 startType은 여러 번 설명했다시피, romInit.s 에서 부팅의 종류에 따라서 (WARM boot 또는 COLD boot) 초기화 되고, romStart()를 통해서 전달되는 값이다.

      while(trapValue1 != TRAP_VALUE_1 || trapValue2 != TRAP_VALUE_2)
      {
      	/* infinite loop */
      }

       

      이 부분은 romStart() 함수에서 복사된 데이터 영역이 제대로 복사가 되었는지 확인하는 부분이다.

       

      trapValue1trapValue2는 모두 지역 변수로 선언이 되어있다. 따라서 운영체제 이미지의 컴파일과 링킹이 끝나고 나면 이 값들은 오브젝트 파일의 .data 섹션에 들어가게 되고, romStart() 함수에 의해서 RAM의 목적 번지로 복사가 된다.

       

      따라서, 이렇게 RAM에 복사된 변수의 값을 ROM에 저장된 상수의 값과 비교하는 과정을 거치면 data 섹션에 이상이 없는지 알게 된다. 만약에 문제가 있을 경우엔 무한 루프에 들어가게 되며, 소스 코드의 설명에도 나와있듯이, 이는 JTAG 에뮬레이터를 이용한 디버깅을 용이하게 하기 위한 설정이다.

       

      #endif
      
      #ifdef INCLUDE_SYS_HW_INIT_0
      
      /*
       * Perform any BSP – specific initialisation that must be done before
       * cacheLibInit( ) is called and / or BSS is cleared.
       */	
      SYS_HW_INIT_0 ( );
      
      #endif /* INCLUDE_SYS_HW_INIT_0 */

       

      다음에 사용자가 설정한 모드에 맞게 cache를 초기화 하게 되는데, 이때 호출되는 cacheLibInit() 함수는 사용자가 만드는 함수는 아니고 VxWorks 라이브러리의 일부이며, 사용자는 인자로 cache mode만 전해주면 된다.

      #if CPU_FAMILY != SIMNT && CPU_FAMILY != SIMSPARCSUNOS && CPU_FAMILY != SIMHPPA && CPU_FAMILY!=SIMSPARCSOLARIS
      
      /* don't assume bss varibles are zero before this call */
      
      bzero(edata, end-edata); /* zero out bss variables */
      
      #endif /* CPU_FAMILY != SIMNT && CPU_FAMILY != SIMSPARCSUNOS && CPU_FAMILY != SIMHPPA && CPU_FAMILY != SIMSPARCSOLARIS */

       

      시뮬레이터가 아닌 실제 타겟 하드웨어의 경우 bezro() 함수를 이용해서 .bss 섹션을 0으로 초기화 하게 된다.

       

      위에서 설명한 바와 같이, 실제 프로그램 코드를 갖고 있는 .text 섹션과 초기화된 전역변수나 지역변수의 값을 갖고 있는 .data 섹션은 romStart() 함수에 의해서 램 영역으로 복사가 된다. 문제는, bss 섹션의 처리인데, C 표준에서 초기화 되지 않은 전역변수들은 모두 0으로 초기값을 가지도록 되어있는데, 이렇게 초기화 되지 않은 전역변수들을 갖고 있는 영역이 .bss 이고, 이에 맞게 부팅 과정에서 이 영역을 0으로 초기화해 줌으로서 C언어 표준 실행 환경을 제공하게 되는 것이다.

       

      혹시 이 과정에서 너무 많은 시간이 걸리므로 부팅 시간을 절약하기 위해서 이 bzero() 함수의 호출을 건너뛰거나 해도, 응용 프로그램을 작성할 때 초기화 되지 않은 전역 변수의 값이 0이 아닐 수도 있다는 사실을 염두에 두고 작업을 한다면 큰 문제가 안될 수도 있지만 표준적인 방법은 아니라고 하겠다.

       

      #if (CPU_FAMILY == PPC)
      
      /*
       * Immediately after clearing the bss, ensure global stdin
       * etc. are ERROR until set to real values. This is used in
       * target/src/arch/ppc/excArchLib.c to improve diagnosis of
       * exceptions which occur before I/O is set up.
       */
      ioGlobalStdSet(STD_IN, ERROR);
      ioGlobalStdSet(STD_OUT, ERROR);
      ioGlobalStdSet(STD_ERR, ERROR);
      
      #endif /* CPU_FAMILY == PPC */

       

      이 부분은 위의 소스 설명에 잘 나와있듯이. PowerPC CPU의 경우, 기본 Exception 핸들러에서 예외 상황 처리를 할때, I/O 채널이 셋업이 되지 않았다는 것을 감지하면, 커널이 아직 살아나지 않은 상황에서 에러가 발생한 것이므로, 일반적인 예외 상황 처리를 하지 않고, 리부팅을 진행하게 된다.

       

      sysStartType = startType; /* save type of system start */
      
      intVecBaseSet((FUNCPTR *) VEC_BASE_ADRS); /* set vector base table */

       

      usrInit() 함수의 인자로 전달된 startType() 변수를 나중에 다른 모듈에서도 참조가 가능하도록 sysStartType에 저장을 해 놓고나서, inVecBaseSet() 함수를 호출하는데, 여기서 사용되는 VEC_BASE_ADRS값은 대부분의 CPU에서 0x0으로 정의가 되는데, 이의 정확한 의미는 CPU의 종류에 따라서 다르다. 예를 들어 자동 Interrupt Vectoring 을 지원하는 68k 계열의 칩들은 이 값이 의미가 있고, PPC나 ARM과 같이 외부 인터럽트 컨트롤러를 사용하는 칩들은 별 의미가 없는 값이다.

       

      #ifdef INCLDE_EXC_HANDLING
      #if(CPU_FAMILY==PPC)&&defined(INCLUDE_EXC_SHOW)
      
      /*
       * Do this ahead of excVecInit( ) to set up _func_excPanicHook, in case
       * the enabling of Machine Check there allows a pending one to occur.
       * excShowInit( ) will be called again later, harmlessly.
       */
      excShowInit( );
      #endif /* CPU_FAMILY == PPC && defined(INCLUDE_EXC_SHOW) */
      excVecInit( ); /* install exception vectors */
      #endif /* INCLUDE_EXC_HANDLING */

       

      그다음에 나머지 하드웨어를 초기화 하기 전에, CPU 마다 있는 Exception Handling에 관한 부분을 처리하게 된다. PowerPC의 경우, excVecInit()을 호출하면서 혹시 처리 대기중이던 Exception이 발생했을 경우 이를 처리할 수 있도록 훅 루틴을 먼저 설정하는 과정을 거치게 된다. VxWorks 에서 기본으로 제공되는 exception handler는 INCLUDE_EXC_SHOW 가 정의되어 있을 경우 Exception message를 콘솔에 뿌려주고 나서, Exception을 일으킨 태스크를 SUSPEND 상태로 바꿔 놓아서, 나중에 사용자에 의한 디버깅을 가능하게 해준다.

       

      Exception이 발생한 장소가 ISR내부라면, 에러를 복구할 방법이 없으므로 자동으로 리부팅을 하게 된다. 물론 이런 동작은 사용자가 나중에 자체 제작한 Exception Handler를 설치하게 되면 바뀌게 되며, 그게 보다 바람직한 방법이라고 볼 수도 있다. 어차피 나중에 제품이 나가게 되면 콘솔에 디버깅용 메시지를 뿌려 준다거나, 혹은 태스크를 SUSPEND 상태로 바꾼다거나 하는 일들이 별 의미가 없는 경우가 많기 때문이다.

       

      sysHwInit( ); /* initiaize system hardware */

       

      이제 본격적으로 하드웨어를 초기화하게 되는데, 여기서 호출되는 sysHwInit() 함수는 BSP 디렉토리의 sysLib.c 파일에 있다. 실제로, 이 부분이 처음으로 특정 보드나 하드웨어 관련된 초기화를 수행하는 곳이라고 할 수 있다.

       

      실제로, 이 부분이 처음으로 특정 보드나 하드웨어 관련된 초기화를 수행하는 곳이라고 할 수 있다. 기에서 보드에 장착된 인터럽트 컨트롤러나 시리얼 드라이버 컨트롤러, LAN 컨트롤러나 PCI 브리지등 각종 장치의 기화를 수행하게 된다. 물론 이런 장치들은 하드웨어 설계에 따라서 달라지게 되므로 모두 다 설명하긴 어렵지만, 선 가장 기본 적인 장치들인 인터럽트 컨트롤러와 시리얼 컨트롤러의 초기화에 대해서만 간단하게 설명하면 아래와 같다.

       

      인터럽트 컨트롤러의 초기화

      인터럽트 컨트롤러는, CPU Architecture 레벨에서 인터럽트의 처리 과정이 명확하게 정의되는 64k와 같은 일부 CPU 들의 경우 VxWorks 라이브러리에서 제공되는 수도 있지만, 대부분의 경우엔 보드상의 하드웨어 구성에 따라서 달라지게 되는 BSP 디바이스로 보게 된다.

       

      즉, VxWorks라이브러리로 제공되는 코드들은 표준된 인터페이스를 제공하는 껍데기 API정도이고, 실제로 인터럽트 처리의 대부분은 사용자가 BSP 포팅 작업의 일부로 작성을 하게 되는 인터럽트 컨트롤러 드라이버에서 이루어진다.

       

      많이 사용되는 PowerPC의 경우를 보면, 이 계열의 CPU들은, 코더 자체적으로 단 한 갠의 외부 인터럽트를 지원한다. 물론 MPC860이나 MPC8260과 같은 SoC (System On Chip) 들은 단일 칩 내부에 인터럽트 컨트롤러를 제공하므로 칩 외부에서 보면 여러 개의 외부 인터럽트를 지원하는 것 처럼 보일지도 모른다. 하지만, 그런 경우에도 역시 CPU 코어의 입장에서보면 CPU 칩 외부에 인터럽트 컨트롤러 칩이 있는 것과 마찬가지로 다루어야 한다.

       

      PowerPC 를 위해서 제공되는 VxWorks 의 표준 라이브러리는 기본적으로 아래의 세가지 함수 포인터들을 원하는 값으로 초기화 해주면, 응용 프로그램이나 장치 드라이버에서 인터럽트 컨트롤러를 사용하는데 이상이 없게 된다.

       

      _func_intConnectRtn -> intConnect()

      _func_intEnableRtn -> intEnable()

      _func_intDisableRtn -> intDisable()

       

      물론 이 외에도, 다른 함수 포인터들이 많이 있지만, 실제로 주로 사용되는 것들은 이 세가지를 함수 포인터들이다. 따라서, sysHwInit()에서 호출되는 인터럽트 컨트롤러의 초기화 함수에서는 실제 인터럽트 컨트롤러의 필요한 레지스터들을 초기화 하는 일 외에, 위의 세가지 함수 포인터를 사용자 함수로 할당을 하는 것이 필요하다.

       

      각각의 함수에서 하느일은, 함수 이름에서 쉽게 알 수 있듯이, _funcIntConnectRth 함수의 경우엔 특정 인터럽트 벡터에 사용자가 원하는 인터럽트 섭스 루틴을 붙여주는 역할을 하는 함수로, 사용되는 인자는 당연히 VxWorks API인 intConnect와 같다. 위에서 설명한바와 같이, PowerPC의 인터럽트 처리 구조는 외부 인터럽트 소스를 하나만 제공하는 구조이므로, 인터럽트 컨트롤러를 통해서 들어오는 여러 개의 외부 인터럽트 소스를 처리하기 위해서는 사용자가 배열이나 연결 리스트등을 이용해서, 각각의 외부 인터럽트를 처리할 수 있는 인터럽트 핸들러를 관리하는 방법이 필요하다.

       

      _func_intEnableRtn_func_intDisableRtn은 각각의 벡터에 대한 인터럽트 소스를 개별적으로 Enable 시키거나 Disable 시키는 일을 하는 함수들이며, 위의 경우와 마찬가지로 역시 사용자가 편한 방식으로 구현을 하면 된다.

       

      ARM 칩의 경우에도 역시 PowerPC 와 비슷한 인터럽트 처리 구조를 갖고 있는데, 하드웨어적으로 ARM 계열의 칩들은 일반적인 외부 인터럽트를 처리하는 IRQ 입력 이외에, 보다 빠른 인터럽트 처리를 제공하는 FIQ 입력을 제공한다는 차이점이 있다. 하지만, VxWorks의 경우 FIQ 인터럽트를 지원하지 않으므로, 소프트웨어적으로는 PowerPC 의 경우와 같이 외부 인터럽트 소스가 하나인 코어로 생각을 하면 된다.

       

      따라서, 인터럽트 컨트롤러 드라이버를 작성할 때, PowerPC의 경우와 마찬가지로 사용자가 드라이버 레벨에서 필요한 인터럽트 벡터들을 관리해주는 것이 필요하고, 이런 일들을 해 주는 함수 포인터들을 VxWorks 인터럽트 처리 라이브러리에 함수 포인터를 통해서 제공해주는 것고 똑 같은데, 다만 CPU 의 구조가 틀린 이유로 제공하는 함수 포인터의 종류가 틀리다.

       

      sysIntLvecChkRtn -> 기존 인터럽트 핸들러에서 내부적으로 사용

      sysIntLvlVecAckRtn -> 기존 인터럽트 핸들러에서 내부적으로 사용

      sysInLvChgRtn -> intLevelSet()

      sysIntLvEnableRtn -> intEnable

      sysIntLvDisableRtn -> intDisable

       

      위의 PowerPC의 경우와 달리 약간 복잡한 것은, ARM Architecture 의 경우 두가지 인터럽트 처리 모드, 즉 인터럽트 처리 중에 보다 높은 우선순위의 인터럽트가 발생하면 이를 즉시 처리하는 NT_PREEMPT_MODEL 과, 인터럽트 처리 중에는 다른 인터럽트를 처리하지 않고, 현재 처리중인 인터럽트가 끝나고 나서야 다음 인터럽트를 처리하는 INT_NON_PREEMPT_MODEL이 있기 때문이다.

       

      INT_PREEMPT_MODEL 의 경우 높은 우선 순위의 인터럽트 처리 지연 시간을 최소화할 수 있다는 장점이 있고, INT_NON_PREEMPT_MODEL의 경우엔 전반적인 인터럽트 처리가 보다 효율적이라는 장점이 있다.

       

      ARM 을 위한 VxWorks의 라이브러리에서는, PowerPC와는 달리 기본 인터럽트 핸들러를 각각의 모드를 위해서 제공을 하고, BSP 개발자는 위에서 언급된 다섯가지 함수를 만들어서 함수 포인터를 통해서 라이브러리로 전달해주면 되는 것이다. 따라서, PowerPC의 경우에 인터럽트 컨트롤러 드라이버가 배열이나 리스트를 통해서 각각의 인터럽트 벡터를 위한 인터럽트 핸들러를 관리했는데, ARM의 경우엔 아키텍쳐 라이브러리 레벨에서 인터럽트 벡터를 관리하는 방식으로 되어있다는 차이가 있다.

       

      시리얼 컨트롤러의 초기화

      sysHwInit()에서 인터럽트 컨트롤러의 초기화와 더불어 시리얼 컨트롤러를 초기화 하는데, 이는 표준 함수 이름으로 sysSerialHwInit()을 호출함으로서 이루어진다. 개발자는 BSP 디렉토리에 sysSerial.c 파일을 만들고, 이 파일 내부에서 다음의 세가지 중요한 함수를 제공하게 된다.

       

      sysSeralHwInit();

      sysSerialHwInit2();

      sysSerialChanGet();

       

      sysSerialHwInit()함수에서 인터럽트 관련 부분을 제외한 모든 시리얼 컨트롤러 하드웨어의 초기화가 이루어진다. 실제 인터럽트 서비스 루틴의 등록과, 시리얼 입출력 관련 인터럽트는 sysSerialHwInit2() 함수에서 이루어지는데, 소스 파일의 설명에도 나와있듯이, 인터럽트 서비스 루틴을 등록하는 intConnect() 함수에서 내부적으로 커널 함수를 사용하므로, sysSerialHwInit2() 함수는 VxWorks 커널이 살아난 다음에야 제대로 동작을 하게 되어있다.

       

      하지만, 위에서 살펴보았듯이, BSP 개발자가 등록한 인터럽트 컨트롤러 관련 루틴들이 그대로 사용되는 PowerPC의 경우에는, 사용자가 구현한 루틴에서 특별히 커널 함수들을 사용하지 않는다면 이런 제약은 적용되지 않는다고 할 수 있다.

       

      세번째 함수인 sysSerialChanGet() 는 나중에 ttyDevCreate() 함수를 이용해서 시리얼 포트를 위한 장치 (/tyCo/*) 를 만들 때 각각의 시리얼 채널에 대한 표준 컨트롤 스트럭쳐를 얻어내기 위해서 호출이 되는 함수이다.

       

      usrKernelInit( ); /* configure the Wind kernel */

       

      usrKernelInit() 함수는 이름과 같이 실제로 커널을 초기화 하는 함수라기보다는, 커널을 초기화 하는데 필요한 데이터 구조체들을 초기화 하는 역할을 한다. 이 함수는 /tornado/target/src/config/usrKernel.c파일에 있는데, config.h 나 configAll.h 에 정의된 커널 모듈들을 초기화 하고, 사용자가 지정해 준 옵션에 따라서 각종 커널 큐들을 만들어준다. VxWorks 커널이 제대로 동작하기 위해서는 많은 커널 큐들이 필요한데, 여기서 초기화되는 큐들은 다음과 같은 세개의 큐들이다.

       

      • readyQ : 사용자가 INCLUDE_CONSTANT_RDY_Q 옵션을 지정했을 경우 우선순위 기반의 비트맵 큐가 사용이 되고, 그렇지 않을 경우 우선순위 기반의 리스크 큐가 사용되는데, 이 큐에 실행 가능한 태스크들이 들어가서 실행 순서를 기다리게 되고, 어떤 순간이던 이 큐에 있는 태스크들 중에서 가장 우선순위가 높은 태스크가 CPU를 차지하게 되는 것이다.
      • activeQ : 이는 시스템에 존재하는 모든 태스크들이 연결되어있는 리스트이다. WindSh 에서 i 명령을 주면 태스크들의 리스트를 보여주는데 그때 사용하는 것이 바로 이 큐에 있는 태스크들의 리스트인 것이다.
      • tickQ : 이것은 태스크들의 딜레이를 처리하기 위한 큐이다. 가장 기본적으로는 taskDelay() 호출을 했을경우 이 큐에서 대기를 하게 되고, 소프트웨어 Watchdog 타이머를 이용할 경우에도 큐가 사용된다. 또한, 세마포어나 메시지큐와 같은 VxWroks 커널 API를 사용할 때 인자로 타임아웃 값을 줄 수가 있는데, 그럴 경우에도 이 큐를 이용한다.

       

      시스템 전체적으로 각각 하나씩만 존재하는 이런 큐들과 달리, 태스크를 PEND 상태로 빠지게하는 큐들은 각각의 커널 오브젝트, 즉 세마포어나 메시큐마다 하나씩 존재하게 된다. 따라서, 어떤 태스크가 semTake()msgQReceive() 호출을 하고, 원하는 이벤트가 발생하지 않은 경우 그 커널 오브젝트의 PEND 큐에 들어가서 대기를 하게 된다. 위에서 설명한 바와 같이, 만약에 타임아웃 값이 있는 경우라면 tickQ 에도 동시에 들어가게 되므로, 그런 경우엔 동시에 두개의 큐에 들어가있는 경우라고 할 수 있다.

       

      #ifdef INCLUDE_USB
      #ifdef INCLUDE_OHCI_PCI_INIT
      sysUsbPciOhcilnit();
      #endif
      #endif
      
      #ifdef INCLUDE_CACHE_SUPPORT
      #ifdef USER_I_CACHE_ENABLE
      cacheEnable(INSTRUCTION_CACHE); /* enable insrtuction cache */
      #endif /* USER_I_CACHE_ENABLE */
      
      #ifdef USER_D_CACHE_ENABLE
      cacheEnable(DATA_CACHE); /* enable data cache */
      #endif /* USER_D_CACHE_ENABLE */
      
      #if(CPU == MC68060)
      #ifdef USER_B_CACHE_ENABLE
      cacheEnable(BRANCH_CACHE); /* enable branch cache */
      #endif /* (CPU == MC68060) */
      #ebdif /* INCLUDE_CACHE_SUPPORT */
      
      /* start the kernel specifying usrRoot as the root task */
      
      kernelInit((FUNCPTR) usrRoot, ROOT_STACK_SIZE, (char *)MEM_POOL_START_ADRS,
      			sysMemTop (), ISR_STACK_SIZE, INT_LOCK_LEVEL);
      }

       

      이 후에 캐시를 Enabel 해 놓고나서 실제로 kernelInit() 함수를 이용해서 멀티 태스킹 커널이 살아나게 된다.

      이 함수의 인자들을 하나씩 살펴보면, 우선 usrRoot가 최초로 생성하는 태스크의 엔트리 포인트가 된다.

      ROOT_STACK_SIZE 는 이 초기 태스크가 살아나면서 메모리 관리자를 초기화 하고, 그렇게 해야만 malloc()을 이용한 메모리 할당이 가능한데, 일반적인 태스크들은 생성될 때 malloc()을 이용한 스택 영역의 생성이 가능하지만 이 초기화 태스크의 경우 아직 그 함수를 사용할 수 없기 때문에 약간 특수한 방법으로 스택 영역을 정적으로 할당하게 된다. ROOT_STACK_SIZE는 그때 할당하는 스택의 크기이다.

       

      MEM_POOL_START_ADRS는 usrConfig.c 파일과 configAll.h 를 통해서 결정이 되는데, 기본적으로 링커에 의해서 정의되는 end 라는 심볼의 값으로 정해진다. 이 심볼은 링커가 VxWorks 이미지를 링크할 때 .text와 .data 및 .bss 섹션의 조립이 모두 끝나면 그 마지막 번지를 end 라는 심볼에 넣어준다. 즉, 전체 VxWorks 이미지의 끝 번지를 저장하고 있는 심볼이다.

      단, WDB디버그 에이전트를 VxWorks 이미지에 넣는 경우엔, 그 번지에서 WDB_POOL_SIZE만큼을 비워놓게 되는데, 이는 디버그 에이전트가 사용할 공간을 비워놓는 것이다.

       

      그 다음 인자는 sysMemTop()의 리턴 값으로 결정이 되는데, 여기가 시스템 메모리 풀의 끝 번지가 된다.

      즉, 동적인 메모리 할당을 위해서 사용되는 메모리 풀 영역은, MEM_POOL_START_ADRS부터 sysMemTop() 까지로 정해진다. 이 sysMemTop() 함수는 BSP 디렉토리에 있는 sysLib.c 파일에 있는데, 시스템의 물리적 메모리의 끝을 가리키는sysPhysMemTop()의 값에서 USER_RESERVED_MEM 값을 뺀 주소로 정해진다.

       

      ISR_STACK_SIZE는, 인터럽트 서비스 루틴을 위한 전용 스택 영역을 따로 제공하는 CPU들의 경우에, 사용될 스택의 크기를 정해주는 인자이고, INT_LOCK_LEVEL 은 VxWorks 커널 내부에서 중요한 영역의 실행을 방해받지 않기 위해서 필요할 때 사용되는 intLock()함수에서 사용할 인터럽트 Disable의 레벨을 결정한다. 위에서 설명한 PowerPC나 ARM과 같이 외부 인터럽트를 하나만 허용하는 CPU들의 경우 intLock()은 그저 외부 인터럽트 자체를 enable 하거나 disable 하거나 둘중의 하나지만, 인터러트 레벨이라는 개념을 제공하는 CPU들의 경우엔, 특정 레벨 이하의 인터럽트만 disable 시킴으로서, 설사 커널이 중요한 처리를 하느라고 intLock() 을 해 놓은 상태에서도 절대 disable 되면 안되는 외부 인터럽트 소스의 경우엔 처리가 가능하고록 할 수 있는 것이다.

       

       

       

       

       

       

      728x90
      반응형

      'OS > vxWorks' 카테고리의 다른 글

      VxWorks Shell edit control  (0) 2017.07.05
      vxSim 과 Window 네트워크 통신  (0) 2017.07.05
      VxWorks (romStart( ) 함수의 동작 분석)  (0) 2017.07.05
      VxWorks (BSP 파일구성/romInit.s 분석)  (0) 2017.07.05
      VxWorks C99 버전 변경  (0) 2017.06.30
    상단으로