新華 ARM9_S3C2410 - 系統初始化與中斷向量的配置

程式碼追蹤

檔案:head.s

    .global stext
    .global main
    .global __gccmain
    .global CUdefHandler, CIrqHandler, CPabtHandler, CDabtHandler, CFiqHandler
    .global MMU_Init, MMU_EnableICache, MMU_EnableDCache,MMU_EnableMMU
    .global enable_irq, disable_irq

.section ".stext"

    .equ    USER_MODE,         0x10
    .equ     FIQ_MODE ,       0x11
    .equ     IRQ_MODE ,       0x12
    .equ     SVC_MODE ,       0x13
    .equ     ABORT_MODE ,       0x17
    .equ     UNDEF_MODE ,       0x1b
    .equ    MODE_MASK  ,      0x1f
    .equ     NOINT ,            0xc0
    .equ     ROM0_SIZE,         0x200000
    .equ     SDRAM0_BASE_FOR_LOADER    , 0x1000000

// ============================中斷向量表==========================
stext:
    b        ResetHandler    // Reset 中斷
    b        UdefHnd        // 未定義中斷
    b        SwiHnd        // 軟體中斷 Software Interrput
    b        PabtHnd        // ?? 中止中斷 Process Abort.
    b        DabtHnd        // ?? 中止中斷 Process Abort.
    b        Unexpected    // 非期望中斷
    b        IrqHnd        // 一般中斷
    b        FiqHnd        // 快速中斷

// ============================例外事件==========================
Unexpected:        
    b        Unexpected    // 非期望中斷,不處理、無窮迴圈

// ============================未定義事件==========================
UdefHnd:
    stmdb    sp!,{r0-r12,lr}
    bl        CUdefHandler    // 跳到 CUdefHandler 未定義中斷處理函數
    ldmia    sp!,{r0-r12,lr}
    subs    pc,lr,#4

// ============================軟體中斷==========================
SwiHnd:    
    stmdb    sp!,{r0-r12,lr}
    subs     r0, lr, #4
    ldr        r0,[r0]
    mov        r1, #0xffffff
    and     r0,r0,r1
    cmp     r0, #1
    beq        Enable_IRQ_SWI
    b        EndOfSwi

Enable_IRQ_SWI:
    mrs        r1,spsr
    mvn        r0,#0xc0
    and        r1,r1,r0
    msr        spsr_c,r1
    b         EndOfSwi

EndOfSwi:
    ldmia    sp!,{r0-r12,lr}
    movs    pc, lr

// ============================一般中斷管理==========================
IrqHnd:
    stmdb    sp!,{r0-r12,lr}
    bl        CIrqHandler    // 跳到 CIrqHandler 一般中斷處理函數
    ldmia    sp!,{r0-r12,lr}
    subs    pc,lr,#4

PabtHnd:
    stmdb    sp!,{r0-r12,lr}
    sub        r0,lr,#8
    bl        CPabtHandler    // 跳到 CPabtHandler  abort 處理函數
    ldmia    sp!,{r0-r12,lr}
    subs    pc,lr,#4

DabtHnd:
    stmdb    sp!,{r0-r12,lr}
    sub        r0,lr,#8
    bl        CDabtHandler    // 跳到 CDabtHandler  abort 處理函數
    ldmia    sp!,{r0-r12,lr}
    subs    pc,lr,#4

// ============================快速中斷管理==========================
FiqHnd:
    stmdb    sp!,{r0-r7,lr}
    bl        CFiqHandler    // 跳到 CFiqHandler 快速中斷處理函數
    ldmia    sp!,{r0-r7,lr}
    subs    pc,lr,#4

enable_irq:
    mrs        r0,cpsr
    bic        r0,r0,#0x80
    msr        cpsr_c,r0
    mov        pc,lr 

disable_irq:        
    mrs        r0,cpsr
    orr        r0,r0,#0x80
    msr        cpsr_c,r0
    mov        pc,lr

