오후 12:36 2006-04-26
arm boot
조경민 bro@shinbiro.com
http://neri.cafe24.com
============================================================

;=====================================================
; boot test
; by bro, bro@shinbiro.com 오전 10:23 2006-04-26
;
; armasm main.s -o main.o
; armlink main.o --ro-base 0x0 -o main.axf
;=====================================================

        AREA boot, CODE, READONLY
        ENTRY
vector                                ; 인터럽트 벡터 테이블
        b        reset                 ; 주소 0번지에 reset 인터럽트가 오면 바로 reset레이블로 점프
        b        error                 ; undefined_instruction
        b        error                 ; software_interrupt
        b        error                 ; prefetch_abort
        b        error                 ; data_abort
        b        error                 ; not_used
        b        error                 ; IRQ
        b        error                 ; FIQ

error
        b        error

reset
        ; 현재 모드에서 IRQ|FIQ를 끈다.
        mrs     r0, CPSR                ; 현재 상태 얻어옴
        bic     r0, r0, #0x1f                ; 모드 클리어
        orr     r0, r0, #(0x13 | 0xc0)        ; 0x13(0001 0011) | 0xC0 (1101 0000) = 0xD3(1101 0011)
        msr     CPSR_cxsf, r0                ; 현재 상태 저장
        ; 괜히 r0를 1로 만든다.
        mov        r0, #1
        ; 소프트 인터럽트를 발생시켜본다. (x86 vc의 __asm int 30과 동일)
        ; swi        30
        ; 스택 초기화        0x9000
        mov        sp, #0x9000
        ; 함수 호출
        bl        sub
        ; 종료
        b        end
sub
        stmfd        sp!, {r0-r12,lr}
        mov        r0, #3
        ldmfd        sp!, {r0-r12,pc}
end
        END
-----------------------------------------------------------------------------

본 소스는 부팅부터 시작함을 의미하기 때문에 0x0 번지부터 시작하도록
링킹을 해야 한다.
또한 -G 옵션을 주면 AXD Debugger로 디버깅시 main.s 소스 레벨 디버깅이 가능하다.

armasm main.s -G -o main.o
armlink main.o --ro-base 0x0 -o main.axf

시작하자 마자 여러 주변 장치에서 발생되는 IRQ(인터럽트)가 발생될 수 있다.
일단 이것부터 꺼놓고 시작해야 한다.

        mrs     r0, CPSR
        bic     r0, r0, #0x1f
        orr     r0, r0, #(0x13 | 0xc0)        ; 0x13(0001 0011) | 0xC0 (1101 0000) = 0xD3(1101 0011)
        msr     CPSR_cxsf, r0

mrs r0, CPSR을 통해서 CPSR 의 값을 읽는다. CPSR은 아래와 같다.

CPSR(Current Program State Register)
31    28 27                       8 7 6 5 4  0
+---------------------------------------------+
|N Z C V                            I F T mode|
+---------------------------------------------+

N: Negative로 ALU 수행 결과가 음수인 경우 1로 변함
Z: Zero로 ALU 결과가 0이면 1로 변함
C: Carry로 ALU 결과 또는 shift 수행 결과에 의해 carry 출력이 발생하면 1로 변함
V: oVerflow로 산술 연산 결과 값이 너무 커 sign bit를 연산 결과가 침범하면 1로 변함
I: IRQ를 금지하면 1로 설정됨
F: FIQ를 금지하면 1로 설정됨
T: Thumb 모드이면 1로 설정됨
mode[4:0] 5비트는 ARM의 user, fiq, svc, abort, irq, undefined 모드로 6가지 중 하나
                  10011는 svc 모드를 의미

다음 bic r0, r0, #0x1f를 통해서 r0 = r0 & ~(0x1f)를 한다. 즉 [4:0] 모드비트들을 0으로 클리어하고

ex) CPSR의 최상위 4비트를 0으로 셋
mrs R0, CPSR
bic R0, R0, #0xF0000000 ; 0 의 갯수가 항상 6개 이상이어야 한다... 0xf1100000 은 안됨

orr r0, r0, #(0x13 | 0xc0) 즉 orr r0, r0, #0xD3를 통해서 [4:0] 1 0011로 svc모드로
[7:5]비트는 110로 IRQ는 1, FIQ는 1, Thumb은 0, 즉 IFt이다.
그런후, msr CPSR_cxsf, r0 로 CPSR에 svc모드면서 IFt를 적용하게 된다.

스택 레지스터 sp (r13)을 사용하기 전에는 사용할 공간을 잘 머리속에 메모리 맵을
구상하면서 정해야한다. 현재는 0x9000번지를 stack top으로 정하였으며 스택은
stmfd (full decending)이므로 하위 주소로 자란다.

서브 함수
서브 함수는 bl로 호출하게 된다. 서브함수 시작시

sub함수
        stmfd        sp!, {r0-r12,lr}
              :
        ldmfd        sp!, {r0-r12,pc}
를 두면 r0부터 r12까지의 레지스터를 스택에 관리하고 리턴 lr도 저장한 후,
ldmfd 에서 lr값을 pc에 넣어 복귀할 수 있도록 한다.

'KB > embbeded sw' 카테고리의 다른 글

arm-4: 커널 영역 올리기  (0) 2006.04.27
arm-3 : c코드로 점프~  (0) 2006.04.26
arm-1: ADS로 ARM 공부 add  (0) 2006.04.25
arm-0: Armulator 사용하기  (0) 2006.04.25
MPSoC 관련  (0) 2006.04.11

+ Recent posts