Chapter 1. VxWorks BSP 파일 구성
.h : 이 파일은, 반드시 그럴 필요는 없지만, 일반적으로 BSP 디렉터리와 같은 이름을 갖는 헤더 파일로,
하드웨어에 관련된 각종 상수와 파라메터 값을 선언한다.
config.h : 이 파일은 BSP의 소프트웨어적인 각종 상수 값들을 갖과 있으며, 만들어 지는 VxWorks 이미지에
포함될 각종 운영체제 라이브러리 등도 여기에서 결정된다. 이 파일에서 ../all/configAll.h 파일을 포함하는데,
그 파일에 선언된 정의들을 고치지 않는 것이 좋고, 꼭 그파일에 선언된 정의들을 고치지 않는 것이 좋고, 꼭
그파일에 선언된 내용을 바꿔야 한다면 config.h 파일에서 정의된 내용을 #undef 하고 나서 다시 정의하는
것이 좋다.
romInit.s : 이 어셈블러 파일이 BSP의 롬 초기화 코드를 갖고 있다. 즉, 보드에 최초로 전원이 인가되거나
혹은 하드웨어 리셋 버튼이 눌리는 경우에, 이 루틴에 정의된 romInit( ) 이라는 심볼로부터 전체 운영체제의
실행이 시작된다.
일반적으로, 보드에서 램을 사용할 수 있을 정도의 최소한의 하드웨어 초기화를 실행한 후에 bootInit.c
에 정의되어 있는 romStart( ) 루틴으로 분기한다.
bootInit.c : …/target/config/all/ 디렉터리에 위치하며, 하드웨어 부팅 후 처음으로 실행되는 C 소스코드 이다.
이곳에 정의된 romStart( ) 루틴에서는, 실제 운영체제를 초기화 하는 usrInit( ) 함수로 실행을 넘기기 전에
필요한 램 초기화 작업을 한다. 이 초기화 작업은 실행중인 VxWorks 이미지의 종류에 따라서 다른데, 예를
들어 롬에 저장된 운영체제 이미지를 램으로 복사하거나 혹은 롬에 저장된 초기화된 전역변수 영역을
램으로 복사하거나 하는 등의 일을 한다.
bootConfig.c : VxWorks 부트롬 (bootrom)의 운영체제 초기화 루틴인 usrInit( )을 갖고 있는 파일이다.
실제로 운영체제의 각종라이브러리들이 이곳에서 초기화 되고, 각종 시스템 태스크들이 생성되며
마지막으로 부팅 프로그램을 호출하여, 실제 램에서 실행되는 VxWorks 이미지를 이더넷이나 기타 다른
방법으로 적재하게 된다.
usrConfig.c : 실제 응용 프로그램을 위한 VxWorks 이미지의 초기화 루틴인 usrInit( )을 갖고 있는 파일이다.
위의 bootConfig.c 와의 차이는, 우선 위의 파일은 다른 VxWorks 이미지를 램에 적재하는 것이 주 목적인
부트롬의 메인 루틴을 갖고 있는 반면이, 이 파일은 실제로 응용 프로그램에 사용될 VxWorks의 초기화
루틴을 갖고 있다는 점이다.
따라서, 모든 시스템 태스크들이 생성되고 난 이후에, 마지막으로 사용자 루틴을 호출함으로써 사용자가
작성한 응용 프로그램이 VxWorks 상에서 실행되도록 해 주는 것이다.
Chapter 2. romInit.s 동작 분석
romInit.s
보드에 전원이 인가되면 CPU가 어떤 식으로 깨어나서 동작을 시작하는가를 이해해야 최초로
실행되는ROM 초기화 코드, 혹은 부트스트랩 (Boostrapping) 코드라고 하는, 하드웨어 리셋 발생
후 최초로 실행되는 코드 영역을 어떻게 배치할 것인가를 결정할 수 있다.
일반적으로 대부분의 CPU들은 전원 인가나 하드웨어 리셋등의 이벤트후에 ROM에 있는 부트
스트랩 코드를 CPU로 가져오기 위한 특별한 동작을 지원한다.
모토롤라의 MPC8260 같은 경우엔 "Boot Chip-Select Operation" 이라는 동작 모드가 있는데,
하드웨어 리셋이 발생한 직후에는, 나중에 GPCM(General Pupose Chipselect Machine) 이 적절한
순서로 초기화 되기 전까지 CS0(Chip Select 0)가 항상 인가되게 된다.
따라서, 실제로 ROM 초기화 코드의 위치가 시스템 메모리 맵 상에서 어디이건간에, 일단 하드리셋
직후에는 CS0에 물려있는ROM 영역에서 코드를 가져오기 시작하는데 MPC8260의 리셋백터는
0x100번지에 있으므로, 결국 하드웨어적으로 CS0에 물려있는 ROM 영역의 오프셋 0x100 번지에서부터
ROM 초기화 코드가 위치하도록 하면 된다.
물론 나중에 이 ROM 영역의 오프셋0x100 번지에서부터 ROM 초기화 코드가 위치하도록 하면 된다.
물론 나중에 이 ROM영역의 실제적인 위치는 GPCM의BR0(Base Register 0)의 값에 따라서
(보통 0xfff00000)적절한 값으로 재 배치가 되고, 그 이후에는 그 번지값에 대한 접근에만 응답을 하게 된다.
이렇게 결정된 ROM의 위치에 최초로 실행되는 코드가 들어가게 되는데, 이 코드가 바로 지난시간에
설명한, romInit.s 에 들어있는 어셈블리 코드가 된다.
다시한번 설명하면, 이 romInit.s에 들어있는 코드의 목적은 CPU자체의 각종 환경설정 레지스터나 혹은
장착된 하드웨어 장치들을 안정적인 상태로 초기화하고, 시스템에 존재하는 RAM 메모리 영역을 사용
가능한 상태로 만들고나서, romStart( )라는 C함수에게 제어권을 넘겨주는 역할을 한다.
여기서, 각종 하드웨어를 안정적으로 만든다는 것은 그리 어려운 문제가 아닌데, 왜냐하면 대부분의
칩들이 하드웨어 리셋 상태에서 빠져나올 때 기본적으로 안정적인 상태로 들어가도록 설계가 되어있기
때문이다.
따라서, 예를 들어 인터럽트 컨트롤러의 경우, 하드웨어적으로 초가화된 이후에는 기본적으로 아무런
인터럽트 요청도 받아들이지 않는 상태로 초기화가 되어있는 경우가 많다.
물론 이런 경우에도 확실히 하기위해서, 다시한번 칩 메뉴얼에 정의된 방법대로 인터럽트 마스크(Mask)
레지스터나 인터럽트 펜딩(Pending) 레지스터를 적절한 값으로 다시한번 초기화 해 주는 등의 일이
필요하다.
실제로 이 romInit.s 라는 어셈블러 파일에서 이루어지는 가장 중요한 일은, 바로 보드상에 존재하는
RAM영역을 사용 가능한 상태로 만들어 주는 것이다.
이 RAM 영역이 초기화 되어야 비로소 CPU의 스택 포인터를 사용 할 수가 있게 되고, 그제서야 C로 된
함수를 호출 할 수 있게 되는 것이다. 많은 개발자들이 이미 인지하고 있듯이, 어셈블러 코드는 정말로
꼭 필요한 부분에만 사용하고, 되도록이면 많은 부분을 보다 고수준의 언어인 C나 C++로 작업을 하는 것이,
코딩 작업의 효율성이나 장기적인 유지/보수의 문제를 보더라도 훨씬 좋은 선택인 것이다.
특히나 RAM/ROM 메모리 소자의 가격이 점점 떨어지고 또 CPU의 성능이 나날이 올라가는 추세에서는
어셈블러 코딩의 필요성이 점차 감소하고 있다고 볼 수 있겠다.
참고로 VxWorks 표준 BSP에서 어셈블러로 되어있는 파일은, 지금 설명하고 있는 ROM 초기화 코드인
romInit.s와 더불어 각종 BSP관련 어셈블러 함수들을 담고 있는 sysALib.s 파일 이렇게 단 두개 뿐이다.
어셈블러 형식의 BSP 라이브러리 설명한 바와 같이, romInit.s 파일은 이제 겨우 시스템이 하드웨어 리셋
상태에서 깨어나고 있는 상황이므로 어셈블러로 작성할 수 밖에 없다.
반면에 sysALib.s 파일에 있는 어셈블러 루틴들은 sysLib.c에 있는 C함수들과 마찬가지로, BSP에서 제공하는
함수들을 가지고 있는데, 그중에서 반드시 어셈블러로 작성을 해야 하는 루틴들을 갖고 있다. 이렇게
어셈블러로 되어있는 BSP라이브러리가 존재하는 이유는 크게 두가지인데, 상황에 따라서 BSP 개발자들은
이 파일에 있는 필수 함수만 구현을 하거나 아니면 여러가지 다양한 함수들을 구현 할 수도 있다.
우선, 첫번째 이유는, CPU에서 제공하는 특정 명령어를 C를 이용해서 구현할 수 없는 경우에 당연히
어셈블러로 필요한 명령어를 직접 사용해야 한다.
예를 들어, 가장 대표적인 경우가, CPU에서 ROM/RAM을 접근하는 메모리 공간 이외에, 입출력용
주소 공간을 따로 제공 하는 경우이다.
메모리 공간에 대한 접근은 C/C++에서 제공하는 포인터를 이용하면 아주 쉽게 해결이 된다.
하지만 인텔 X86 계열의 칩들처럼 I/O 공간을 따로 제공하는 경우 이에대한 접근은 미리 정의된 특별한 CPU
명령어들 (inb/outb, inw/outw. intl, outl)을 사용해야 하는데 표준 C 언어 에서 이를 직접 사용할 수 있는
방법은 없다.
따라서 필요한 일을 해주는 함수를 어셈블러로 구현한 후에 이를 C에서 호출해서 사용하는 방식으로
해결을 한다.
두번째 이유는, 비록 C를 이용해서 똑 같은 일을 할 수 있어도 이를 어셈블러를 이용해서 구현하면 보다
효율적인 경우에 어셈블러 함수를 만들어서 사용하는 경우가 있다.
아래의 코드 예제는 PCI 버스를 가지고 있는 거의 모든 PowerPC 계열의 BSP에서 제공하는 어셈블러
함수이다.
FUNC_BEGIN(sysPcilnLong)
lwbrx r3, r0, r3 /* Read 32 bit byte reversed */
sync /* Sync I/O operation */
bclr 20, 0 /* Return to caller */
FUNC_END(sysPcilnLong)
(리스트 1 : sysALib.s 파일)
FUNC_BEGIN과 FUNC_END는 Tornado 에서 제공하는 매크로들로, 어셈블러 함수의 시작 라벨과
마지막에 함수의 크기를 계산하는 .size 명령으로 치환된다. 여기서 중요한 것은 첫번쨰 명령어인
lwbrx로 , 이는 Little Endian 방식의 버스(예를 들어 PCI)에서 읽어온 4바이트짜리 데이터를 Big Endian
방식의 프로세서인 PowerPC에서 사용할 수 있도록 바이트 순서를 바꿔서 레지스터에 넣어주는
명령어이다.
당연히 C 언어로도, PCI의 특정 메모리 주소에서 값을 읽어온 후에 이를 조작해서 바이트의 순서를
바꾸어주는 함수를 쉽게 만들 수 있다.
하지만 아무리 잘 만든다고해도, 위의 함수 예제와 같이 명령어 하나로 이를 해결하는 것 만큼 효율적으로
만들 수는 없을 것이다.
또 모든 표준 BSP의 경우에 sysALib.s 파일에 보면 sysInit 이라는 라벨을 갖는 함수가 존재한다.
이 함수는 부트롬을 통해서 RAM에 적재되는 버전의 VxWorks 이미지의 첫 시작 코드가 되며
romInit.s에서 하는 것과 같이 보드를 초기화 하는 일을 하지만 약간 다른 의미를 갖는데, 이는 다음
부트롬 이미지의 부팅 과정을 설명할 때 보다 자세하게 설명할 기회가 있을 것이다.
vxWorks_rom 이미지의 메모리 맵
그러면, romInit.s 파일을 좀더 자세히 분석을 해 보기전에 우선 vxWorks_rom 메모리 맵을 살 펴보기로 한다.
VxWorks 운영체제의 경우 부팅에 사용되 이미지 파일의 종류에 따라서 메모리 맵이 달라지는데,
각종 부트롬이나 운영체제 이미지의 종류에 대한 간단한 설명은 지난호를 참조하기를 바라며,
이번호에는 가장 간단한 부팅 과정을 갖고있는 vxWorks_rom 이미지를 기준으로 설명을 하도록 하겠다.
LOCAL_MEM_LOCAL_ADRS는 config.h 파일에 정의되는 매크로로, 시스템의 RAM 영역의 시작 번지를
가리킨다.
거의 모든 BSP 에서 이값은 0이 되지만, 예를 들어 0번지에 반드시 ROM 영역이 와야하는 BSP 같은
경우엔 0이 아닌 다른 값을 가질 수 도 있다.
MPC8260 같은 경우엔 0x100 번지의 Reset Vector를 시작으로해서 0x100씩의 오프셋 값을 갖고 여러가지
Exception Vector 들이 위치하는 구조로 되어있다. 그리고 Exception이 발생하면 CPU는 정해진 특정 번지로
점프를 수행해서 그곳에서부터 명령어를 수행하게 된다. 예를 들어, 외부 인터럽트 요청이 발생하면 CPU는
0x500번지로부터 명령어를 수행하게 되는 식이다.
따라서 엄밀한 의미에서 이는 인터럽트 벡터가 아니고 인터럽트 서비 루틴 (ISR)이 직접 0x500번지에
위치하게 된다. 다른 Exception들도 마찬가지 방식으로 처리된다.
SM_ANCHOR_OFFSET은 공유 메모리 네트웍(Shared Memory Network)이나 혹은 VxMP와 같은
추가적인 라이브러리를 이용해서 Multi-Processor환경에서 공유 메모리를 이용한 태스크간 통신을
수행할 경우에 필요한 영역이다.
BOOT_LINE_OFFSET은 부트롬을 이용해서 부팅을 하는 RAM 기반의 VxWorks 이미지의 경우 부트 장치나
IP주소값 등을 저장하고 있는 부트라인의 위치인데, 이는 나중에 부트롬의 동작을 설명할 때 다시
설명하도록 하겠다.
EXC_MSG_OFFSET은 재 부팅을 해야하는 상황에서 Exception Message를 갖고 있다가 부팅 과정에서
보여주기 위해서 사용하는 영역이다.
일반적으로 어떤 태스크가 Exception을 발생시키면 VxWorks 에서 제공하는 기본 Exception Handler
는 그 태스크를 SUSPEND 상태로 만들고, 자세한 Exception Message를 콘솔에 보여주게 된다.
물론 이는, 개발 기간동안의 디버깅을 위한 조치이다. 하지만, 이런식의 디버깅이 불가능한 경우,
즉 인터럽트 서비스 루틴(ISR)에서 발생한 Exception Message를 콘솔에 보여주게 된다.
시스템을 소프트웨어적으로 리부팅하게 되고, 그 과정에서 이곳에 저장된 Exception Message를
보여줌으로서 사용자에게 왜 리부팅이 발생했는지를 알려주는 것이다.
초기 스택 영역
그리고 VxWorks OS 이미지가 적재되는 주소인 RAM_LOW_ADRS에서부터 초기 스택 영역이 시작되는데,
실제로 이 매크로 값은 configAll.h 파일에 보면 아래와 같이 정의가 되어있다:
#if (_STACK_DIR == _STACK_GROWS_DOWN)
#ifdef ROM_RESIDENT
#define STACK_ADRS STACK_RESIDENT
#else
#define STACK_ADRS _romInit
#endif /* ROM_RESIDENT */
(리스트 2 : configAll.h 파일)
PowerPC 아키텍쳐의 경우 스택은 아래 방향으로 자라는 것으로 되어있고, 또 지금 우리가 다루는
VxWorks_rom 이미지는 ROM에서 실행하지 않고 RAM에서 실행하는 이미지이다.
따라서 결국 STACK_ADRS는 _romInit이라는 심볼로 정의가 된다. 바로 아래에서 이 _romInit
심볼을 실제로 갖고 있는 romInit.s 파일을 설명하겠지만, 이 _romInit 심볼은 결국 전체 VxWorks_rom
이미지의 엔트리 포인트가 되며, ROM 초기화 코드이므로 당연히 ROM에서 실행을 하게 된다.
자 그럼, 여기서 아주 당연히 나오는 질문이, 어떻게 데이터가 써져야 하는 스택 영역을 ROM
영역으로 배치하느냐 하는 것인데, VxWorks_rom 파일의 메모리 맵 파일을 만들어보면 실제
이 _romInit 심볼의 주소를 알 수 있다.
메모리 맵 파일을 만들어내는 가장 간단한 방법은, 관련된 Makefile을 수정하는 것이다.
/tornado/target/h/make/rules.b네 파일의 415번쨰 줄을 보면 vxWorks_rom이미지를 만드는 build rule
이 나오는데, 이중에서 아랫쪽에 보면 $(LD)로 시작하는 링커 명령 부분이 나온다.
이 명령에서 중간에 적당한 부분에 "-Msp $@.map" 이라고 끼워 넣고나서 "Make clean vxWorks_rom"
명령을 주면 vxWorks_rom 이미지의 메모리 맵 파일인 vxWorks_rom.map 파일이 생성된다.
이 파일을 들여다보면 아래와 같은 부분을 찾을 수 있다.
.text 0x00100000 0x9c 150
0x00100000 wrs_kernel_text_start=.
0x00100000 _wrs_kernel_text_start=.
*(.text)
.text 0x00100000 0x78c romInit.o
0x00100000 romInit
0x00100000 _romInit
.text 0x0010078c 0x1a8 bootInit_uncmp.o
0x0010078c romStart
*fill* 0x00100934 0x4
(리스트 3 : vxWorks_rom.map 파일)
여기서 주의 깊게 볼 것은, romInit.s가 컴파일 된 출력물인 romInit.o에 우리가 원하는 romInit
이라는 심볼의 값이 0x0100000 번지로 나와 있다는 것이다.
이는 이 특정 ROM영역의 주소가 아니라 RAM 영역의 주소인 것이다.
따라서 결국 초기 스택 포인터가 0x00100000번지로 설정이 되고 운영체제가 정상적으로 부팅이 되는
것이다.
VxWorks BSP를 처음으로 접하고, 부팅 과정을 분석하는 개발자들이 좀 혼란스럽게 생각하는게 바로 이
부분이다.
또 사람뿐만 아니라, JTAG 에뮬레이터 등을 이용해서 심볼 기반의 디버깅을 할 때 사용하는 디버거 역시
이 부분에서 정상적이지 않은 동작을 하는 이유가 바로 이 때문이다. 즉, 실제로 romInit 코드는 현재
ROM에서 실행중인데, 심볼 테이블의 정보는 RAM번지로 나와있는 것이다.
이렇게 되어있는 이유는 vxWorks_rom 이미지의 링크 및 동작 방식때문이다.
vxWorks_rom 이미지를 구성하고 있는 수많은 오브젝트 모듈들 중에서 실제로 ROM에서 실행되는
모듈은 딱 두개로, romInit.s로부터 만들어지는 romInit.o 파일과, bootInit.c 파일로부터 만들어지는
bootInit.o 파일 (실제로 컴파일 과정에서 bootInit.c 파일은 bootInit_uncmp.c 파일로 복사되어
bootInit_uncmp.o 파일로 컴파일이 된다) 이렇게 단 두개 뿐이다.
그런데, 실제로 부팅 과정을 들여다보면, romStart( ) 함수에서, 현재 ROM에 바이너리 형태로 저장되어있는
vxWorks_rom이미지를 RAM으로 복사한 후에, RAM에 있는 코드로 점프를 해서 수행을 계속 하는
방식으로 되어있다.
따라서 커맨드라인 빌드 방식의 vxWorks_rom 이미지를 만드는 과정에서는, 두개의 파일을 그냥 전체
이미지에 링크를 한 후에, 엔트리 포인트를 romInit( ) 으로 정해주고나서 링크 주소를 RAM 번지로 주게된다.
이렇게 하면, ROM에서 실행하는 극히 일부분의 초기화 코드 부분을 제외한 나머지 부분은 링크 번지와
실행 번지가 일치하게 되는 것이다.
Tornado 2.x의 프로젝트 기능을 이용해서 vxWorks_rom 이미지를 만들 경우엔 이와는 양상이 좀 다른데,
이는 다음에 보다 자세히 설명할 기회를 갖도록 하겠다.
romInit.s 파일 분석
그러면 실제 romInit.s 어셈블러 파일의 코드를 보면서 중요한 부분을 설명하도록 하겠다.
64 _romInit:
65 romInit
66 bl cold /* jump to the cold boot initalzation */
67 nop
68 bl start /* jump to the warm boot initialzation */
69
70 /* copyright notice appears at beginning of ROM (in TEXT segment) */
71
72 .asdii "Copyright 1984-1999 Wind River Systems, Inc."
73 .align 2
74
75 cold:
76 li r3, BOOT_COLD /* set cold boot as start type */
77
78 start:
79
80 /* disable external interrupts (by zeroinf out msr) */
81 xor r5, r5, r5
82 isync
83 mtmsr r5
84 isync
85
86 /* invalidate and disable the MPU's data/instruction caches */
87 mfspr r6, HID0
88 ori r5, r5, 0xC000
89 andc r6, r6, r5 /* clear cache enable bits in r6 */
90 mr r5, r6
91 ori r5, r5 0xCC00 /* r5 has DCE, ICE, ICFI, DCFI set */
92 sync
93 mtspr HID0, r5 /* invalidata both caches with 2 stires */
94 mtspr HID0, r6 /* leaving them both disabled */
95 isync
96
97 mtspr SORG0, r3
98 bl romCkearBATs
99 bl romInvalidateTLBs
100 bl romClear Segs
101 bl romClearFPRegs
102 mfspr r3, SPRG0
103
104 /* Zero-out registers : r0 & SPRGs */
105 xor r0, r0, r0
106 mtspr SPRG0, r0
107 mtspr SPRG1, r0
108 mtspr SPRG2, r0
109 mtspr SPRG3, r0
110
111 /* MSR : clear DCE, ICE, EE, DR, IR –set ME, RI */
112 mfmsr r4
113 ori r4, r0, 0x1002
114 mtmsr r4
115 isync
116
117 /*
118 * initialize the IMMR register before any non-core registers
119 * modification.
120 */
121
122 lis r4, HIADJ(INTERNAL_MEM_MAP_ADDR+0x10000)
123 addi r4, r4, LO(INTERNAL_MEM_MAP_ADDR+0x10000)
124 sync
125
126 lis r5, HIADJ(INTERNAL_MEM_MAP_ADDR)
127 addi r5, r5, LO(INTERNAL_MEM_MAP_ADDR)
128 sync
129
130 stw r5, INIT_IMMR(r4) /* initialize the IMMR register */
131
132 /***********************************************
133 *initialize the SIU.
134 ************************************************/
135
136 bl romSiuInit
137
138 /***********************************************
139 * initialize the MEMC.
140 ************************************************/
141
142 bl romMemcInit
143
144 /************************************************
145 * Initialize Instruction and Data Caches
146 *************************************************/
147
148 bl romCacheInit
149
150 /* initialize the stack pointer */
151
152 lis sp, HIADJ(STACK_ADRS)
153 addi sp, sp, LO(STACK_ADRS)
154
155 /* go to C entry point */
156
157 addi sp, sp, -FRAMEBASESZ /* get frame stack */
158
159 /*
160 * calulate C entry point: rouitine – entry point + ROM base
161 * routine = romStart = R6
162 * entry point = romInit = R7
163 * ROM base = ROM_TEXT_ADRS = R8
164 * C entry point: R6 – R7 + R8
165 */
166
167 lis r7, HIADJ(romInit)
168 addi r6, r6, LO(romStart) /* load R6 with C entry point */
169
170 lis r7, HIADJ(romInit)
171 addi r7, r7, LO(romInit)
172
173 lis r8, HIADJ(ROM_TEXT_ADRS)
174 addi r8, r8, LO(ROM_TEXT_ADRS)
175
176 sub r6, r6, r7 /* routine – entry point */
177 add r6, r6, r8 /* + ROM base */
178
179 mtlr r6 /* move C entry point to LR */
180 blr /* jump to the C entry point */
위의 리스트는 VxWorks 5.5.1 for PowerPC BSP (TDK-14630-ZC-02) CD-ROM 에서 설치한 윈드리버의
wrSbc8260Atm BSP 에 있는 romInit.s 파일의 일부분이다.
이를 완전하게 이해하기 위해서는 PowerPC의 어셈블러 및 MPC8260 CPU의 구조에 대한 이해가 있어야
하지만, 깊은 지식이 없어도 전체적인 과정만 이해한다면 충분할 것이다. 전반적인 흐름에 대한 이해만
갖는다면 다른 종류의 PowerPC 코어나 혹은 전혀 다른 CPU 아키텍쳐에 대해서도 레퍼런스 BSP를
참조해가면서 romInit.s 파일을 수정할 수 있을 것이다.
64 – 65 : 이부분이 전체 vxWorks_rom 이미지의 엔트리 포인트가 된다. 이 특정 BSP의 경우 ROM의
0xfff00100 번지에 위치하게 되며, CPU가 하드웨어 리셋에서 빠져나오면서 처음으로 명령어를 가져가기
시작하는 위치이다. 'romInit' 심볼과 '_romInit 심볼을 사용하고, C 파일과의 링크가 필요한 경우엔 _romInit
심볼이 필요할 경우가 있기 때문이다.
66 – 68 : VxWorks에서는 COLD 부트와 WARM 부트를 구별하는데, 전원의 ON-OFF나 하드웨어 리셋로직에
의한 리셋의 경우엔 당연히 romInit의 엔터리포인트부터 명령을 수행하기 시작하므로 COLD 부트가 된다.
반면에 소프트웨어적인 리부팅의 경우엔, 엔트리포인트로부터 약간의 오프셋을 준 번지로부터 리부팅을
개시하게 된다.
75 – 76 : COLD 부팅의 경우엔 함수 호출시 인자로 사용되는 R3 레지스터에 COLD 부팅임을 알려주는 상수
값을 집어넣는다.
물론 이후로 이 R3레지스터 값은 변경하면 안된다. 이 값은 나중에 romStart( ) 함수에 인자로 전달되어,
메모리 영역의 초기화를 어떻게 할것인가를 결정하는 기준이 된다.
78 : WARM 부팅의 경우, R3 레지스터에 WARM 부팅임을 알려주는 상수값을 따로 셋팅하는 과정이 없는데,
이는 이미 WARM 부팅을 담당하는 소프트웨어에서 적절한 값을 R3 레지스터에 넣어놓고 이쪽으로 분기를
했기 때문이다.
80 – 84 : 보통 외부인터럽트는 CPU가 정상적으로 하드웨어 리셋이 발생했을 경우엔 이미 Disable 되어있을
것이다. 소프트웨어적인 리부팅의 경우에도 대개 인터럽트는 막아놓고 ROM 초기화 코드로 분기를
하게된다. 하지만, 어떤이유에서든 그렇지 않을 경우를 대비해서 가장 먼 너 외부 인터럽트를 막아놓게
된다. 이후에 운영체제가 정상적으로 살아나고 인터럽트를 처리할 준비가 될때까지 인터럽트는 계속 Disable
되어있게된다.
86 – 95 : 외부 인터럽트와 마찬가지로 캐시도 다시한번 확실하게 사용불능으로 만들어 놓는 것이 좋다.
97 – 148 : 여기서는 MPC8260의 여러가지 레지스터 값들을 적절한 값으로 설정을 해 놓는다.
또한 romInit.s 파일에서 어떻게 보면 가장 중요한, 메모리 관련 초기화도 이루어지게 된다.
메모리 컨트롤러는 간단한 칩 셀렉트 머신에서부터 복잡한 타이밍 관련 파라메터들을 셋팅해주어야하는
SDRAM 컨트롤러까지 다양하지만, 이 과정 이후에는 시스템의 RAM을사용할 수 있어야 하는 것이다.
150 – 157 : 위에서 설명한 바와 같이 스택 포인터를 STACK_ADRS라는 값으로 설정을 하는데 이는 결국
RAM_LOW_ADRS 값인 0x0010_0000이 된다. 이 스택 관련 값들이 제대로 셋팅이 되어 있고, 또 위에서
초기화된 RAM들이 제대로 동작을 해 준다면, 이제는 C 함수를 호출할 준비가 된 것이다.
159 – 180 : 이제 bootInit.c 파일에 있는 romStart( )라는 함수를 호출하게 되는데, 여기서 바로 romStart( )
심볼로 점프를 하지 못하고 이렇게 복잡하게 번지를 계산하는 것은, 위에서 설명한 바와 같이 실제
romStart( )함수는 ROM영역에 있지만, 컴파일 할 때 링커가 갖고 있는 번지는 RAM 영역의 번지이기
때문이다. 즉 ,위의 리스트에 나와있듯이, 컴파일시에 링커는 romStart( )함수의 위치가 0x0010078c 번지라고
생각하고 있는데, 이제 겨우 RAM이 초기화된 직후이므로 실제로 RAM의 번지에는 아무런 내용이 없고,
ROM의 0xfff0088c번지에 실제로 romStart( )함수의 코드가 있으므로 그 번지의 값을 계산해서 그곳으로
점프를 하기위한 코드인 것이다.
VxWorks (usrInit 함수의 동작 분석) (0) | 2017.07.05 |
---|---|
VxWorks (romStart( ) 함수의 동작 분석) (0) | 2017.07.05 |
VxWorks C99 버전 변경 (0) | 2017.06.30 |
[VxWorks] 메시지 큐 예제 (0) | 2017.06.30 |
VxWorks (세마포어) (0) | 2017.06.30 |