// ============================開機程序:重設電腦初始狀態===================
ResetHandler:                // 開機程序
    ldr        r0,= 0x53000000 // 0x53000000=WTCON, watch dog disable
    ldr        r1,=0x0         
    str        r1,[r0]

// ================= 禁止所有中斷 ===================
    ldr        r0,= 0x4a000008    // 0x4a000008=INTMSK, 中斷遮罩
    ldr        r1,=0xffffffff  // 所有中斷禁能
    str        r1,[r0]

    ldr        r0,= 0x4a00001c // 0x4a00001c=INTSUBMSK, 子中斷遮罩
    ldr        r1,=0x7ff    // 禁止所有子中斷
    str        r1,[r0]

    ldr        r0,= 0x560000a4 // 0x4a00001c=EINTMSK, 外部中斷遮罩
    ldr        r1,=0x00fffff0    // 禁止所有外部中斷
    str        r1,[r0]    

// ================= 設定所有中斷為一般模式 ===================
    ldr     r0,= 0x4a000004     // 0x4a000004=INTMOD, 中斷模式
    mov        r1,#0        // 設定所有中斷為一般中斷
    str     r1,[r0]

// ================= 清除來源、中斷懸置暫存器 ===================
    ldr     r0,= 0x4a000000     // 0x4a000000=SRCPND 來源懸置暫存器
    ldr     r1,=0xffffffff
    str     r1,[r0]

    ldr     r0,= 0x4a000010      // 0x4a000010=INTPND 中斷懸置暫存器
    ldr     r1,=0xffffffff
    str     r1,[r0]    

    ldr     r0,= 0x4a000018       // 0x4a000018=SUBSRCPND 中斷懸置暫存器
    ldr     r1,=0x7ff
    str     r1,[r0]        

    ldr     r0,= 0x560000a8     // 0x4a000018=EINTPND 外部中斷懸置暫存器
    ldr     r1,=0x00fffff0
    str     r1,[r0]        

// ================= 清除並禁能 cache 功能 ===================
    mrc      p15,0,r0,c1,c0,0
    bic      r0,r0,#0x1000             
    bic      r0,r0,#0x000f                

    mcr      p15,0,r0,c1,c0,0
    nop
    nop
    mov      r0,#0
    mcr      p15,0,r0,c7,c6,0         

// ================= 組態記憶體控制暫存器 ===================
    ldr        r0,=SMRDATA
    ldr        r1,= 0x48000000 // 0x48000000=BWSCON
    add        r2, r0,#52         
0:       
    ldr        r3, [r0],#4    
    str        r3, [r1],#4    
    cmp        r2, r0        
    bne        0b

// ================= 組態時脈比率為 FCLK:HCLK:PCKL=1:2:4 ======
    ldr        r0,= 0x4c000014 // 0x4c000014=CLKDIVN
    ldr        r1,=0x03
    str        r1,[r0]

// ================= 組態 LOCKTIME ===================
     ldr        r0,= 0x4c000000 // 0x4c000000=LOCKTIME
    ldr        r1,=0xffffff
    str        r1,[r0]    

// ================= 組態 MPLL ===================
    ldr        r0,= 0x4c000004    // =MPLLCON
    ldr        r1,=((0xa1 <<12)+(0x3 <<4)+ 0x1 )   
    str        r1,[r0]

    mov        r0,#4000
1:    subs    r0,r0,#1
    bne        1b

// ================= 組態 UPLL ===================
    ldr     r0, = 0x4c000008         // =UPLLCON
    ldr     r1, =((0x48 <<12) + (0x3 <<4) + 0x2 )  
    str     r1, [r0]    

    mov        r0,#8000
2:    subs    r0,r0,#1
    bne        2b        

    ldr    r1,=0xc0000000
    mrc    p15,0,r0,c1,c0,0
    orr    r0,r0,r1
    mcr    p15,0,r0,c1,c0,0    

