目前測試FIQ中斷,發現中斷可以觸發,但是,FIQ跳轉不知道跑哪去?
嘗試將FIQ的機器代碼(點亮LED)部份,使用LDR/STR方式動態寫入0x00000018, 0x80000018, 0xffff0018, 0xffff40018位置,
但是發現, 還是一樣無法點亮LED,請問有知道的嗎?
代碼如下:
.global _start
.equiv GPIO_BASE, 0x01c20800
.equiv TIMER_BASE, 0x01c20c00
.equiv INTC_BASE, 0x01c20400
.equiv PE, (0x24 * 4)
.equiv PORT_CFG0, 0x00
.equiv PORT_DATA, 0x10
.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
.equiv TMR_IRQ_EN_REG, 0x00
.equiv TMR_IRQ_STA_REG, 0x04
.equiv TMR0_CTRL_REG, 0x10
.equiv TMR0_INTV_VALUE_REG, 0x14
.equiv TMR0_CUR_VALUE_REG, 0x18
.arm
.text
_start:
.long 0xea000016
.byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0'
.long 0, __spl_size
.byte 'S', 'P', 'L', 2
.long 0, 0
.long 0xea000016, 0, 0, 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0
_vector:
b reset
b .
b .
b .
b .
b .
b irq_handler
b .
irq_handler:
ldr r0, =GPIO_BASE
ldr r1, =0x00
str r1, [r0, #(PE + PORT_DATA)]
subs pc, lr, #4
reset:
mrs r0, cpsr
bic r0, #0x80
msr cpsr_c, r0
ldr r0, =INTC_BASE
ldr r1, =(1<< 13)
str r1, [r0, #INTC_EN_REG0]
ldr r1, =~(1 << 13)
str r1, [r0, #INTC_MASK_REG0]
ldr r0, =GPIO_BASE
ldr r1, =0x00010000
str r1, [r0, #(PE + PORT_CFG0)]
ldr r1, =0x10
str r1, [r0, #(PE + PORT_DATA)]
ldr r0, =TIMER_BASE
ldr r1, =256
str r1, [r0, #TMR0_INTV_VALUE_REG]
ldr r1, =(7 << 4) | (1 << 1) | 1
str r1, [r0, #TMR0_CTRL_REG]
ldr r1, =1
str r1, [r0, #TMR_IRQ_EN_REG]
str r1, [r0, #TMR_IRQ_STA_REG]
b .
.end
最近编辑记录 司徒 (2021-05-12 10:34:25)
离线
司徒 说:其實原本的b irq_handler的意思就是跳轉, 但是改成如下, 還是無法挑轉到irq_handler
_vector: b reset b . b . b . b . b . ldr pc, irq_handler ldr pc, irq_handler irq_handler: str r1, [r0, #(PE + PORT_DATA)] subs pc, lr, #4
我知道你直接写b irq_handler 也可以,但这个前提是你的irq_handler是在32MB范围内 因为b只能跳转32M范围,所以我觉得用LDR更好点而已。但是FIRQ中断是在IRQ的下一个地址嘛,你不是没写嘛所以我叫你加上。 至于你加上也不行,那是不是你并没有进入FIRQ中断呢?
初始化中斷的方式如下
mrs r0, cpsr
bic r0, #0x80
msr cpsr_c, r0
ldr r0, =INTC_BASE
ldr r1, =(1<< 13)
str r1, [r0, #INTC_EN_REG0]
ldr r1, =~(1 << 13)
str r1, [r0, #INTC_MASK_REG0]
開啟IRQ,接著Enable Timer0中斷
我有使用UART打印測試(無窮迴圈), 發現中斷後, UART不會打印了, 而且判斷Timer0 IRQ也確實拉起來, 只是IRQ中斷始終無法進入, 請問有建議的方式嗎 ?
离线
你这个不知道能不能跑起来,我给你个我裸机的给你参考下吧。我这个是keil版本的,想要进入IRQ模式还是需要设置 cpsr寄存器的。
AREA WB_INIT, CODE, READONLY USR_MODE EQU 0x10 FIQ_MODE EQU 0x11 IRQ_MODE EQU 0x12 SVC_MODE EQU 0x13 ABT_MODE EQU 0x17 UDF_MODE EQU 0x1B SYS_MODE EQU 0x1F I_BIT EQU 0x80 F_BIT EQU 0x40 IRQ_RAMStack EQU 0x81FA0000 DRAM_Limit EQU 0x81F00000 ;DDR栈顶 RAM_Limit EQU 0x4000 ;内存大小 32k UND_Stack EQU RAM_Limit - 128 Abort_Stack EQU RAM_Limit - 256 IRQ_Stack EQU RAM_Limit - 512 FIQ_Stack EQU RAM_Limit - 768 SVC_Stack EQU RAM_Limit - 1024 USR_Stack EQU RAM_Limit - 2048 ENTRY ; EXPORT Reset_Go ; EXPORT Vector_Table IMPORT ||Load$$ER_IROM1$$Length|| IMPORT ||Image$$RW_RAM1$$RW$$Length|| ; 链接器产生代码链接运行位置 _start ; /* Boot head information for BROM */ DCD 0xea000016 DCB 'e', 'G', 'O', 'N', '.', 'B', 'T', '0' DCD 0, ||Load$$ER_IROM1$$Length|| ; DCD 0, __bootloader_size DCB 'S', 'P', 'L', 2 DCD 0, 0 DCD 0, 0, 0, 0, 0, 0, 0, 0 DCD 0, 0, 0, 0, 0, 0, 0, 0 ;/* 0x40 - boot params, 0x58 - fel boot type, 0x5c - dram size */ Vector_Table B Reset_Go LDR PC, Undefined_Addr LDR PC, SWI_Addr LDR PC, Prefetch_Addr LDR PC, Abort_Addr DCD 0x0 LDR PC, IRQ_Addr LDR PC, FIQ_Addr Reset_Addr DCD Reset_Go Undefined_Addr DCD Undefined_Handler SWI_Addr DCD SWI_Handler1 Prefetch_Addr DCD Prefetch_Handler Abort_Addr DCD Abort_Handler DCD 0 IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler Undefined_Handler B Undefined_Handler SWI_Handler1 B SWI_Handler1 Prefetch_Handler B Prefetch_Handler Abort_Handler B Abort_Handler IMPORT arm32_do_irq PRESERVE8 IRQ_Handler ldr sp,=IRQ_RAMStack sub sp, sp, #72 stmia sp, {r0 - r12} add r8, sp, #60 stmdb r8, {sp, lr}^ str lr, [r8, #0] mrs r6, spsr str r6, [r8, #4] str r0, [r8, #8] mov r0, sp bl arm32_do_irq ldmia sp, {r0 - lr}^ mov r0, r0 ldr lr, [sp, #60] add sp, sp, #72 subs pc, lr, #4 FIQ_Handler B FIQ_Handler EXPORT __CodeAddr__ EXPORT __RamSize__ ; 引入链接器产生符号,以确定代码运行位置,编译生成的大小 IMPORT ||Image$$ER_IROM1$$Base|| IMPORT ||Image$$RW_RAM1$$ZI$$Base|| IMPORT ||Image$$RW_RAM1$$ZI$$Length|| IMPORT ||Image$$RW_RAM1$$RW$$Length|| IMPORT ||Image$$ER_IROM1$$Length|| IMPORT ||Image$$ER_IROM2$$Length|| ; IMPORT ||Image$$ER_IROM2$$Length|| ; 链接器产生代码链接运行位置 __CodeAddr__ DCD ||Image$$ER_IROM1$$Base|| __CodeSize__ DCD ||Image$$ER_IROM1$$Length|| + ||Image$$ER_IROM2$$Length|| __RamSize__ DCD ||Image$$ER_IROM1$$Length|| + ||Image$$ER_IROM2$$Length|| + ||Image$$RW_RAM1$$RW$$Length|| __BssStart__ DCD ||Image$$RW_RAM1$$ZI$$Base|| __BssLenth__ DCD ||Image$$RW_RAM1$$ZI$$Length|| Reset_Go ;/* Save boot params to 0x00000040 */ ldr r0, __CodeAddr__ ldr r1,__CodeSize__ ldr r2,__RamSize__ ldr r3,__RamSize__ ldr r0, =0x01C20C04 ;清除定时器中断 ldr r1, = 0x01 str r1,[r0] ldr r0, =0x01c20410 ;屏蔽所有中断 ldr r1, = 0xffffffff str r1,[r0] ldr r0, =0x00000040 str sp, [r0, #0] str lr, [r0, #4] mrs lr, cpsr str lr, [r0, #8] mrc p15, 0, lr, c1, c0, 0 str lr, [r0, #12] mrc p15, 0, lr, c1, c0, 0 str lr, [r0, #16] ; /* Check boot type just for fel */ mov r0, #0x0 ldr r1, [r0, #8] ldr r2, =0x4c45462e cmp r1, r2 bne lab1 ; ldr r1, =0x1 ; str r1, [r0, #0x58] lab1 nop ; /* Enter svc mode and mask interrupts */ mrs r0, cpsr bic r0, r0, #0x1f orr r0, r0, #0xd3 msr CPSR_cxsf, r0 ; /* Set vector to the low address */ mrc p15, 0, r0, c1, c0, 0 bic r0, #(1<<13) mcr p15, 0, r0, c1, c0, 0 ; /* Copy vector to the correct address */ adr r0, Vector_Table mrc p15, 0, r2, c1, c0, 0 ands r2, r2, #(1 << 13) ldreq r1, =0x00000000 ldrne r1, =0xffff0000 ; mcr p15, 0, r2, c1, c0, 0 ldmia r0!, {r2-r8, r10} stmia r1!, {r2-r8, r10} ldmia r0!, {r2-r8, r10} stmia r1!, {r2-r8, r10} IMPORT sys_clock_init IMPORT sys_dram_init IMPORT sys_spi_flash_init IMPORT sys_spi_flash_read IMPORT sys_spi_flash_exit IMPORT system_register_time_int IMPORT memcpy IMPORT memset IMPORT MMU_Init PRESERVE8 ; /* Boot speed up, leave slower sram */ adr r0, _start ldr r1, =_start cmp r0, r1 beq _speedup bl sys_clock_init bl sys_dram_init bl sys_spi_flash_init ; bl MMU_Init ldr r0,=0x00 ldr r1,__CodeAddr__ ldr r2,__RamSize__ bl sys_spi_flash_read ldr r0, =_speedup ldr r1, =_start sub r0, r0, r1 ldr r1, __CodeAddr__ add r0, r0, r1 ldr r0, =0x01c20810 ldr r1, = 0x0f str r1,[r0] _speedup nop MSR CPSR_c, #UDF_MODE :OR: I_BIT :OR: F_BIT LDR SP, =UND_Stack + DRAM_Limit MSR CPSR_c, #ABT_MODE :OR: I_BIT :OR: F_BIT LDR SP, =Abort_Stack + DRAM_Limit MSR CPSR_c, #IRQ_MODE :OR: I_BIT :OR: F_BIT LDR SP, =IRQ_Stack + DRAM_Limit MSR CPSR_c, #FIQ_MODE :OR: I_BIT :OR: F_BIT LDR SP, =FIQ_Stack + DRAM_Limit MSR CPSR_c, #SYS_MODE :OR: I_BIT :OR: F_BIT LDR SP, =USR_Stack + DRAM_Limit MSR CPSR_c, #SVC_MODE :OR: I_BIT :OR: F_BIT LDR SP, =SVC_Stack + DRAM_Limit MRS r1, CPSR ; BIC r1, #0x1f ; ORR r1, #0x7f;进入IRQ模式 AND r1, #0x7f ;允许IRQ中断 MSR CPSR_c,r1 IMPORT __main adr r0, _start ldr r1, =_start cmp r0, r1 bne _NoDdr _NoDdr LDR R0, =__main BX R0 end
感謝你的代碼, 但是, 還是無法進入IRQ副程式...
离线
感謝各位的協助, 最後終於找到問題, 兩個問題
1. 0x18 vector是被Magic Number佔據, 需要手動複製, 複製時, 需要判斷high or low address
2. "ldr pc, _irq"和"ldr pc, =_irq"誤用
修正後的代碼如下:
.global _start
.equiv GPIO_BASE, 0x01c20800
.equiv TIMER_BASE, 0x01c20c00
.equiv INTC_BASE, 0x01c20400
.equiv PE, (0x24 * 4)
.equiv PORT_CFG0, 0x00
.equiv PORT_DATA, 0x10
.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
.equiv TMR_IRQ_EN_REG, 0x00
.equiv TMR_IRQ_STA_REG, 0x04
.equiv TMR0_CTRL_REG, 0x10
.equiv TMR0_INTV_VALUE_REG, 0x14
.equiv TMR0_CUR_VALUE_REG, 0x18
.arm
.text
_start:
.long 0xea000016
.byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0'
.long 0, __spl_size
.byte 'S', 'P', 'L', 2
.long 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0
_vector:
b reset
b .
b .
b .
b .
b .
ldr pc, _irq
b .
_irq: .word irq_handler
irq_handler:
ldr r0, =GPIO_BASE
ldr r1, =0x00
str r1, [r0, #(PE + PORT_DATA)]
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, _vector
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 << 13)
str r1, [r0, #INTC_EN_REG0]
ldr r1, =~(1 << 13)
str r1, [r0, #INTC_MASK_REG0]
ldr r0, =GPIO_BASE
ldr r1, =0x00010000
str r1, [r0, #(PE + PORT_CFG0)]
ldr r1, =0x10
str r1, [r0, #(PE + PORT_DATA)]
ldr r0, =TIMER_BASE
ldr r1, =256
str r1, [r0, #TMR0_INTV_VALUE_REG]
ldr r1, =(7 << 4) | (1 << 1) | 1
str r1, [r0, #TMR0_CTRL_REG]
ldr r1, =1
str r1, [r0, #TMR_IRQ_EN_REG]
str r1, [r0, #TMR_IRQ_STA_REG]
b .
.end
感謝各位的協助
离线