我开始为BeagleBone Black编写玩具操作系统,它使用基于ARM Cortex-A8的TI Sitara AM3359 SoC和U-Boot引导加载程序。我有一个简单的hello world应用程序写入UART0,目前我可以通过U-Boot加载,现在我试图继续中断处理程序,但我无法让SWI去做任何事情,设备。为什么我的SWI指令挂起? (BeagleBone Black,ARM Cortex-A8 cpu)
根据AM335x TRM(从第4099页开始,如果您有兴趣),中断向量表映射到0x20000的ROM中。 ROM SWI处理程序分支到0x4030ce08处的RAM,分支到存储在0x4030ce28处的地址。 (最初,这是一个独特的死循环,位于0x20084处)。
我的代码将所有ARM处理器模式的SP设置到RAM顶部各自的区域,并启用CPSR中的中断,然后执行SWI指令,它总是挂起。 (也许跳到一些死循环指令?)我看了一大堆样本,并阅读了我能找到的任何文档,但我看不到我错过了什么。
目前我与主板之间的唯一交互是通过我的Linux机箱与UART0进行串口连接。 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]“。)
我错过了什么?它似乎这样应该工作。
什么是SWI CC该怎么办?也许它需要寄存器或模式以某种方式设置?只是在没有调试器的情况下猜测,你将很难看清发生了什么。 –
是的,可惜我没有JTAG调试器。 SWI忽略它的参数,并引起软件中断,该软件中断跳转到中断向量表中的相应位置。所以应该是,它应该将ROM表中的分支打到RAM表中,然后分支到_swi_handler。我传递它的0xCC值仅用于测试目的 - 在_swi_handler中的前两条指令应该将SWI指令加载到r0中,并清除SWI,只留下参数。 – justinian
谁知道?我们需要看到板的0x0处的值(或者真正的矢量所在的位置)。在* ARM *上,它不是一个向量表,而是*向量代码*。我不知道这是否有任何相关性。 '0x0 + swi_offset'如何得到你的例程?我会切换GPIO以知道它正在进入例程。 Cortex处理器允许将异常表映射到0x0和0xffff0000以外的值。 –