// ================= 將 ROM 資料複製到 RAM =======
.ifdef LOADER
    ldr     r0,=0x0           
    ldr     r1,=0x30000000         
    ldr     r2,=0x30080000         
20:    ldr     r3,[r0],#4
    str     r3,[r1],#4
    cmp     r1,r2
    bne     20b
.endif

// ================= 設定堆疊 ==================
    ldr     r1,=_USR_STACK
    ldr     r2,= 0x30000000     // _RAM_STARTADDRESS
    orr     sp,r1,r2

// ================= 建立 MMU 表 ===================
    bl      MMU_Init

// ================= 致能 MMU ===================
    ldr     r2,=RELOCATE        

    mrc     p15,0,r0,c1,c0,0

    orr      r0,r0,#1
    mcr      p15,0,r0,c1,c0,0
    mov     pc,r2            // change address spaces
    nop
    nop
    nop

RELOCATE:

    bl        MMU_EnableICache
    bl        MMU_EnableDCache    

cstartup:

    ldr        r0, =_etext
    ldr        r1, =_sdata
    ldr        r3, =_sbss

    cmp        r0, r1
    beq        1f

0:    cmp        r1, r0
    ldrcc    r2, [r0], #4
    strcc    r2, [r3], #4
    bcc        0b

1:    ldr        r1, =_ebss
    mov        r2, #0
2:    cmp        r3, r1
    strcc    r2, [r3], #4
    bcc        2b

// ================= 堆疊初始化 ===================
InitStacks:

    mrs     r0,cpsr
    bic     r0,r0,#MODE_MASK
    orr     r1,r0,#IRQ_MODE|NOINT
    msr     cpsr,r1            @IRQMode
    ldr     sp,=_IRQ_STACK

    orr     r1,r0,#FIQ_MODE|NOINT
    msr     cpsr,r1            @FIQMode
    ldr     sp,=_FIQ_STACK

    mrs        r0, cpsr
    bic        r0, r0, #MODE_MASK
    orr        r0, r0, #SVC_MODE
    bic        r0,r0,#0xc0        @enable IRQ and FIQ
    msr        cpsr, r0
    ldr        sp, =_USR_STACK

//==================== 進入主程式 main ================================
3: 
    bl    main
    b    3b

// ================= 記憶體組態 ===================
SMRDATA:

        .long (0+(((0x2) ) <<4)+(((0x1)  | (0x1<<2) ) <<8)+(((0x1) ) <<12)+(((0x1) ) <<16)+(((0x1)  | (0x1<<2)  | (0x1<<3) ) <<20)+(((0x2) ) <<24)+(((0x2) ) <<28))
        .long ((0x0 <<13)+(0x2 <<11)+(0x7 <<8)+(0x0 <<6)+(0x0 <<4)+(0x0 <<2)+(0x0 ))    
        .long ((0x0 <<13)+(0x2 <<11)+(0x7 <<8)+(0x0 <<6)+(0x0 <<4)+(0x0 <<2)+(0x0 ))    
        .long ((0x1 <<13)+(0x0 <<11)+(0x7 <<8)+(0x0 <<6)+(0x0 <<4)+(0x0 <<2)+(0x0 ))    
        .long ((0x0 <<13)+(0x0 <<11)+(0x7 <<8)+(0x0 <<6)+(0x0 <<4)+(0x0 <<2)+(0x0 ))    
        .long ((0x0 <<13)+(0x0 <<11)+(0x7 <<8)+(0x0 <<6)+(0x0 <<4)+(0x0 <<2)+(0x0 ))    
        .long ((0x0 <<13)+(0x3 <<11)+(0x7 <<8)+(0x1 <<6)+(0x3 <<4)+(0x3 <<2)+(0x0 ))    
        .long ((0x3 <<15)+(0x1 <<2)+(0x1 ))     
        .long ((0x3 <<15)+(0x1 <<2)+(0x1 ))     
        .long ((0x1 <<23)+(0x0 <<22)+(0x0 <<20)+(0x3 <<18)+(0x2 <<16)+ 1113 )       

        .long 0xB2                 
        .long 0x30               
        .long 0x30                

