简体   繁体   English

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

[英]Branch to Interrupt Handler on Microblaze CPU, Assembly Language

i'm pretty new to assembly language and microblaze cpus and i have a problem getting interrupt handling working. 我对汇编语言和micrlaze cpus很新,我遇到了中断处理工作的问题。

i'm forced to write my own startup and init routines. 我被迫编写自己的启动和初始化例程。 (stuff that is usually contained in crt0) and i guess i'm doing something wrong with branching to the interrupt handler at the specified address. (通常包含在crt0中的东西)我猜我在分支到指定地址的中断处理程序时做错了。 in the documentation it is said, to branch from code address 0x10 to the interrupt handler, however in my test program it doesn't work. 据说在文档中,从代码地址0x10分支到中断处理程序,但是在我的测试程序中它不起作用。

here you can find the microblaze doc. 在这里你可以找到microblaze doc。 i'm referring to p. 我指的是p。 102 (Interrupt and Exception Handling) 102(中断和异常处理)

here you can see the code for 'my_crt0_intc.asm' 在这里你可以看到'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

my test program 'test_interrupt_cpu_intc_gpio.asm' is intended to signal interrupts via leds at address 0x81400000 我的测试程序'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

the error symptoms are: if i do not enable interrupts in the MSR, led 0001 blinks and leds 1000 and 0100 are active if trigger the interrupt by pushing the appropriate button. 错误症状是:如果我没有在MSR中启用中断,如果通过按下相应的按钮触发中断,则指示0001闪烁并且指示灯1000和0100处于活动状态。 however, in this situation of course the cpu doesn't handle interrupts and doesn't branch to the interrupt handler routine. 但是,在这种情况下,cpu当然不处理中断,也不会分支到中断处理程序例程。

BUT: if i enable interrupts in the MSR to enable interrupt handling, led 0001 blinks in the beginning. 但是:如果我在MSR中启用中断以启用中断处理,则led 0001在开始时闪烁。 after triggering the interrupt led 0001 is permanently set (or resp. unset if led 0001 is already unset when the interrupt occurs). 在触发中断之后,永久设置0001(或者如果在发生中断时已取消设置了0001 0001,则设置为未设置)。 led 1000 and 0100 stay inactive, which seems like the cpu stops working. led 1000和0100保持不活动状态,这似乎是cpu停止工作。

i compiled the code as follows with the mb-gcc tools: 我用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

any help would be great. 任何帮助都会很棒。 this problem is really annoying and i'm working on this for days. 这个问题真烦人,我正在研究这几天。 i'm sure i miss something essentially in the code. 我确定我会错过代码中的一些内容。 if you need any additional information, please let me know. 如果您需要任何其他信息,请告诉我。

UPDATE: 更新:

as far as i can trust mb-gdb my program starts at address 0x50. 据我所知,mb-gdb我的程序从地址0x50开始。 if this is true, this explains why my branch operations are never executed. 如果这是真的,这就解释了为什么我的分支操作永远不会被执行。

i tried several things to ensure placing the essential instructions at the correct positions (1) 我尝试了几件事来确保将基本指令放在正确的位置(1)

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

(2) i tried linking with mb-gcc and option x1-mode-xmdstub (as it is said in the documentation, that the standard crt0.o is not linked using this option) -> however, in this case i get the error, mutliple defintions of _start (2)我尝试连接mb-gcc和选项x1-mode-xmdstub(正如在文档中所说,标准crt0.o没有使用此选项链接) - >但是,在这种情况下,我得到错误,_start的多重定义

(3) i tried mb-ld test_interrupt_cpu_intc_gpio.o my_crt0_intc.o -o ../executable.elf -N (3)我试过mb-ld test_interrupt_cpu_intc_gpio.o my_crt0_intc.o -o ../executable.elf -N

this way, the behavior changes, but is still uncorrect since now test_interrupt_cpu_intc_gpio.asm starts at address 0x50. 这样,行为会发生变化,但仍然不正确,因为现在test_interrupt_cpu_intc_gpio.asm从地址0x50开始。

THANKS, sema 谢谢,sema

just for record: 仅供记录:

the problem was that the program was linked with start address 0x50. 问题是该程序与起始地址0x50相关联。 however, as specified in the microblaze documentation, the branch (vector) to the interrupt handler must be located at address 0x10. 但是,如microblaze文档中所指定,中断处理程序的分支(向量)必须位于地址0x10。

'mb-ld --verbose ' gave a hint to this problem 'mb-ld --verbose'暗示了这个问题

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

'mb-objdump -d executable.elf' shows 'mb-objdump -d executable.elf'显示

../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

the problem is solved by option -Ttest 0x0: 选项-Ttest 0x0解决了这个问题:

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

i also missed the clearing the interrupt status registers in the interrupt handler routine which should be as follows (note rtid r14, 0 instead of rtid r14,8): 我也错过了在中断处理程序例程中清除中断状态寄存器的情况,如下所示(注意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

SUMMARY: OBJDUMP is very useful tool! 总结:OBJDUMP是非常有用的工具! (it was new to me) (这对我来说很新)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM