在Microblaze CPU上的中断处理程序分支,汇编语言



我是汇编语言和microblaze cpu的新手,我有一个问题得到中断处理工作。

我被迫写我自己的启动和初始化例程。(通常包含在crt0中的东西),我想我在指定地址分支到中断处理程序时做错了什么。在文档中说,从代码地址0x10分支到中断处理程序,但是在我的测试程序中它不起作用。

在这里你可以找到microblaze文档。我指的是第102页(中断和异常处理)

在这里你可以看到'my_crt0_intc.asm'的代码

bri _start
nop
bri _exception_handler
nop
bri _interrupt_handler
nop
bri _hw_exception_handler
nop
/* Starting Point */
    .global _start
_start:     
    brlid   r15, _init_routine
    nop
/* Exception Handler *
    .global _exception_handler
_exception_handler:
/**/
/* Interrupt Handler */
    .global _interrupt_handler
_interrupt_handler:
    /* set led 0010 */
    ori r20, r20, 0x00000002
    swi r20, r0, 0x81400000
    rtid    r14, 8
    nop
/* HW Exception Handler *
    .global _hw_exception_handler
_hw_exception_handler:
/**/
/* Init Routine */
    .global _init_routine
_init_routine:
    /*** Initialize Stack Pointer ***/
    addi    r1, r0, 0x00004000
    /*** ***/
    /*** Initialize Interrupts ***/
    /** GPIO **/
    /* enable interrupts in GIE */
    addi    r19, r0, 0x80000000
    swi r19, r0, 0x8146011C
    /* enable interrupts in channel 1 (and 2, not) in IER */
    addi    r19, r0, 0x00000003
    swi r19, r0, 0x81460128
    /** INTC **/
    /* enable HW interrupts in INTC */
    addi    r19, r0, 0x00000003
    swi r19, r0, 0x8180001C
    /* enable interrupts in INTC IER */
    addi    r19, r0, 0xffffffff
    swi r19, r0, 0x81800008
    /** CPU, enable interrupts in MSR **/
    msrset  r19, 0x00000002
    /*** ***/
    /* Initialize Constants */
    /* r11 = word size, for increment and decrement stack pointer */
    /* addi r11, r0, 4 */
    /*** call main function ***/
    brlid   r15, main
    nop
    /*** ***/
    /*** halting loop ***/
_halting:
    bri _halting
    /*** ***/
    /* Return */
    rtsd    r15, 8
    nop

我的测试程序test_interrupt_cpu_intc_gpio。Asm '旨在通过地址0x81400000的led发出中断信号

/* Main */
    .global main
main:
    addi    r20, r0, 0x0
_loop:
    /* set/unset alive led 0001 */
    andi    r21, r20, 0x00000001
    bnei    r21, _unset_alive
_set_alive:
    ori r20, r20, 0x1
    swi r20, r0, 0x81400000
    bri _no_alive
_unset_alive:
    andi    r20, r20, 0xfffffffe 
    swi r20, r0, 0x81400000
_no_alive:
    /* if gpio isr is set, set led 0100 */
    lwi r21, r0, 0x81460120
    beqi    r21, _unset_gpio
_set_gpio:
    ori r20, r20, 0x4
    swi r20, r0, 0x81400000
    bri _noset_gpio
_unset_gpio:
    andi    r20, r20, 0xfffffffb
    swi r20, r0, 0x81400000
_noset_gpio:
    /* if intc isr is set, set led 1000 */
    lwi r21, r0, 0x81800000
    beqi    r21, _unset_intc
_set_intc:
    ori r20, r20, 0x8
    swi r20, r0, 0x81400000
    bri _noset_intc
_unset_intc:
    andi    r20, r20, 0xfffffff7
    swi r20, r0, 0x81400000
_noset_intc:
    /* begin time loop */
    addi    r21, r0, 0x004af080
