1. 程式人生 > >S3C2440的Keil啟動檔案S3C2440.s新增中斷配置

S3C2440的Keil啟動檔案S3C2440.s新增中斷配置

參考文件

前言

本文主要描述如何在Keil自帶的S3C2440.s檔案中新增中斷配置及中斷地址對映,從而可以在中斷產生時跳轉到使用者程式碼中的中斷服務函式。目前在TQ2440開發板是實測可用。

本文所有程式碼都是擷取程式碼,“…”代表其還有上下文。可根據程式碼中上下文的殘缺部分找到該程式碼新增的位置。

一,新增中斷相關暫存器地址符號對映

因為原始S3C2440.s檔案中不含中斷相關暫存器的地址,所以需要在開頭新增:

...

; *  RAM_INTVEC: when set the startup code copies exception vectors 
; *  from execution address to on-chip RAM.
; */


;=================
; INTERRUPT
;=================
SRCPND      EQU  0x4a000000
;Interrupt request status INTMOD EQU 0x4a000004 ;Interrupt mode control INTMSK EQU 0x4a000008 ;Interrupt mask control PRIORITY EQU 0x4a00000c ;IRQ priority control <-- May 06, 2002 SOP INTPND EQU 0x4a000010 ;Interrupt request status INTOFFSET EQU 0x4a000014 ;Interruot request source
offset SUSSRCPND EQU 0x4a000018 ;Sub source pending INTSUBMSK EQU 0x4a00001c ;Interrupt sub mask _ISR_STARTADDRESS EQU 0x33ffff00 ; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs Mode_USR EQU 0x10 Mode_FIQ EQU 0x11 Mode_IRQ EQU 0x12 ...

二,新增中斷向量偏移表

在檔案末尾新增中斷向量表,對應2440addr.h檔案中相應的中斷向量地址,起始地址參見_ISR_STARTADDRESS

