메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

설계와 구현을 통한 임베디드 OS의 이해와 응용(3) - cuteOS의 시작 부분(1)

한빛미디어

|

2005-12-16

|

by HANBIT

17,697

저자: 서민우
출처: 임베디드월드

* 설계와 구현을 통한 임베디드 OS의 이해와 응용(1) - Overview
* 설계와 구현을 통한 임베디드 OS의 이해와 응용(2) - 개발환경 구성 및 부트로더 작성(1)
* 설계와 구현을 통한 임베디드 OS의 이해와 응용(2) - 개발환경 구성 및 부트로더 작성(2)

이번 기사에서는 부트로더의 나머지 부분과 cuteOS의 시작 부분을 작성해 보기로 하자.

먼저 다음과 같은 순서로 부트로더의 나머지 부분을 작성해 나갈 것이다.

1. FCLK, HCLK, PCLK, UCLK 등 CPU와 주변 버스로 공급되는 clock의 속도를 설정한다.
2. SDRAM 등을 접근하기 위해 메모리 컨트롤러를 초기화 한다.
3. cuteOS 이미지를 RAM 상으로 복사한 후 cuteOS의 시작 위치로 뛴다.

다음으로 cuteOS는 최소한의 어셈블리 파일과 C 파일로 구성한다. 다음과 같은 순서로 cuteOS의 시작 부분을 작성해 나가겠다.

1. C 루틴으로 뛰기 위해 SVC32 mode의 스택을 초기화 한다.
2. C 루틴으로 뛴다.

cuteOS의 본격적인 작성은 다음 호부터 진행하기로 하겠다. 그리고, cache와 MMU 설정 부분도 다음 기사에서 다루기로 하겠다.

먼저 start.S 파일의 나머지 부분은 다음과 같다.

start.S
              …
              mov          r0,#0x00000010
              bl           led_on

              bl           clksetup

              bl           led_off

              mov          r0,#0x00000020
              bl           led_on

              bl           memsetup

              bl           led_off

              mov          r0,#0x00000040
              bl           led_on

osload:
              ldr          r0,_OS_ROM_BASE
              ldr          r1,_OS_RAM_BASE
              ldr          r2,_OS_END

copy_loop:
              ldr          r3,[r0],#4
              str          r3,[r1],#4
              cmp          r0,r2
              blt          copy_loop

              ldr          pc,_OS_RAM_BASE

              .balign      4

_OS_ROM_BASE:
              .word _os_start

_OS_RAM_BASE:
              .word OS_RAM_BASE

_OS_END:
              .word _os_end

그럼 구체적으로 start.S 파일의 나머지 부분을 살펴 보자.

                …
                mov               r0,#0x00000010
                bl                led_on

이 부분은 이전 기사에서 작성했던 start.S 파일의 마지막 부분이다. <1: b 1b> 명령어가 빠졌으니 주의하기 바란다.

                bl                clksetup

여기서는 FCLK, HCLK, PCLK, UCLK 등 CPU와 주변 버스로 공급되는 clock의 속도를 설정하기 위해 clksetup 함수를 호출한다. 이 함수는 clksetup.S 파일에 정의되어 있으며 뒤에서 구체적으로 살펴 보기로 하자.

                bl                 led_off

                mov                r0,#0x00000020
                bl                 led_on

이 부분은 디버깅을 위해 led를 껐다가 두 번째 led를 켜는 부분이다.

                bl                 memsetup

이 부분은 메모리 컨트롤러를 초기화 하기 위해 memsetup 함수를 호출하는 부분이다. 이 함수는 memsetup.S 파일에 정의되어 있으며 역시 뒤에서 구체적으로 살펴 보기로 한다.

                bl                 led_off

                mov                r0,#0x00000040
                bl                 led_on

이 부분은 디버깅을 위해 led를 껐다가 세 번째 led를 켜는 부분이다.