_loop_time:
    addi    r21, r21, -1
    bnei    r21, _loop_time
    /* end time loop*/
    bri _loop
    /* return 0*/
    addi    r3, r0, 0
    rtsd    r15, 8
    nop

错误症状如下:如果在MSR中未启用中断,则led 0001闪烁,如果通过按相应按钮触发中断,则led 1000和0100处于活动状态。然而,在这种情况下,CPU当然不会处理中断,也不会分支到中断处理程序例程。

BUT:如果我使能MSR中的中断以使能中断处理,则开始时0001闪烁。触发中断后,0001被永久设置(或复位)。当中断发生时,如果led 0001已经被取消设置,则取消设置)。Led 1000和0100保持非活动状态,这似乎是CPU停止工作。

我用mb-gcc工具编译了下面的代码:
mb-as test_interrupt_cpu_intc_gpio.o -o test_interrupt_cpu_intc_gpio.o
mb-as my_crt0_intc.asm -o my_crt0_intc.o
mb-ld my_crt0_intc.o test_interrupt_cpu_intc_gpio.o -o ../executable.elf -N

任何帮助都太好了。这个问题真的很烦人,我为此工作了好几天。我肯定我在代码中遗漏了一些重要的东西。如果你需要任何额外的信息,请告诉我。

更新:

就我可以信任mb-gdb而言,我的程序从地址0x50开始。如果这是真的,这就解释了为什么我的分支操作永远不会被执行。

我尝试了几种方法来确保把重要的指令放在正确的位置(1)

    .org    0x0
brai    _start
    .org    0x8
brai    _exception_handler
    .org    0x10
brai    _interrupt_handler
    .org    0x20
brai    _hw_exception_handler

(2)我尝试链接mb-gcc和选项x1-mode-xmdstub(正如在文档中所说,标准的crt0。O没有使用这个选项链接)->然而,在这种情况下,我得到了错误,_start

的多个定义我试过了mb-ld test_interrupt_cpu_intc_gpio。o my_crt0_intc。/可执行文件。精灵- n

这种方式,行为改变,但仍然是不正确的,因为现在test_interrupt_cpu_intc_gpio。Asm从地址0x50开始

谢谢,某

just for record:

问题是程序被链接到起始地址0x50。然而,正如microblaze文档中指定的那样,中断处理程序的分支(向量)必须位于地址0x10。

'mb-ld——verbose '给出了这个问题的提示

ENTRY(_start) _TEXT_START_ADDR = DEFINED(_TEXT_START_ADDR) ? _TEXT_START_ADDR : 0x50;

'mb-objdump -d executable。精灵"显示了

../executable.elf:     file format elf32-microblaze
Disassembly of section .text:
00000050 <_start-0x28>:
  50:   b0000000        imm     0
  54:   b8080078        brai    120     // 78 <_start>
  58:   b0000000        imm     0
  5c:   b80800cc        brai    204     // cc <_exception_handler>
  60:   b0000000        imm     0
  64:   b80800d4        brai    212     // d4 <_interrupt_handler>
  68:   b0000000        imm     0

问题通过选项-Ttest 0x0:

解决
mb-ld $CRT_OBJ $OBJ -o ../executable.elf -Ttext 0x0

我还错过了在中断处理程序例程中清除中断状态寄存器,该寄存器应该如下(注意rtid r14,0而不是rtid r14,8):

    .global _interrupt_handler
_interrupt_handler:
    /* set led 0010 */
    ori r20, r20, 0x00000002
    swi r23, r0, 0x81400000
    /**/
    /* clear channel 1 in gpio isr */
    addi    r22, r0, 0x00000001
    swi r22, r0, 0x81460120
    /* acknowledge interrupts in intc from channel 1 of gpio 3b (bit 2) */
    addi    r22, r0, 0x00000002
    swi r22, r0, 0x8180000C
    /* return from interrupt */
    rtid    r14, 0
    nop

概要:OBJDUMP是一个非常有用的工具!(这对我来说是新的)

最新更新