模擬器 - QEMU - Allwinner F1C100S - 解決Firmware IRQ副程式無法被呼叫的問題



main.ld

MEMORY {
    RAM : ORIGIN = 0x00000000, LENGTH = 32K
}

SECTIONS {
    text : {
        PROVIDE(__spl_start = .);
        *(.text*)
        PROVIDE(__spl_end = .);
    } > RAM
    PROVIDE(__spl_size = __spl_end - __spl_start);
}

main.s

    .global _start
  
    .equiv INTC_BASE,          0x01c20400
    .equiv INTC_BASE_ADDR_REG, 0x04
    .equiv INTC_PEND_REG0,     0x10
    .equiv INTC_PEND_REG1,     0x14
    .equiv INTC_EN_REG0,       0x20
    .equiv INTC_EN_REG1,       0x24
    .equiv INTC_MASK_REG0,     0x30
    .equiv INTC_MASK_REG1,     0x34
    .equiv INTC_RESP_REG0,     0x40
    .equiv INTC_RESP_REG1,     0x44
    .equiv INTC_FF_REG0,       0x50
    .equiv INTC_FF_REG1,       0x54
  
    .arm
    .text
_start:
    b reset
    b .
    b .
    b .
    b .
    b .
    ldr pc, _irq
    b .
   
_irq: .word irq_handler
   
irq_handler:
    ldr r0, =INTC_BASE
    ldr r1, =0x00000000
    str r1, [r0, #INTC_FF_REG0]
    ldr r1, =0xffffffff
    str r1, [r0, #INTC_PEND_REG0]
    subs pc, lr, #4
   
reset:
    mrc p15, 0, r0, c1, c0, 0
    bic r0, #(1 << 13)
    mcr p15, 0, r0, c1, c0, 0
   
    adr r0, _start
    mrc p15, 0, r2, c1, c0, 0
    ands r2, r2, #(1 << 13)
    ldreq r1, =0x00000000
    ldrne r1, =0xffff0000
    ldmia r0!, {r2-r8, r10}
    stmia r1!, {r2-r8, r10}
    ldmia r0!, {r2-r8, r10}
    stmia r1!, {r2-r8, r10}
   
    mrs r0, cpsr
    bic r0, #0x80
    msr cpsr_c, r0
   
    ldr r0, =INTC_BASE
    ldr r1, =(1 << 3)
    str r1, [r0, #INTC_EN_REG0]
    ldr r1, =0x00000000
    str r1, [r0, #INTC_MASK_REG0]
    ldr r1, =(1 << 3)
    str r1, [r0, #INTC_FF_REG0]
   
0: 
    b 0b
    .end

追查後才發現BootROM是位於0xffff0000,而原本main.ld的記憶體位址則是從0x00000000開始

static const hwaddr f1c100s_memmap[] = {
    [SRAM_BASE]    = 0x00000000,
    [CCU_BASE]     = 0x01c20000,
    [INTC_BASE]    = 0x01c20400,
    [GPIO_BASE]    = 0x01c20800,
    [SDRAM_BASE]   = 0x80000000,
    [BOOTROM_BASE] = 0xffff0000
};

更換如下位址後,即可觸發中斷副程式

MEMORY {
    RAM : ORIGIN = 0xffff0000, LENGTH = 32K
}

SECTIONS {
    text : {
        PROVIDE(__spl_start = .);
        *(.text*)
        PROVIDE(__spl_end = .);
    } > RAM
    PROVIDE(__spl_size = __spl_end - __spl_start);
}