다음은 편의상 파일의 마지막 부분을 먼저 살펴 보겠다.

                .balign                4

이 부분은 이후에 올 코드를 4 바이트 경계에 놓겠다는 어셈블러 지시어이다.

_OS_ROM_BASE:
            .word _os_start

여기서 <.word>는 32 비트 숫자를 정의하는 어셈블러 지시어이다. _os_start는 부트 롬상에서의 cuteOS 이미지의 시작 위치를 나타내며, 뒤에서 보게 될 cute-boot.lds 라는 링커 스크립트 파일에 정의 되어있다.

_OS_RAM_BASE:
            .word OS_RAM_BASE

OS_RAM_BASE는 매크로로써 Makefile에서 0x30100000 번지로 정의해 놓았으며, RAM 상에서 cuteOS가 놓일 시작 위치를 나타낸다. 즉, cuteOS는 물리적으로 0x30100000 번지에 놓이게 된다. Makefile의 내용은 뒤에서 살펴 보기로 하자.

_OS_END:
            .word _os_end

_os_end는 부트 롬상에서의 cuteOS 이미지의 마지막 위치를 나타내며, 역시 cute-boot.lds 링커 스크립트 파일에 정의 되어 있다.

그럼 다시 파일의 앞 부분으로 가 보자.

osload:
            ldr            r0,_OS_ROM_BASE
            ldr            r1,_OS_RAM_BASE
            ldr            r2,_OS_END

이 부분은 r0 레지스터에 부트 롬상에 있는 cuteOS 이미지의 시작주소를, r1 레지스터에 0x30100000 값을, r2 레지스터에 부트 롬상에 있는 cuteOS 이미지의 마지막 주소를 넣는 부분이다.

copy_loop:
            ldr            r3,[r0],#4
            str            r3,[r1],#4
            cmp            r0,r2
            blt            copy_loop

이 부분은 롬상에 있는 cuteOS 이미지를 4 바이트씩 읽어서 램상으로 복사하는 부분이다. cuteOS 이미지의 마지막 부분까지 복사하면 루프를 빠져 나간다.

                ldr                pc,_OS_RAM_BASE

여기서는 램상에 있는 cuteOS로 뛴다. 이로써 부트로더의 역할은 끝나게 된다. cuteOS는 head.S 파일과 main.c 파일로 구성되며 뒤에서 살펴 보기로 한다.

그러면 cute-boot.lds 파일의 내용을 살펴 보기로 하자.

먼저 파일의 내용은 다음과 같다.

cute-boot.lds
OUTPUT_FORMAT("elf32-littlearm","elf32-bigarm","elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
                . = 0x00000000;

                . = ALIGN(4);
                .text : {start.o(.text) *(.text)}

                . = ALIGN(4);
                .rodata : {*(.rodata)}

                . = ALIGN(4);
                .data : {*(EXCLUDE_FILE(cuteOS.bin.o).data)}

                . = ALIGN(4);
                __bss_start = .;
                .bss : {*(.bss)}
                _end = .;

                . = ALIGN(4);
                _os_start = .;
                .cuteOS : {cuteOS.bin.o}
                . = ALIGN(4);
                _os_end = .;
}

cute-boot.lds 파일은 링커 스크립트로써 arm-linux-ld가 최종 결과 파일을 만들어 내는 과정에서 설계도 역할을 한다. 그러면 파일의 내용을 좀 더 자세히 살펴 보자.

OUTPUT_FORMAT("elf32-littlearm","elf32-bigarm","elf32-littlearm")

