天天看點

S3C44B0X啟動代碼分析

  44binit.s 引導程式注解   GET option.s ;相當于c語言中的#include "option.s" 

GET memcfg.s  ;Interrupt Control 

;聲明一些符号常量,這些符号常量和位址相應寄存器的位址對應 

INTPND EQU 0x01e00004 ;訓示中斷請求狀态寄存器,每一位代表一種中斷請求,具體表示哪一種中斷請參考44b0 spec 

INTMOD EQU 0x01e00008 ;中斷模式寄存器,有兩種中斷模式對應位為1代表FIQ mode, 0代表IRQ mode 

INTMSK EQU 0x01e0000c ;确定哪個中斷源被屏蔽,屏蔽的中斷源将不被服務 

I_ISPR EQU 0x01e00020 ;中斷服務挂起寄存器 

I_CMST EQU 0x01e0001c ;目前主寄存器IRQ優先級 

;Watchdog timer 

WTCON EQU 0x01d30000 ; 看門狗定時器控制寄存器 ;Clock Controller 

PLLCON EQU 0x01d80000 ; pll 控制寄存器  

CLKCON EQU 0x01d80004 ; 時鐘控制寄存器  

LOCKTIME EQU 0x01d8000c ; 鎖定時間計數值寄存器  

;Memory Controller 

REFRESH EQU 0x01c80024 ; Dram/sdram 重新整理控制寄存器  

; 下面是對 arm 處理器模式寄存器對應值的常數定義, arm 處理器中有一個 CPSR 程式狀态 寄存器,它的後五位決定目前的處理器模式  

;Pre-defined constants 

USERMODE EQU 0x10  ; 0b10000 使用者模式  

FIQMODE EQU 0x11    ; 0b10001 FIQ 模式 

IRQMODE EQU 0x12  ; 0b10010 IRQ 模式  

SVCMODE EQU 0x13  ; 0b10011 管理模式  

ABORTMODE EQU 0x17   ; 0b10111 中止模式  UNDEFMODE EQU 0x1b  ; 0b11011 未定義 

MODEMASK EQU 0x1f  ; 0b11111 系統模式 

NOINT EQU 0xc0 ;  ;check if tasm.exe is used. 

;arm 處理器有兩種工作狀态  1.arm : 32 位,  這種工作狀态下執行字對準的 arm 指令  2.Thumb:16 位,這種工作狀态執行半字對準的 Thumb 指令  

; 因為處理器分為 16 位  32 位兩種工作狀态,程式的編譯器也是分 16 位和 32 兩種編譯方式,  是以下面的程式用于根據處理器工作狀态确定編譯器編譯方式  

;code16 僞指令訓示彙編編譯器後面的指令為 16 位的 thumb 指令  

;code32 僞指令訓示彙編編譯器後面的指令為 32 位的 arm 指令  

; 這段是為了統一目前的處理器工作狀态和軟體編譯方式( 16 位編譯環境使用 tasm.exe 編譯)  

GBLL THUMBCODE  ; 設定 一個全局邏輯變量  