...

                LDR     R2, = (Heap_Mem +      Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR
                ENDIF

ALIGN

    AREA RamData, DATA, READWRITE

    ^   _ISR_STARTADDRESS       ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset     #   4
HandleUndef     #   4
HandleSWI       #   4
HandlePabort    #   4
HandleDabort    #   4
HandleReserved  #   4
HandleIRQ       #   4
HandleFIQ       #   4

;Do not use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;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

三,新增程式__ENTRY入口點

定義程式入口點的位置,在ram除錯狀態下,就是0x30000000對應的Reset Handler的跳轉程式碼。

...


;  Mapped to Address 0.
;  Absolute addressing mode must be used.
;  Dummy Handlers are implemented as infinite loops which can be modified.

                EXPORT __ENTRY
__ENTRY

Vectors         LDR     PC, Reset_Addr         
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr

...

四,修改新增中斷現場保護及跳轉程式碼

除了IRQ中斷以外的所有中斷的現場保護及跳轉程式碼,因為這些中斷在向量表都只有一種狀態,所以不需要偏移。這裡是巨集定義的實際程式碼,巨集定義的呼叫見五,修改新增IRQ中斷現場保護及跳轉程式碼中的程式碼。

...

GPJCON_Val      EQU     0x00000000
GPJUP_Val       EQU     0x00000000

;// </e> I/O Setup‘

        MACRO
$HandlerLabel HANDLER $HandleLabel

$HandlerLabel
    sub sp,sp,#4    ;decrement sp(to store jump address)
    stmfd   sp!,{r0}    ;PUSH the work register to stack(lr does not push because it return to original address)
    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

;----------------------- CODE --------------------------------------------------

                PRESERVE8


; Area Definition and Entry Point
;  Startup Code must be linked first at Address at which it expects to run.

...

五,修改新增IRQ中斷現場保護及跳轉程式碼

IRQ中斷的現場保護及跳轉程式碼。IRQ中斷有很多可能,比如按鍵的外部中斷,串列埠中斷,IIC中斷。。。等,需要根據實際中斷標誌指示跳轉到對應的服務函式,所以需要一套獨立的中斷處理程式碼。此處程式碼來自《mini2440—–keil for ARM之中斷一》。

...

                ELSE
IRQ_Addr        DCD     IRQ_Handler
                ENDIF
FIQ_Addr        DCD     FIQ_Handler

;Undef_Handler   B       Undef_Handler
                ;IF      :DEF:__RTX
                ;ELSE
;SWI_Handler     B       SWI_Handler
                ;ENDIF
;PAbt_Handler    B       PAbt_Handler
;DAbt_Handler    B       DAbt_Handler
;IRQ_Handler     PROC
                ;EXPORT  IRQ_Handler               [WEAK]
                ;B       .
                ;ENDP
;FIQ_Handler     B       FIQ_Handler

FIQ_Handler     HANDLER HandleFIQ
HandlerIRQ      HANDLER HandleIRQ
Undef_Handler   HANDLER HandleUndef
SWI_Handler     HANDLER HandleSWI
DAbt_Handler    HANDLER HandleDabort
PAbt_Handler    HANDLER HandlePabort

;呵呵,來了來了.好戲來了,這一段程式就是用來進行第二次查表的過程了.
;如果說第一次查表是由硬體來完成的,那這一次查表就是由軟體來實現的了.
;為什麼要查兩次表??
;沒有辦法,ARM把所有的中斷都歸納成一個IRQ中斷異常和一個FIRQ中斷異常
;第一次查表主要是查出是什麼異常,可我們總要知道是這個中斷異常中的什麼中斷呀!
;沒辦法了,再查一次表唄!
;===================================================================================
;外部中斷號判斷,通過中斷服務程式入口地址儲存器的地址偏移確定
;PC=[HandleEINT0+[INTOFFSET]]              
;IsrIRQ
IRQ_Handler
    sub sp,sp,#4      ;給PC暫存器保留 reserved for PC
    stmfd sp!,{r8-r9} ;把r8-r9壓入棧
    ldr r9,=INTOFFSET ;把INTOFFSET的地址裝入r9  INTOFFSET是一個內部的暫存器,存著中斷的偏移
    ldr r9,[r9]       ;I_ISR
    ldr r8,=HandleEINT0 ;這就是我們第二個中斷向量表的入口的,先裝入r8
;===================================================================================
;哈哈,這查表方法夠好了吧,r8(入口)+index*4(別望了一條指令是4 bytes的喔),
;這不就是我們要找的那一項了嗎.找到了表項,下一步做什麼?肯定先裝入了!
;==================================================================================
    add r8,r8,r9,lsl #2  ;地址對齊,因為每個中斷向量佔4個位元組,即isr = IvectTable + Offeset * 4
    ldr r8,[r8]          ;裝入中斷服務程式的入口
    str r8,[sp,#8]       ;把入口也入棧,準備用舊招
    ldmfd sp!,{r8-r9,pc} ;施招,彈出棧,哈哈,順便把r8彈出到PC了,跳轉成功!


; Reset Handler

                EXPORT  Reset_Handler


...

六,遮蔽USER模式,開啟SVC模式,開啟IRQ中斷

因為在ram除錯時,code地址是從0x30000000開始,而IRQ中斷跳轉會直接調到0x00000018,然而我們期望跳到0x30000018(這個才是真正的IRQ入口),所以需要用mmu做一個0x000000180x30000018的對映(這個在TQ2440工程中的mmu初始化程式碼中完成)。但是mmu呼叫cp15協處理器的彙編程式碼在USER模式下會出問題?!目前只能先用SVC模式。此外,Keil自帶的S3C2440.s檔案預設是關閉SVC模式的IRQ中斷,需要修改程式碼開啟。

...

             SUB     R0, R0, #FIQ_Stack_Size

;  Enter IRQ Mode and set its Stack Pointer
                MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #IRQ_Stack_Size

;  Enter Supervisor Mode and set its Stack Pointer
                ;MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                MSR     CPSR_c, #Mode_SVC:OR:F_Bit
                MOV     SP, R0
                SUB     R0, R0, #SVC_Stack_Size

;  Enter User Mode and set its Stack Pointer
                ;MSR     CPSR_c, #Mode_USR
                ;MSR     CPSR_c, #Mode_USR:OR:I_Bit:OR:F_Bit
                ;MOV     SP, R0
                ;SUB     SL, SP, #USR_Stack_Size

;  Enter User Mode and set its Stack Pointer
                ;MSR     CPSR_c, #Mode_USR
                IF      :DEF:__MICROLIB

                EXPORT __initial_sp

...