태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

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

신고

댓글을 달아 주세요

  1. 윤수리 2008.11.01 16:37 신고  댓글주소  수정/삭제  댓글쓰기

    이..이건..ㅋㅋㅋ

About



모바일 페이지 QR 코드

Counter

· Total
: 468,751
· Today
: 103
· Yesterday
: 142


DNS server, DNS service