이 부분은 arm-linux-ld가 만들어 낼 최종 결과 파일의 포맷을 나타낸다. 즉, little endian 포맷의 파일을 생성할 것인지, big endian 포맷의 파일을 생성할 것인지를 결정하는 역할을 한다. 링커 스크립트 내의 키워드는 arm-linux-ld 명령어의 <-EB> 또는 <-EL> 옵션과 같이 사용할 수 있다. 만약 arm-linux-ld 명령어를 <-EB> 옵션과 함께 사용하였다면, 두 번째 항목에 해당하는 포맷의 파일을 생성해 내며(elf32-bigarm), arm-linux-ld 명령어를 <-EL> 옵션과 함께 사용하였다면, 세 번째 항목에 해당하는 파일 포맷을 생성해 낸다(elf32-littlearm). 이 두 옵션을 모두 사용하지 않을 경우 디폴트로 첫 번째 항목에 해당하는 파일 포맷을 생성해 낸다(elf32-littlearm). 여기서는 elf32-littlearm 포맷의 파일을 생성하기로 한다.

OUTPUT_ARCH(arm)

이 부분은 최종 결과 파일이 동작할 CPU의 architecture를 나타낸다. 즉, 이 파일은 ARM CPU 상에서 동작한다는 의미이다.

ENTRY(_start)

최종 결과 파일의 시작 지점을 나타낸다. 즉, 여기서 파일의 시작 지점은 _start가 된다. _start는 start.S 파일에 정의되어 있다.

SECTIONS
{
                …
}

이 부분은 링커(arm-linux-ld)가 입력 파일들의 섹션들을 결과 파일의 어떤 섹션들로 위치시킬지를 결정하는 역할을 한다. 다음의 예를 보자.

.text : {start.o(.text) *(.text)}

이 문장은 start.o 입력 파일의 .text 섹션과 그 외의 입력 파일들(*)의 .text 섹션을 결과 파일의 .text 섹션에 위치 시키는 역할을 한다. 참고로 C 파일을 컴파일하여 오브젝트 파일을 생성할 경우, 기본적으로 함수는 .text 섹션에, 전역 변수는 .data 섹션에, 초기화 되지 않은 전역 변수는 .bss 섹션에 놓인다. 그 외에도 여러 가지 섹션들이 있으며, 또한 새로운 섹션을 정의해서 쓸 수도 있다.

. = 0x00000000;

이 부분은 현재의 위치는 0x00000000 번지라는 의미이다.

. = ALIGN(4);

이 부분은 현재의 위치를 4 바이트 경계에 놓겠다는 의미이다.

.rodata : {*(.rodata)}

이 부분은 모든 입력 파일의 .rodata 섹션을 결과 파일의 .rodata 섹션에 놓겠다는 의미이다.

.data : {*(EXCLUDE_FILE(cuteOS.bin.o).data)}

이 부분은 cuteOS.bin.o 파일을 제외한 모든 입력 파일의 .data 섹션을 결과 파일의 .data 섹션에 놓겠다는 의미이다. cuteOS.bin.o 파일은 cuteOS의 순수 바이너리 이미지이다. cuteOS.bin.o 파일을 만들어 내는 과정은 뒤에서 살펴 보기로 하자.

__bss_start = .;

이 부분은 __bss_start 심벌의 주소 값은 현재 위치와 같다라는 의미이다. arm-linux-nm 명령어를 이용하여 이 부분을 확인해 보기 바란다.

.bss : {*(.bss)}

이 부분은 모든 입력 파일의 .bss 섹션을 결과 파일의 .bss 섹션에 놓겠다는 의미이다.

_os_start = .;
.cuteOS : {cuteOS.bin.o}
. = ALIGN(4);
_os_end = .;

이 부분은 결과 파일의 .cuteOS 섹션에 cuteOS.bin.o 파일을 놓는 역할을 한다. _os_start와 _os_end 심벌이 .cuteOS 섹션의 앞뒤에 오는걸 확인해 볼 수 있다. 즉, _os_start 심벌은 cuteOS 이미지의 시작위치를 나타내며, _os_end 심벌은 cuteOS 이미지의 끝 위치를 나타낸다.

이상에서 링커 스크립트의 내용을 알아 보았다.
TAG :
댓글 입력
자료실

최근 본 상품0