Я новичок в языке ассемблера и процессоре microblaze, и у меня возникла проблема с обработкой прерываний.
я вынужден писать свои собственные процедуры запуска и инициализации. (материал, который обычно содержится в crt0), и я предполагаю, что делаю что-то не так с переходом к обработчику прерывания по указанному адресу. в документации сказано, что нужно переходить от кодового адреса 0x10 к обработчику прерывания, однако в моей тестовой программе это не работает.
Отн. ="nofollow">здесь вы можете найти документацию по 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
/* 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, светодиод 0001 мигает, а светодиоды 1000 и 0100 активны, если вызвать прерывание нажатием соответствующей кнопки. однако в этой ситуации, конечно, процессор не обрабатывает прерывания и не переходит к процедуре обработки прерываний.
НО: если я разрешаю прерывания в MSR, чтобы включить обработку прерываний, светодиод 0001 сначала мигает. после срабатывания прерывания светодиод 0001 постоянно установлен (или, соответственно, не установлен, если светодиод 0001 уже не установлен, когда происходит прерывание). светодиоды 1000 и 0100 остаются неактивными, что похоже на то, что процессор перестает работать.
Я скомпилировал код с помощью инструментов 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.
СПАСИБО, сема
mb-ld --verbose <options>
? - person user786653   schedule 29.08.2011