※ 설명이 조금은 부족합니다.
양해바랍니다^^;
Board initialization
;=========================================
; NAME: 2440INIT.S
; DESC: C start up codes
; Configure memory, ISR ,stacks
; Initialize C-variables
; for education
; HISTORY:
; 2002.02.25:kwtark: ver 0.0
; 2002.03.20:purnnamu: Add some functions for testing STOP,Sleep mode
; 2003.03.14:DonGo: Modified for 2440.
; 2005.01.11:pottery: Modified for Education
;=========================================
GET option.inc // GET : INCLUDE로도 쓸 수 있다
// 어셈블로 옵션 초기화 파일
GET memcfg.inc
// 보드에 장착된 메모리 뱅크와 연관된 장치(device) 초기화 : 메모리 컨트롤러 옵션 초기화
GET 2440addr.inc
// 대부분의 메모리에 맵핑된 컨트롤 레지스터 초기화
BIT_SELFREFRESH EQU (1<<22)
;Pre-defined constants
USERMODE EQU 0x10 // 유저 모드 비트 정의(define)
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
//각 모드의 시작위치 define
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~
MACRO // 메크로 정의 시작
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4
stmfd sp!,{r0}
ldr r0,=$HandleLabel
ldr r0,[r0]
str r0,[sp,#4]
ldmfd sp!,{r0,pc}
MEND // 메크로 정의 끝
// IMPORT : C에서의 extern - 현재의 어셈블리 소스파일에서 만든 레이블을 다른 파일에서 쓰기 위함
IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
//링커가 사용하는 내부변수(컴파일 옵션에서 RO base...)- 링킹하기 위한 실제 정보를 가짐
IMPORT |Image$$RW$$Base| ; Base of RAM to initialise
IMPORT |Image$$ZI$$Base| ; Base and limit of area
IMPORT |Image$$ZI$$Limit| ; to zero initialise
IMPORT Main ; The main entry of mon program
// 메인함수의 시작위치를 가져와 점프
// 섹션시작(area)
AREA Init,CODE,READONLY
ENTRY
//이미지의 첫 위치(entry)
//섹션이름(init), CODE이므로 readonly가 되어야 함
// 현재까지 정의한 옵션들을 토대로, 이미지의 첫 위치(Init)를 삼게 됨
// 바이너리 파일을 만들 때 , 첫 위치가 중요함
// Exception Vector table 초기화
// 실습시에는 RO base : 0x30000000 (SDRAM 영역에 바로 올림)
// 실제 제품 생산시에는 RO base 를 0x0
// 0x0에 4바이트 크기로 2440init.o 의 init섹션이 올라감
// 이는, 0x0 b Reset Handler,
// 0x4 b HandlerUndef,..
// 각 exception 발생시 해당 번지(처리 루틴)로 점프하게 됨
b ResetHandler // 0x0
b HandlerUndef // 0x4
b HandlerSWI //0x8 ...
b HandlerPabort //0x0c
b HandlerDabort//0x10
b .
//0x14 (reserved:구arm core 에서 사용했음) - 0x14번지로 점프 : 무한루프 , 암코어가 제공하는 벡터테이블과 프로그래머가 만드는 벡터테이블을 일치 시키기 위함, 이곳으로 점프하게 된다는 것은 문제가 있다는 것으로 하드웨어적인 버그일 가능성이 높다. 디버깅의 용이성 때문이기도 함.
b HandlerIRQ //0x18
b HandlerFIQ //0x1c
;@0x20
b .
LTORG
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
////// 매크로 호출, 프로그래머의 코딩 작업을 줄여주기 위한것
/*
// 매크로
-> 바뀌는 효과
HandlerIRQ
sub sp,sp,#4 // sp는 IRQ sp,
stmfd sp!,{r0} // r0 백업
ldr r0,=HandleIRQ //
ldr r0,[r0]
str r0,[sp,#4]
ldmfd sp!,{r0,pc}
*/
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9} // 8,9번 백업
// 발생한 인터럽트 번호의 주소 값을 저장
// 9번 watchdog timer
ldr r9,=INTOFFSET
ldr r9,[r9]
// HandleWDT 에 WDT ISR start address 값을 저장
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
;=======
; ENTRY
;=======
ResetHandler
ldr r0,=WTCON ;watch dog disable 자기 자신을 죽일 수 있음
// 2440addr.h 에서 define 된 WTCON
ldr r1,=0x0
str r1,[r0]
ldr r0,=INTMSK
ldr r1,=0xffffffff ;all interrupt disable 초기화하는 과정중에 인터럽트 발생시 죽어 버릴 수 있음->MASK
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x7fff ;all sub interrupt disable
str r1,[r0]
;To reduce PLL lock time, adjust the LOCKTIME register.
// 시스템의 클럭 스피드 초기화
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
ldr r0,=CLKDIVN
ldr r1,=CLKDIV_VAL
str r1,[r0]
;Configure UPLL
ldr r0,=UPLLCON
ldr r1,=((U_MDIV<<12)+(U_PDIV<<4)+U_SDIV)
str r1,[r0]
nop ; Caution: After UPLL setting, at least 7-clocks delay must be inserted for setting hardware be completed.
nop //컴파일러의 슈도코드 : 7 클럭동안 쉬도록 함
nop
nop
nop
nop
nop
;Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) ;Fin=16.9344MHz
str r1,[r0]
;Set memory control registers
//13개의 레지스터를 한번에 셋팅하도록 함
ldr r0,=SMRDATA //r0가 가르키도록 함(DCD...의 첫번째)
// 메모리 컨트롤러를 셋팅하기 위한 상수 값들(13개)을 이용
ldr r1,=BWSCON ;BWSCON Address // 실제 값이 셋팅되어져야할 값을 가르키도록 함
add r2, r0, #52 ;End address of SMRDATA
// 13*3=52, DCD 끝나는 위치를 가르키도록 함
ldr r3, [r0], #4 // 값을 꺼내오고, 값 증가(4)
str r3, [r1], #4 // 4바이트의 데이터를 r1이 가르키고 있는 곳에 저장하고, 값 증가(4)
cmp r2, r0
bne %B0
// 로컬 레이블(%..): 전체 빌드하는 소스 코드 중, 중복된 이름 가능하며, 숫자 0,..1...2로 표시, B 또는 F를 쓸 수 있다. Branch 명령어를 사용한 곳으로부터 backword하면서 0이라는 레이블로 점프하라는 의미, F는 forward
// 13번 순환하며, 실제 레지스터에 집어 넣어음 -> 하나하나씩 셋팅하는 것보다 빠르게 셋팅
//스택 초기화
;Initialize stacks
bl InitStacks //레이블(InitStacks)에서 초기화 하도록 함
; Setup IRQ handler
ldr r0,=HandleIRQ // r14에 해당하는 주소로 점프
ldr r1,=IsrIRQ
str r1,[r0]
///////////////////////////////////////////////////////////////
// 컴파일 후, .axf는 바이너리 + 심볼, 이는 디버깅을 위한 것
// - RO : code영역, RO data영역
// - RW : ZI data영역, RW data영역... 으로 나누어짐
//
//
/////////////복사전///////////////
/*
-------------------
ZI data
zi base ------------------- <-r3 : RW
RW data
rw base =================== <-r1
RO data
r0 limit-> ------------------- <-r0 : RO
CODE
-------------------
*/
//////////////////////////////////
//
//
/*
------------------------------------------------------------------
| #include <stdio.h> |
| int x=100; // 전역변수, 초기화 값 가짐 : RW data |
| int y; // 전역변수, 초기화 값 없음 : ZI data (zero initialize) |
| const int z=1000; // RO data : 변할 필요가 없음 |
| int main() |
| {...} |
| |
| |
------------------------------------------------------------------ : 전체는 CODE
CODE 는 롬 영역(읽기만 해야하므로)
RW 영역(ZI,RW) 는 RAM 영역(읽기 쓰기해야하므로)
개발시:
RO base : 0x3000000
RW base 위치는 RO영역이 끝나는 곳 다음으로 된다.(RW base를 특별히 설정하지 않는 이유)
시판시 : 0x0
RW base : 0x3000000 : 읽고 쓰기를 해야하므로
*/
//////////////////////////////////////////////////////////////
;Copy and paste RW data/zero initialized data
ldr r0, =|Image$$RO$$Limit| ; Get pointer to ROM data
// RO 끝나는 영역, 다음 영역을 가지도록 함(RW영역시작을 가르키도록 함)
ldr r1, =|Image$$RW$$Base| ; and RAM copy
// 컴파일시 설정한 RW base
ldr r3, =|Image$$ZI$$Base|
;Zero init base => top of initialised data
// 복사할 필요가 있는지 검사
cmp r0, r1 ; Check that they are different
beq %F2 // 만족시 2번 레이블로 점프
// cmp는 - 연산
// 참고 : add carry 1, x 0
// 참고 : sub carry 0, x 1
1
cmp r1, r3 ; Copy init data // 복사가 끝났는지 검사
ldrcc r2, [r0], #4 ;--> LDRCC r2, [r0] + ADD r0, r0, #4
strcc r2, [r1], #4 ;--> STRCC r2, [r1] + ADD r1, r1, #4
bcc %B1
// 마지막 워드까지 복사가 끝나면 같은 곳을 가르키게 되며, 루프 종료(r1=r3일때)
2
ldr r1, =|Image$$ZI$$Limit| ; Top of zero init segment
mov r2, #0 // zi data이므로
3
cmp r3, r1 ; Zero init // carry 발생 -> cpsr값 변화
strcc r2, [r3], #4
bcc %B3
// 메인함수 실행 준비 완료
bl Main
b .
/////////////// 기본적인 초기화 과정 종료, C소스 main 에서 기타 사항(인터럽트 처리 등)을 초기화 함
;function initializing stacks
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
//해당하는 모드에서 사용할 스택포인터 할당
mrs r0,cpsr // 상태reg의 값을 가져올때 mrs사용
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack ; UndefStack=0x33FF_5C00
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack ; AbortStack=0x33FF_6000
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack ; IRQStack=0x33FF_7000
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack ; FIQStack=0x33FF_8000
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack ; SVCStack=0x33FF_5800
mov pc,lr // bl명령어 사용한 곳 다음으로 점프
//유저모드는 초기화를 하지 않는다 : 비특권 모드이므로, 직접 cpsr 을 이용해 reg.의 값으로 바꾸지 못한다. 이는 다시 supervisor모드로 빠져나오지 못한다(방법은 있으나 힘들다.안하는게 좋다)
LTORG
SMRDATA DATA
; Memory configuration should be optimized for best performance
; The following parameter is not optimized.
; Memory access cycle parameter strategy
; 1) The memory settings is safe parameters even at HCLK=75Mhz.
; 2) SDRAM refresh period is for HCLK<=75Mhz.
//0x48000000 : BWSCON 레지스터
DCD (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
DCD ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) ;GCS0
DCD ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) ;GCS1
DCD ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) ;GCS2
DCD ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) ;GCS3
DCD ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) ;GCS4
DCD ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) ;GCS5
DCD ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) ;GCS6
DCD ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) ;GCS7
DCD ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Tsrc<<18)+(Tchr<<16)+REFCNT)
DCD 0x32 ;SCLK power saving mode, BANKSIZE 128M/128M
DCD 0x30 ;MRSR6 CL=3clk
DCD 0x30 ;MRSR7 CL=3clk
ALIGN
AREA RamData, DATA, READWRITE
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
// ^ : 4바이트의 빈공간을 만들어 줌 - _ISR_STARTADDRESS라는 이름으로...
// 레이블만 생성됨, 연속된 메모리의 공간이지만...
// HandleReset, HandleUndef,...
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
;IntVectorTable
;@0x33FF_FF20
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleCAM # 4 ; Added for 2440.
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
;@0x33FF_FF60
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleNFCON # 4 ; Added for 2440.
HandleUSBD # 4
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
;@0x33FF_FFA0
END
Interrupt handling
SVC ----------------> IRQ(0x18)--------------------------------------> 되돌아감
( core가 담당 ) (어떤 인터럽트?, ISR : 프로그래머 담당)
s3c2440a:
60개의 인터럽트가 동시에 요청할수 있고 이를 수용할 수 있다
댓글