ARM s3c2440 스타트업 코드
Posted on 2007/09/27 20:38
Filed Under Linux/Embedded
신뢰도 50% ㅡ_ㅡ;
틀린게 있을때는 과감히 태클 요망
;=========================================
; NAME: 2410INIT.S
; DESC: C start up codes
; Configure memory, ISR ,stacks
; Initialize C-variables
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,POWER_OFF mode
; 2003.05.19:jcs: Configure UPLL in init.s not usbmain.c
; 2005.01.08:kimingoo@hotmail.com: 강의용으로 최대한 간략화 시킴
; 2005.04.01:kagekiri@gbtec.co.kr: 2410init.s based S3C2440A initial asm
;=========================================
;Start address of Exception & ISR vector table
_ISR_STARTADDRESS EQU 0x33ffff00
;Start address of each stacks
_STACK_BASEADDRESS EQU 0x33ff8000
;=================
; WATCH DOG TIMER
;=================
WTCON EQU 0x53000000
;==========================
; CLOCK & POWER MANAGEMENT
;==========================
MPLLCON EQU 0x4c000004
LOCKTIME EQU 0x4c000000
;=================
; INTERRUPT
;=================
INTSUBMSK EQU 0x4a00001c
INTOFFSET EQU 0x4a000014
INTMSK EQU 0x4a000008
;=================
; Memory control
;=================
BWSCON EQU 0x48000000
; Pre-defined constants
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1b
MODEMASK EQU 0x1f
NOINT EQU 0xc0
; The location of stacks
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff-4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff-5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff-5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff-6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff-7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff-8000 ~
;----------------------------------------------------
IMPORT |Image$$RO$$Limit|
IMPORT |Image$$RW$$Base|
IMPORT |Image$$ZI$$Base|
IMPORT |Image$$ZI$$Limit|
IMPORT Main
AREA Init,CODE,READONLY
ENTRY
;----------------------------------------------------
; Exception handler(part1)
b ResetHandler
b HandlerUndef
b HandlerSWI
b HandlerPabort
b HandlerDabort
b .
b HandlerIRQ
b HandlerFIQ
; Exception handler(part2)
HandlerFIQ
sub sp, sp, #4 ;분기할 주소를 PC에 넣기 위해 스택 하이어드레스 먼저 비움
stmfd sp!, {r0} ;R0 를 백업
ldr r0, =HandleFIQ ;r0에 HandleFIQ 레이블의 주소를 가져옴
ldr r0, [r0] ;HandleFIQ 레이블 안의 4바이트 공간의 주소값을 r0에 가져옴
str r0, [sp, #4] ;현재 가르키고 있는 스택포인트에서 4를 더해 아까전에 PC를 위해 비운 곳에 r0를 넣음
ldmfd sp!, {r0, pc} ;스택을 팝시켜 r0와 pc 에 가져옴 (분기)
;이하 동일한 내용의 반복. 각각의 익셉션에 해당하는 실제 처리루틴을 연결함
HandlerIRQ
sub sp, sp, #4
stmfd sp!, {r0}
ldr r0, =HandleIRQ
ldr r0, [r0]
str r0, [sp, #4]
ldmfd sp!, {r0, pc}
HandlerUndef
sub sp, sp, #4
stmfd sp!, {r0}
ldr r0, =HandleUndef
ldr r0, [r0]
str r0, [sp, #4]
ldmfd sp!, {r0, pc}
HandlerSWI
sub sp, sp, #4
stmfd sp!, {r0}
ldr r0, =HandleSWI
ldr r0, [r0]
str r0, [sp, #4]
ldmfd sp!, {r0, pc}
HandlerDabort
sub sp, sp, #4
stmfd sp!, {r0}
ldr r0, =HandleDabort
ldr r0, [r0]
str r0, [sp, #4]
ldmfd sp!, {r0, pc}
HandlerPabort
sub sp, sp, #4
stmfd sp!, {r0}
ldr r0, =HandlePabort
ldr r0, [r0]
str r0, [sp, #4]
ldmfd sp!, {r0, pc}
;=======
; ENTRY
;=======
ResetHandler
;-----------------------------------------------
; Disable watchdog Timer
;-----------------------------------------------
ldr r0, =WTCON ;와치독컨트롤영역의 메모리 주소를 r0로 가져옴
ldr r1, =0x0 ;r1 에 0을 넣음
str r1, [r0] ;r1 을 와치독컨트롤영역에 넣음(모든비트를 0으로 초기화 하여 와치독을 정지)
;-----------------------------------------------
; Disable all interrupts
;-----------------------------------------------
ldr r0, =INTMSK ;인터럽트 마스크 영역의 메모리 주소를 r0로 가져옴
ldr r1, =0xffffffff ;r1에 32비트를 모두 1로 채운 값을 넣음
str r1, [r0] ;r1을 인터럽트 마스크 영역에 넣음(1:Disable,0:Enable 즉 1로 초기화 하여 모든 인터럽트 접근을 금지)
;서브 인터럽트 마스킹 - 없어도 상관없다고 생각됩니다. 메인인터럽트가 마스크되면 서브인터럽트 마스크도 발생해도 결국 마스킹되기 때문에.
ldr r0, =INTSUBMSK ;인터럽트 서브 마스크 영역의 메모리 주소를 r0로 가져옴
ldr r1, =0x7fff ;r1에 15비트를 모두 1로 채운 값을 넣음
str r1, [r0] ;r1을 인터럽트 서브 마스크 영역에 넣음(1:Disable,0:Enable)
;-----------------------------------------------
; Clock initialization
;-----------------------------------------------
ldr r0, =LOCKTIME ;LOCKTIME 영역의 메모리 주소를 r0로 가져옴
ldr r1, =0xffffffff ;r1에 32비트를 모두 1로 채운 값을 넣음
str r1, [r0] ;r1의 값을 LOCKTOME 영역에 넣음
ldr r0, =MPLLCON ;MPLLCON 영역의 메모리 주소를 r0로 가져옴
ldr r1, =((0x38 << 12) + (0x2 << 4) + 0x2) ;Fin=12MHz,Fout= 48MHz ;MPLL을 48Mhz 로 설정
str r1, [r0] ;설정된 값을 MPLLCON 영역에 넣음
;-----------------------------------------------
; Set memory control registers
;-----------------------------------------------
bl InitMemoryController ;메모리 컨트롤러 분기
;-----------------------------------------------
; Initialize stacks
;-----------------------------------------------
bl InitStacks ;스택 초기화 분기
;-----------------------------------------------
; Setup IRQ handler
;-----------------------------------------------
ldr r0, =HandleIRQ ;r0에 HandleIRQ 레이블의 주소를 가져온다.
ldr r1, =IsrIRQ ;r1에 IsrIRQ 레이블의 주소를 가져온다.
str r1, [r0] ;IsrIRQ 주소를 HandleIRQ 영역에 넣음 (실제 처리루틴을 핸들과 연결)
;-----------------------------------------------
; Initialization RW/ZI data area
;-----------------------------------------------
bl InitRWZI ;ReadWrite/Zero Initialize 영역 초기화 분기
;-----------------------------------------------
; Call Main()
;-----------------------------------------------
bl Main ; Main 으로 분기
b .
;----------------------------------------------------
InitMemoryController
ldr r0, =SMRDATA ;SMRDATA 레이블의 주소를 r0에 넣음
ldr r1, =BWSCON ; BWSCON (0x4800-0000) - BWSCON의 메모리주소를 r1에 넣음
add r2, r0, #52 ; End address of SMRDATA - 메모리컨트롤러부 13개, 13*4=52, 즉 r2에 마지막 주소를 저장
0
ldr r3, [r0], #4 ; 포스트인덱싱으로 r3에 SMRDATA의 값을 가져온 후 4바이트 증감
str r3, [r1], #4 ; r3 를 BWSCON영역에 넣음
cmp r2, r0 ; SMRDATA 메모리의 마지막 주소와 현재 가져온 다음의 SMRDATA 주소를 비교
bne %B0 ; 같지 않다면 앞쪽에 있는 레이블0으로 분기
mov pc, lr ; 같다면 링크레지스터를 pc 에 넣고 호출했던곳으로 복귀
;----------------------------------------------------
InitStacks
mrs r0, cpsr ;cpsr을 r0로 가져온다.
bic r0, r0, #MODEMASK ;r0에서 모드비트(하위 5개비트)를 0으로 초기화시킴.
orr r1, r0, #UNDEFMODE|NOINT ;현재 r0값을 UNDEFINE모드 설정과 IRQ,FIQ비트를 Disable 하여 r1에 넣음
msr cpsr_cxsf, r1 ;CPSR 의 cxsf 플래그 (즉 전체) 에 r1값을 넣음 (모드전환)
ldr sp, =UndefStack ;스택포인터에는 UndefStack (해당 모드 스택의 베이스 어드레스) 를 넣는다.
orr r1, r0, #ABORTMODE|NOINT ;이하 모드 전환을 하며 같은 작업을 반복한다.
msr cpsr_cxsf, r1
ldr sp, =AbortStack
orr r1, r0, #IRQMODE|NOINT
msr cpsr_cxsf, r1
ldr sp, =IRQStack
orr r1, r0, #FIQMODE|NOINT
msr cpsr_cxsf, r1
ldr sp, =FIQStack
bic r0, r0, #MODEMASK|NOINT
orr r1, r0, #SVCMODE
msr cpsr_cxsf, r1
ldr sp, =SVCStack
;USER mode has not be initialized. ;유저모드로 들어가면 사용자 개입이 없는한 다른 모드로 복귀가 불가능
mov pc, lr ;링크레지스터를 pc에 넣고 복귀
;----------------------------------------------------
InitRWZI
ldr r0, =|Image$$RO$$Limit| ;RO영역의 Limit 주소를 r0에 가져옴
ldr r1, =|Image$$RW$$Base| ;RW영역의 Base 주소를 r1에 가져옴
ldr r3, =|Image$$ZI$$Base| ;ZI영역의 Base 주소를 r3에 가져옴
cmp r0, r1 ;r0와 r1을 비교(RO_Limit 와 RW_Base영역)
beq %F2 ;같다면 다음에 있는 2번레이블로 분기 (두주소가 같다면 RW영역의 데이터는 없다)
1
cmp r1, r3 ;r1과 r3을 비교(RW_Base 와 ZI_Base)
ldrcc r2, [r0], #4 ;!!!!!감산연산은 캐리(내림수)가 발생하면 캐리비트가 0으로 셋트된다. 즉 r1<r3 일경우 r2에 RW데이터를 가져온후 주소 증가
strcc r2, [r1], #4 ; r2를 RW_Base 영역에 넣음. (롬영역의 데이터를 램영역으로 올림)
bcc %B1 ; 이전의 1번 레이블로 분기
2
ldr r1, =|Image$$ZI$$Limit| ;r1에 ZI_Limit 주소를 가져옴
mov r2, #0 ;r2에 0을 대입
3
cmp r3, r1 ;ZI_Base 와 Zi_Limit 를 비교
strcc r2, [r3], #4 ;ZI_Base<ZI_Limit 라면 ZI영역의 변수가 존재하므로 0으로 초기화시킴
bcc %B3 ;그리고 이전 3번레이블로 분기
mov pc, lr ;링크레지스터를 pc 에 넣고 복귀
;----------------------------------------------------
IsrIRQ
sub sp, sp, #4 ; 이후 분기될 영역의 주소를 pc 에 넣기 위해 4바이트의 스택을 비우고 다음 영역에 스택포인터를 위치
stmfd sp!, {r8-r9} ; r8와 r9를 백업
ldr r9, =INTOFFSET ; INTOFFSET (0x4a00-0014) - 인터럽트가 들어올때 받는값, if) WDT - 9
ldr r9, [r9] ; INTOFFSET 안의 값을 r9로 가져옴 - 실제 인터럽트 종류를 알아냄
ldr r8, =HandleEINT0 ; HandleEINT0(실제 ISR 의 베이스 어드레스 정도?) 주소를 r8에 넣음
add r8, r8, r9, lsl #2 ; 인터럽트 오프셋의 값을 좌로 두번 쉬프트 하여 ISR 베이스 어드레스와 더함(하나의 명령어는 32비트이기 때문에 *4의 목적)
ldr r8, [r8] ; 해당인터럽트에 해당하는 ISR 주소가 가지고 있는 실제 처리루틴의 주소를 가져옴
str r8, [sp, #8] ; 그 주소를 이전에 pc값으로 넣기 위해 비워뒀던 스택영역에 넣음
ldmfd sp!, {r8-r9, pc} ; 현재 스택포인터의 값을 팝 시켜 해당 인터럽트 ISR 루틴으로 분기
;----------------------------------------------------
SMRDATA DATA
DCD 0x22111120 ; BWSCON (0x4800-0000)
DCD 0x00000700 ; BANKCON0 (0x4800-0004)
DCD 0x00000700 ; BANKCON1 (0x4800-0008)
DCD 0x00000700 ; BANKCON2 (0x4800-000c)
DCD 0x00000700 ; BANKCON3 (0x4800-0010)
DCD 0x00000700 ; BANKCON4 (0x4800-0014)
DCD 0x00000700 ; BANKCON5 (0x4800-0018)
DCD 0x00018005 ; BANKCON6 (0x4800-001c)
DCD 0x00018005 ; BANKCON7 (0x4800-0020)
DCD 0x008e0459 ; REFRESH (0x4800-0024)
DCD 0x00000032 ; BANKSIZE (0x4800-0028)
DCD 0x00000030 ; MRSR6 (0x4800-002c)
DCD 0x00000030 ; MRSR7 (0x4800-0030)
;----------------------------------------------------
AREA RamData, DATA, READWRITE
; Exception handler(part3)
^ _ISR_STARTADDRESS
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT_AC97 # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
END
'Linux/Embedded' 카테고리의 다른 글
| mtd-utils 크로스 컴파일 하기 (0) | 2010/12/17 |
|---|---|
| Makefile: *** mixed implicit and normal rules. Stop. 메시지 해결법 (3) | 2010/11/17 |
| 우분투 환경에서 Kdevelop 쉽게 설치하기 (0) | 2010/10/14 |
| ARM s3c2440 스타트업 코드 (2) | 2007/09/27 |
| Watchdog note (0) | 2007/09/27 |




댓글을 달아 주세요
윤수리 2008/11/01 16:37 댓글주소 수정/삭제 댓글쓰기
이..이건..ㅋㅋㅋ
ㅋㅋㅋㅋ
예전에 교육때 자료죠.
ㅡ,.ㅡ;