分支到 Microblaze CPU 上的中断处理程序,汇编语言
我对汇编语言和 microblaze cpu 非常陌生,并且在中断处理工作方面遇到问题。
我被迫编写自己的启动和初始化例程。 (通常包含在 crt0 中的东西)我想我在分支到指定地址的中断处理程序时做错了。在文档中据说,从代码地址 0x10 分支到中断处理程序,但是在我的测试程序中它不起作用。
<一href="http://www.google.de/url?q=http://www.xilinx.com/support/documentation/sw_manuals/mb_ref_guide.p df&sa=U&ei=gb9YTrjeJsnwsga5x6XcCg&ved=0CBcQFjAD&usg=AFQjCNGxQYRu8WZdrbEuKhsAAGMpR-rzcQ" rel="nofollow">在这里您可以找到 microblaze 文档。我指的是p。 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 当然不会处理中断,也不会分支到中断处理程序例程。
但是:如果我在 MSR 中启用中断以启用中断处理,则 led 0001 在开始时会闪烁。触发中断后,led 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
任何帮助都会很棒。这个问题真的很烦人,我已经为此工作了好几天。我确信我错过了代码中的一些本质内容。如果您需要任何其他信息,请告诉我。
更新:
据我所知,我的程序从地址 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 (3) 的多重定义 mb-ld test_interrupt_cpu_intc_gpio.o my_crt0_intc.o -o ../executable.elf -N
这样,行为发生了变化,但仍然不正确,因为现在 test_interrupt_cpu_intc_gpio.asm 从地址 0x50 开始。
谢谢, 塞玛
i'm pretty new to assembly language and microblaze cpus and i have a problem getting interrupt handling working.
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. 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.
here you can find the microblaze doc. i'm referring to p. 102 (Interrupt and Exception Handling)
here you can see the code for '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
/* 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. however, in this situation of course the cpu doesn't handle interrupts and doesn't branch to the interrupt handler routine.
BUT: if i enable interrupts in the MSR to enable interrupt handling, led 0001 blinks in the beginning. after triggering the interrupt led 0001 is permanently set (or resp. unset if led 0001 is already unset when the interrupt occurs). led 1000 and 0100 stay inactive, which seems like the cpu stops working.
i compiled the code as follows with the mb-gcc tools:
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. 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)
.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
(3) i tried
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.
THANKS,
sema
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
仅供记录:
问题是该程序与起始地址 0x50 链接。然而,正如 microblaze 文档中所指定的,中断处理程序的分支(向量)必须位于地址 0x10。
'mb-ld --verbose '给出了这个问题的提示
'mb-objdump -dexecutable.elf'显示
问题是通过选项-Ttest 0x0解决的:
我还错过了在中断处理程序例程中清除中断状态寄存器的操作应如下所示(注意 rtid r14, 0 而不是 rtid r14,8):
摘要:
OBJDUMP是非常有用的工具! (这对我来说是新的)
just for record:
the problem was that the program was linked with start address 0x50. however, as specified in the microblaze documentation, the branch (vector) to the interrupt handler must be located at address 0x10.
'mb-ld --verbose ' gave a hint to this problem
'mb-objdump -d executable.elf' shows
the problem is solved by option -Ttest 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):
SUMMARY:
OBJDUMP is very useful tool! (it was new to me)