[ {CONFIG} = 16  ; if config==16  這裡表示你的目前處于領先地 16 位編譯方式  

THUMBCODE SETL {TRUE}  ; 設定 THUMBCODE  為  true 

CODE32  ; 轉入 32 位編譯模式  

|  ;else 

THUMBCODE SETL {FALSE}  ; 設 置 THUMBCODE  為  false 

[ THUMBCODE  ; if THUMBCODE==TRUE 

CODE32  ; for start-up code for Thumb mode; 轉入 32 位編譯方式  

; 注意下面這段程式是個宏定義,很多人對這段程式不了解,我再次強調這是一個宏定義, ;是以大家要注意了下面包含的 HandlerXXX HANDLER HandleXXX 将都被下面這段程式 ;展開。  這段程式用于把中斷服務程式的首位址裝載到 pc 中,有人稱之為 “ 加載程式 ” 。 

; 本初始化程式定義了一個資料區(在檔案最後), 34 個字空間,存放相應中斷服務程式的首位址。每個字空間都有一個标号,以 Handle*** 命名。 

; 在向量中斷模式下使用 “ 加載程式 ” 來執行中斷服務程式。 

; 這裡就必須講一下向量中斷模式和非向量中斷模式的概念  

; 向量中斷模式 是當 cpu 讀取位于 0x18 處的 IRQ 中斷指令的時候,系統自動讀取對應于該中斷源确定位址上的指令取代 0x18 處的指令,通過跳轉指令系統就直接跳轉到對應位址  

; 函數中  節省了中斷處理時間提高了中斷處理速度标  例如  ADC 中斷的向量位址為 0xC0, 則在 0xC0 處放如下代碼: ldr PC,=HandlerADC  當 ADC 中斷産生的時候系統會  

; 自動跳轉到 HandlerADC 函數中  

; 非向量中斷模式 處理方式是一種傳統的中斷處理方法,當系統産生中斷的時候,系統将 interrupt pending 寄存器中對應标志位置位,然後跳轉到位于 0x18 處的統一中斷  

; 函數中  該函數通過讀取 interrupt pending 寄存器中對應标志位  來判斷中斷源  并根據優先級關系再跳到對應中斷源的處理代碼中  

MACRO 

$HandlerLabel HANDLER $HandleLabel 

$HandlerLabel 

sub sp,sp,#4  ;decrement sp(to store jump address) 

stmfd sp!,{r0}  ;PUSH the work register to stack  ; 将要使用的 r0 寄存器入棧  

ldr r0,=$HandleLabel ;load the address of HandleXXX to r0 

ldr r0,[r0]  ;load the contents(service routine start address) of HandleXXX 

str r0,[sp,#4]  ;store the contents(ISR) of HandleXXX to stack  ; 将對應的中斷函數首位址入棧  

ldmfd sp!,{r0,pc}  ;POP the work register and pc(jump to ISR) 

; 将中斷函數首位址出棧  放入程式指針中  系統将跳轉到對應中斷處理函數  

MEND 

; 一個 arm 由 RO,RW,ZI 三個段組成,其中 RO 為代碼段, RW 是已經初始化的全局變量, ZI 是未初始化的全局變量(對于 GNU 工具  對應的概念是 TEXT ,DATA,BSS )

;bootloader 要将 RW 段複制到 ram 中并将 ZI 段清零  編譯器使用下列段來記錄各段的起始和結束位址  

; |Image$$RO$$Base| ; RO 段起始位址  

; |Image$$RO$$Limit| ; RO 段結束位址加 1 

; |Image$$RW$$Base| ; RW 段起始位址  

; |Image$$RW$$Limit| ; RW 段結束位址加 1 

; |Image$$ZI$$Base| ; ZI 段起始位址  

; |Image$$ZI$$Limit| ; ZI 段結束位址加 1 

; 這些标号的值是通過編譯器的設定來确定的,如編譯軟體中對 ro-base 和 rw-base 的設定, 例如  ro-base=0xc000000 rw-base=0xc5f0000 

IMPORT |Image$$RO$$Limit|    ; End of ROM code (=start of ROM data) 

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 

; 下面為代碼段 PRESERVE8

AREA Init, CODE, READONLY  ; 異常中斷矢量表(每個表項占 4 個位元組)  下面是中斷向量表,  一旦系統運作時有中斷發生,  即使移植了作業系統,  如 linux  處理器已經把控制權交給了作業系統,  一旦發生中斷處理器還是會跳轉到從 0x0 開始  

; 中斷向量表中某個中斷表項(依據中斷類型)開始執行  

; 具體中斷向量布局請參考 s3c44b0 spec  例如  adc 中斷向量為  0x000000c0 下面對應表中第 49 項位置  向量位址 0x0+4*(49-1)=0x000000c0 

ENTRY 

; 扳子上電和複位後  程式開始從位于 0x0 處開始執行,硬體剛剛上電複位後程式從這裡開始執行跳轉到标号為 ResetHandler 處執行  

b ResetHandler ;for debug 

b HandlerUndef ;handlerUndef 

b HandlerSWI ;SWI interrupt handler 

b HandlerPabort ;handlerPAbort 

b HandlerDabort ;handlerDAbort b . ;handlerReserved 

b HandlerIRQ 

b HandlerFIQ 

;***IMPORTANT NOTE*** 

;If the H/W vectored interrutp mode is enabled, The above two instructions should 

;be changed like below, to work-around with H/W bug of S3C44B0X interrupt controller. 

; b HandlerIRQ -> subs pc,lr,#4 

; b HandlerIRQ -> subs pc,lr,#4 

VECTOR_BRANCH 

ldr pc,=HandlerEINT0 ;mGA H/W interrupt vector table 

ldr pc,=HandlerEINT1 ; 

ldr pc,=HandlerEINT2 ; 

ldr pc,=HandlerEINT3 ; 

ldr pc,=HandlerEINT4567 ; 

ldr pc,=HandlerTICK ;mGA 

b . 

b . 

ldr pc,=HandlerZDMA0 ;mGB 

ldr pc,=HandlerZDMA1 ; 

ldr pc,=HandlerBDMA0 ; 

ldr pc,=HandlerBDMA1 ; 

ldr pc,=HandlerWDT ; 

ldr pc,=HandlerUERR01 ;mGB 

b . 

b . 

ldr pc,=HandlerTIMER0 ;mGC 

ldr pc,=HandlerTIMER1 ; 

ldr pc,=HandlerTIMER2 ; 

ldr pc,=HandlerTIMER3 ; 

ldr pc,=HandlerTIMER4 ; 

ldr pc,=HandlerTIMER5 ;mGC 

b . 

b . 

ldr pc,=HandlerURXD0 ;mGD 

ldr pc,=HandlerURXD1 ; 

ldr pc,=HandlerIIC ; 

ldr pc,=HandlerSIO ; 

ldr pc,=HandlerUTXD0 ; 

ldr pc,=HandlerUTXD1 ;mGD 

b . 

b . 

ldr pc,=HandlerRTC ;mGKA 

b . ; 

b . ; 

b . ; 

b . ; 

b . ;mGKA 

b . 

b . 

ldr pc,=HandlerADC ;mGKB 

b . ; 

b . ; 

b . ; 

b . ; 

b . ;mGKB 

b . 

b . 

;0xe0=EnterPWDN 

ldr pc,=EnterPWDN 

LTORG 

; 下面是具體的中斷處理函數跳轉的宏,通過上面的 $HandlerLabel 的宏定義展開後跳轉到對應的中斷處理函數(對于向量中斷)  

HandlerFIQ HANDLER HandleFIQ 

HandlerIRQ HANDLER HandleIRQ 

HandlerUndef HANDLER HandleUndef 

HandlerSWI HANDLER HandleSWI 

HandlerDabort HANDLER HandleDabort 

HandlerPabort HANDLER HandlePabort 

HandlerADC HANDLER HandleADC 

HandlerRTC HANDLER HandleRTC 

HandlerUTXD1 HANDLER HandleUTXD1 

HandlerUTXD0 HANDLER HandleUTXD0 

HandlerSIO HANDLER HandleSIO 

HandlerIIC HANDLER HandleIIC 

HandlerURXD1 HANDLER HandleURXD1 

HandlerURXD0 HANDLER HandleURXD0 

HandlerTIMER5 HANDLER HandleTIMER5 

HandlerTIMER4 HANDLER HandleTIMER4 

HandlerTIMER3 HANDLER HandleTIMER3 

HandlerTIMER2 HANDLER HandleTIMER2 

HandlerTIMER1 HANDLER HandleTIMER1 

HandlerTIMER0 HANDLER HandleTIMER0 

HandlerUERR01 HANDLER HandleUERR01 

HandlerWDT HANDLER HandleWDT 

HandlerBDMA1 HANDLER HandleBDMA1  HandlerBDMA0 HANDLER HandleBDMA0 

HandlerZDMA1 HANDLER HandleZDMA1 

HandlerZDMA0 HANDLER HandleZDMA0 

HandlerTICK HANDLER HandleTICK 

HandlerEINT4567 HANDLER HandleEINT4567 

HandlerEINT3 HANDLER HandleEINT3 

HandlerEINT2 HANDLER HandleEINT2 

HandlerEINT1 HANDLER HandleEINT1 

HandlerEINT0 HANDLER HandleEINT0  ;One of the following two routines can be used for non-vectored interrupt. 

; 下面這段程式是用來處理非向量中斷,具體判斷 I_ISPR 中各位是否置 1  置 1 表示目前此中斷等待響應(每次隻能有一位置 1 ),從最高優先級中斷位開始判斷,檢測到等待服務  

; 中斷就将 pc 置為中斷服務函數首位址  

IsrIRQ ;using I_ISPR register. 

sub sp,sp,#4 ;reserved for PC 

stmfd sp!,{r8-r9}  ;IMPORTANT CAUTION 

;if I_ISPC isn't used properly, I_ISPR can be 0 in this routine. 

ldr r9,=I_ISPR 

ldr r9,[r9] 

mov r8,#0x0 

movs r9,r9,lsr #1 

bcs %F1 

add r8,r8,#4 

b %B0 

ldr r9,=HandleADC 

add r9,r9,r8 

ldr r9,[r9] 

str r9,[sp,#8] 

ldmfd sp!,{r8-r9,pc} 

;**************************************************** 

;* START * 

;**************************************************** 

; 扳子上電和複位後  程式開始從位于 0x0 執行 b ResetHandler  程式從跳轉到這裡執行  

; 闆子上電複位後  執行幾個步驟這裡通過标号在注釋中加 1 , 2 , 3.... 标示  标号表示執行順序  

;1. 禁止看門狗  屏蔽所有中斷  

ResetHandler 

ldr r0,=WTCON ;watch dog disable 

ldr r1,=0x0 

str r1,[r0] 

ldr r0,=INTMSK 

ldr r1,=0x07ffffff ;all interrupt disable 

str r1,[r0] 

;2. 根據工作頻率設定 PLL ; 這裡介紹一下計算公式  

;Fpllo=(m*Fin)/(p*2^s) 

;m=MDIV+8,p=PDIV+2,s=SDIV 

;Fpllo 必須大于 20Mhz 小于 66Mhz 

;Fpllo*2^s 必須小于 170Mhz 

; 如下面的 PLLCON 設定中的 M_DIV P_DIV S_DIV 是取自 option.h 中  

;#elif (MCLK==40000000) 

;#define PLL_M (0x48) 

;#define PLL_P (0x3) 

;#define PLL_S (0x2) 

; 是以 m=MDIV+8=80,p=PDIV+2=5,s=SDIV=2 

; 硬體使用晶振為 10Mhz, 即 Fin=10Mhz 

;Fpllo=80*10/5*2^2=40Mhz  ;**************************************************** 

;* Set clock control registers * 

;**************************************************** 

ldr r0,=LOCKTIME 

ldr r1,=800 ; count = t_lock * Fin (t_lock=200us, Fin=4MHz) = 800 

str r1,[r0] 

[ PLLONSTART 

ldr r0,=PLLCON ;temporary setting of PLL 

ldr r1,=((M_DIV<<12)+(P_DIV<<4)+S_DIV) ;Fin=10MHz,Fout=40MHz 

str r1,[r0] 

ldr r0,=CLKCON 

ldr r1,=0x7ff8 ;All unit block CLK enable 

str r1,[r0] 

;3. 置存儲相關寄存器的程式  

; 這是設定 SDRAM,flash ROM  存儲器連接配接和工作時序的程式 , 片標明義的程式  

;SMRDATA map 在下面的程式中定義  

;SMRDATA 中涉及的值請參考 memcfg.s 程式  

; 具體寄存器各位含義請參考 s3c44b0 spec  ;**************************************************** 

;* Set memory control registers * 

;**************************************************** 

ldr r0,=SMRDATA 

ldmia r0,{r1-r13} 

ldr r0,=0x01c80000 ;BWSCON Address 

stmia r0,{r1-r13}  4 .初始化堆棧 ;**************************************************** 

;* Initialize stacks * 

;**************************************************** 

ldr sp, =SVCStack ;Why? 

bl InitStacks 

;5. 設定預設中斷處理函數  

;**************************************************** 

;* Setup IRQ handler * 

;**************************************************** 

ldr r0,=HandleIRQ ;This routine is needed 

ldr r1,=IsrIRQ ;if there isn't 'subs pc,lr,#4' at 0x18, 0x1c 

str r1,[r0] 

;6. 将資料段拷貝到 ram 中  将零初始化資料段清零  跳入 C 語言的 main 函數執行  到這步結束 bootloader 初步引導結束  

;******************************************************** 

;* Copy and paste RW data/zero initialized data * 

;******************************************************** 

LDR r0, =|Image$$RO$$Limit| ; Get pointer to ROM data 

LDR r1, =|Image$$RW$$Base| ; and RAM copy 

LDR r3, =|Image$$ZI$$Base| 

;Zero init base => top of initialised data 

CMP r0, r1 ; Check that they are different 

BEQ %F1 

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 %B0 

LDR r1, =|Image$$ZI$$Limit| ; Top of zero init segment 

MOV r2, #0 

CMP r3, r1 ; Zero init 

STRCC r2, [r3], #4 

BCC %B2  [ :LNOT:THUMBCODE 

BL Main ;Don't use main() because ......; 跳入 main 函數  

B . 

[ THUMBCODE ;for start-up code for Thumb mode 

orr lr,pc,#1 

bx lr 

CODE16 

bl Main ;Don't use main() because ......; 跳入 main 函數  

b . 

CODE32 

;7.初始化各模式下的棧指針 

;**************************************************** 

;* The function for initializing stack * 

;**************************************************** 

InitStacks 

;Don't use DRAM,such as stmfd,ldmfd...... 

;SVCstack is initialized before 

;Under toolkit ver 2.50, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1' 

mrs r0,cpsr 

bic r0,r0,#MODEMASK 

orr r1,r0,#UNDEFMODE|NOINT 

msr cpsr_cxsf,r1 ;UndefMode 

ldr sp,=UndefStack 

orr r1,r0,#ABORTMODE|NOINT 

msr cpsr_cxsf,r1 ;AbortMode 

ldr sp,=AbortStack 

orr r1,r0,#IRQMODE|NOINT 

msr cpsr_cxsf,r1 ;IRQMode 

ldr sp,=IRQStack 

orr r1,r0,#FIQMODE|NOINT 

msr cpsr_cxsf,r1 ;FIQMode 

ldr sp,=FIQStack 

bic r0,r0,#MODEMASK|NOINT 

orr r1,r0,#SVCMODE 

msr cpsr_cxsf,r1 ;SVCMode 

ldr sp,=SVCStack 

;USER mode is not initialized. 

mov pc,lr  ;The LR register may be not valid for the mode changes. 

;下面是pwdn模式下的相關寄存器的定義 

;**************************************************** 

;* The function for entering power down mode * 

;**************************************************** 

;void EnterPWDN(int CLKCON); 

EnterPWDN 

mov r2,r0 ;r0=CLKCON 

ldr r0,=REFRESH 

ldr r3,[r0] 

mov r1, r3 

orr r1, r1, #0x400000 ;self-refresh enable 

str r1, [r0] 

nop ;Wait until self-refresh is issued. May not be needed. 

nop ;If the other bus master holds the bus, ... 

nop ; mov r0, r0 

nop 

nop 

nop 

nop 

;enter POWERDN mode 

ldr r0,=CLKCON 

str r2,[r0] 

;wait until enter SL_IDLE,STOP mode and until wake-up 

mov r0,#0xff 

0 subs r0,r0,#1 

bne %B0 

;exit from DRAM/SDRAM self refresh mode. 

ldr r0,=REFRESH 

str r3,[r0] 

mov pc,lr 

LTORG 

;這是上面提到的對存儲寄存器初始化的資料map 

SMRDATA DATA 

;***************************************************************** 

;* Memory configuration has to be optimized for best performance * 

;* The following parameter is not optimized. * 

;***************************************************************** 

;*** memory access cycle parameter strategy *** 

; 1) Even FP-DRAM, EDO setting has more late fetch point by half-clock 

; 2) The memory settings,here, are made the safe parameters even at 66Mhz. 

; 3) FP-DRAM Parameters:tRCD=3 for tRAC, tcas=2 for pad delay, tcp=2 for bus load. 

; 4) DRAM refresh rate is for 40Mhz. 

DCD 0x11110090 ;Bank0=OM[1:0], Bank1~Bank7=16bit, bank2=8bit; 

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)+(Trc<<18)+(Tchr<<16)+REFCNT) ;REFRESH RFEN=1, TREFMD=0, trp=3clk, trc=5clk, tchr=3clk,count=1019 

DCD 0x16 ;SCLK power mode, BANKSIZE 32M/32M 

DCD 0x20 ;MRSR6 CL=2clk 

DCD 0x20 ;MRSR7 

ALIGN 

;下面是對ram區域map的定義 

AREA RamData, DATA, READWRITE 

;這裡定義了處理器工作于各模式的堆棧區在ram中map 

^ (_ISR_STARTADDRESS-0x500) 

UserStack # 256 ;c1(c7)ffa00 

SVCStack # 256 ;c1(c7)ffb00 

UndefStack # 256 ;c1(c7)ffc00 

AbortStack # 256 ;c1(c7)ffd00 

IRQStack # 256 ;c1(c7)ffe00 

FIQStack # 0 ;c1(c7)fff00 

;這裡将中斷異常向量建立在sdram中 

^ _ISR_STARTADDRESS 

HandleReset # 4 

HandleUndef # 4 

HandleSWI # 4 

HandlePabort # 4 

HandleDabort # 4 

HandleReserved # 4 

HandleIRQ # 4 

HandleFIQ # 4 

;Don't use the label 'IntVectorTable', 

;because armasm.exe cann't recognize this label correctly. 

;the value is different with an address you think it may be. 

;IntVectorTable 

HandleADC # 4 

HandleRTC # 4 

HandleUTXD1 # 4 

HandleUTXD0 # 4 

HandleSIO # 4 

HandleIIC # 4 

HandleURXD1 # 4 

HandleURXD0 # 4 

HandleTIMER5 # 4 

HandleTIMER4 # 4 

HandleTIMER3 # 4 

HandleTIMER2 # 4 

HandleTIMER1 # 4 

HandleTIMER0 # 4 

HandleUERR01 # 4 

HandleWDT # 4 

HandleBDMA1 # 4 

HandleBDMA0 # 4 

HandleZDMA1 # 4 

HandleZDMA0 # 4 

HandleTICK # 4 

HandleEINT4567 # 4 

HandleEINT3 # 4 

HandleEINT2 # 4 

HandleEINT1 # 4 

HandleEINT0 # 4 ;0xc1(c7)fff84  END   =============================================================================== ==    From: http://www.mcu123.com/news/Article/ARMsource/ARM/200610/2740.html                                  ==   Date : 2006.11.8                                                          ==   Other:                                                                    ===============================================================================    

繼續閱讀