Я начинаю писать игрушечную ОС для BeagleBone Black, в которой используется ARM Cortex-A8 на основе TI Sitara AM3359 SoC и загрузчика U-Boot. У меня есть простое автономное приложение hello world, записывающее в UART0, которое я пока могу загрузить через U-Boot, и теперь я пытаюсь перейти к обработчикам прерываний, но я не могу заставить SWI делать что-либо, кроме как повесить устройство.
Согласно AM335x TRM (начиная со страницы 4099, если вам интересно), таблица векторов прерываний отображается в ПЗУ по адресу 0x20000. Обработчик SWI ПЗУ переходит в ОЗУ по адресу 0x4030ce08, который переходит к адресу, хранящемуся в 0x4030ce28. (Изначально это уникальный мертвый цикл по адресу 0x20084.)
Мой код устанавливает SP всех режимов процессора ARM в их собственные области в верхней части ОЗУ и разрешает прерывания в CPSR, а затем выполняет инструкцию SWI, которая всегда зависает. (Возможно, переход к какой-нибудь инструкции по мертвому циклу?) Я просмотрел кучу примеров и прочитал всю документацию, которую смог найти, и не вижу, что мне не хватает.
В настоящее время мое единственное взаимодействие с платой осуществляется через последовательное соединение на UART0 с моим Linux-боксом. U-Boot инициализирует UART0 и позволяет загружать двоичный файл через последовательное соединение.
Вот соответствующая сборка:
.arm
.section ".text.boot"
.equ usr_mode, 0x10
.equ fiq_mode, 0x11
.equ irq_mode, 0x12
.equ svc_mode, 0x13
.equ abt_mode, 0x17
.equ und_mode, 0x1b
.equ sys_mode, 0x1f
.equ swi_vector, 0x4030ce28
.equ rom_swi_b_addr, 0x20008
.equ rom_swi_addr, 0x20028
.equ ram_swi_b_addr, 0x4030CE08
.equ ram_swi_addr, 0x4030CE28
.macro setup_mode mode, stackpointer
mrs r0, cpsr
mov r1, r0
and r1, r1, #0x1f
bic r0, r0, #0x1f
orr r0, r0, #\mode
msr cpsr_csfx, r0
ldr sp, =\stackpointer
bic r0, r0, #0x1f
orr r0, r0, r1
msr cpsr_csfx, r0
.endm
.macro disable_interrupts
mrs r0, cpsr
orr r0, r0, #0x80
msr cpsr_c, r0
.endm
.macro enable_interrupts
mrs r0, cpsr
bic r0, r0, #0x80
msr cpsr_c, r0
.endm
.global _start
_start:
// Initial SP
ldr r3, =_C_STACK_TOP
mov sp, r3
// Set up all the modes' stacks
setup_mode fiq_mode, _FIQ_STACK_TOP
setup_mode irq_mode, _IRQ_STACK_TOP
setup_mode svc_mode, _SVC_STACK_TOP
setup_mode abt_mode, _ABT_STACK_TOP
setup_mode und_mode, _UND_STACK_TOP
setup_mode sys_mode, _C_STACK_TOP
// Clear out BSS
ldr r0, =_bss_start
ldr r1, =_bss_end
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
b _clear_bss_check$
_clear_bss$:
stmia r0!, {r5-r8}
_clear_bss_check$:
cmp r0, r1
blo _clear_bss$
// Load our SWI handler's address into
// the vector table
ldr r0, =_swi_handler
ldr r1, =swi_vector
str r0, [r1]
// Debug-print out these SWI addresses
ldr r0, =rom_swi_b_addr
bl print_mem
ldr r0, =rom_swi_addr
bl print_mem
ldr r0, =ram_swi_b_addr
bl print_mem
ldr r0, =ram_swi_addr
bl print_mem
enable_interrupts
swi_call$:
swi #0xCC
bl kernel_main
b _reset
.global _swi_handler
_swi_handler:
// Get the SWI parameter into r0
ldr r0, [lr, #-4]
bic r0, r0, #0xff000000
// Save lr onto the stack
stmfd sp!, {lr}
bl print_uint32
ldmfd sp!, {pc}
Эти отладочные отпечатки дают ожидаемые значения:
00020008: e59ff018
00020028: 4030ce08
4030ce08: e59ff018
4030ce28: 80200164
(Согласно objdump, 0x80200164 действительно _swi_handler. 0xe59ff018 - это инструкция «ldr pc, [pc, # 0x20]».)
Что мне не хватает? Кажется, что это должно сработать.
0x0
платы (или где бы то ни было реальный вектор). В ARM это не векторная таблица, а векторный код. Я не знаю, имеет ли это какое-то отношение. Как0x0+swi_offset
попадает в вашу рутину? Я бы переключил GPIO, чтобы знать, что он приближается к рутине. Процессоры Cortex позволяют отображать таблицу исключений на значения, отличные от 0x0 и 0xffff0000. - person artless noise   schedule 16.07.2013