3

私はアセンブリ言語とmicroblazeCPUにかなり慣れていませんが、割り込み処理を機能させるのに問題があります。

私は自分のスタートアップと初期化ルーチンを書くことを余儀なくされています。(通常はcrt0に含まれているもの)そして、指定されたアドレスの割り込みハンドラーへの分岐で何か問題が発生していると思います。ドキュメントでは、コードアドレス0x10から割り込みハンドラーに分岐すると言われていますが、私のテストプログラムでは機能しません。

ここで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が点滅し、適切なボタンを押して割り込みをトリガーすると、LED1000と0100がアクティブになります。ただし、この状況ではもちろん、CPUは割り込みを処理せず、割り込みハンドラルーチンに分岐しません。

しかし、MSRで割り込みを有効にして割り込み処理を有効にすると、最初にLED0001が点滅します。割り込みをトリガーした後、led 0001は永続的に設定されます(または、割り込みが発生したときにled 0001がすでに設定解除されている場合は、それぞれunset)。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の複数の定義

(3)mb-ld test_interrupt_cpu_intc_gpio.o my_crt0_intc.o -o../executable.elf-Nを試しました

このように、動作は変更されますが、test_interrupt_cpu_intc_gpio.asmがアドレス0x50で開始されるため、まだ正しくありません。

ありがとう、セマ

4

1 に答える 1

1

記録のためだけに:

問題は、プログラムが開始アドレス0x50にリンクされていることでした。ただし、microblazeのドキュメントで指定されているように、割り込みハンドラへの分岐(ベクトル)はアドレス0x10に配置する必要があります。

'mb-ld --verbose'は、この問題にヒントを与えました

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

「mb-objdump-dexecutable.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

この問題は、オプション-Ttest0x0によって解決されます。

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

また、割り込みハンドラルーチンの割り込みステータスレジスタをクリアするのを見逃しました。これは次のようになります(rtidr14,8ではなくrtidr14、0に注意してください)。

    .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は非常に便利なツールです。(私にとっては初めてでした)

于 2011-09-04T14:07:44.630 に答える