.section ".bss"

檔案:demo.c

int main(void)
{    
    //USER PROGRAM INTERFACE
    //...
    //...

    return(0);

}

檔案:Irq.c

/*************************************************************************
Include files
*************************************************************************/
#include <stdio.h>
#include <string.h>
#include "driver.h"

/*************************************************************************
Constant define
*************************************************************************/
#define    IRQ_INT_NO    NORMAL_IRQ_OFFSET

#define IRQ_NAME_SIZE    24

/*
* This table holds the list of irq handlers and is indexed by interrupt
* priority - 1. Therefore each interrupt must be assigned a unique priority 
* in the range 1-17 in the irq_priority_table below.
*/

struct irq_entry{
    void (*handler)(void); //pointer to an interrupt handler
    char id;    // bit position for masking interrupt controller registers
    char name[IRQ_NAME_SIZE]; // used to identify the owner of this irq
};

/*************************************************************************
Function prototypes
*************************************************************************/

/*************************************************************************
Variable define
*************************************************************************/
static struct irq_entry irq_table[IRQ_INT_NO];

void irq_init (void)
{
    int        i;

    for(i=0; i < IRQ_INT_NO; i++){
        irq_table[i].handler = NULL;        
    }        
}

void print_irq_info(void){
    int i;

    //printf("priority\tid\tname\n\r========\t==\t====\n\r\n\r");    
    for(i=0; i < IRQ_INT_NO;i++){
        //printf("%d\t\t%d\t%s\r\n",i+1,irq_table[i].id,irq_table[i].name[0]=='\0' ? "Unused" : irq_table[i].name);
    }
}

void register_irq(unsigned int Id, void (*handler)(void), char *name)
{
    if ((Id >= 0) && (Id < IRQ_INT_NO)){
        if (!irq_table[Id].handler){
            irq_table[Id].handler = handler;        
            strncpy(irq_table[Id].name, name, IRQ_NAME_SIZE);
            //INT_MASK_SET = 1<<id;
        }else{
            //printf("Error %s: irq %d already claimed by %s\n\r",name,id,irq_table[priority].name);        
        }
    }
}

void unregister_irq(unsigned int id, char* name)
{
    /* check for owneship of the irq and then unregister it */
    if(!strncmp(irq_table[id].name, name, sizeof(irq_table[id].name))){
        //INT_MASK_CLEAR = 1<<id;
        irq_table[id].handler=NULL;
        irq_table[id].name[0]='\0';
    }else{
        //printf("Error %s: not owner of irq %d \n\r",name,id);
    }
}

void CIrqHandler(void)
{
    int IRQindex;

    IRQindex = rINTOFFSET ;
    if ((IRQindex >= 0) && (IRQindex < IRQ_INT_NO)) {
        if(irq_table[IRQindex].handler){
            irq_table[IRQindex].handler();
        } else {
            printf("Error, no irq registered for irq %d\n\r",irq_table[IRQindex].id);
        }            
    }
}

void CFiqHandler(void)
{
    /* This shouldn't happen, but let's trap it just in case */
    //printf("Unexpected FIQ\r\n");
    return;
}

/*************************************************************************
EXCEPTIONS
*************************************************************************/

void CAbtHandler(void)
{
    printf("Data abort\n\r");
}

void CPabtHandler(unsigned int address)
{
    printf("Error prefetch abort at address %#x\n\r",address);
}

void CDabtHandler(unsigned int address)
{
    printf("Error data abort at address %#x\n\r", address);
}

void CSwiHandler(void)
{
    printf("Error swi\n\r");
}

void CUdefHandler(void)
{
    printf("Error undefined instruction\n\r");
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License