본문 바로가기
dev, tech/embedded

Board initialization / Interrupt handling (스타트업 코드)

by 구띵 2006. 7. 13.

※ 설명이 조금은 부족합니다.

양해바랍니다^^;

 

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개의 인터럽트가 동시에 요청할수 있고 이를 수용할 수 있다

댓글