我开始为BeagleBone Black编写一个玩具操作系统,它使用基于ARM Cortex-A8的TI Sitara AM3359 SoC和U-Boot启动加载程序。我有一个简单的独立hello world应用程序写入UART0,我可以通过U-Boot加载到目前为止,现在我正在尝试继续中断处理程序,但我不能让SWI做任何事情,但挂起设备
根据AM335x TRM(从第4099页开始,如果您感兴趣),中断向量表将映射到ROM20000的0x20000。 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]”。)
我错过了什么? 似乎就像这应该有效。
答案 0 :(得分:1)
变化
ldr r0, [lr, #-4]
bic r0, r0, #0xff000000
stmfd sp!, {lr}
bl print_uint32
ldmfd sp!, {pc}
到
stmfd sp!, {r0-r3, r12, lr}
ldr r0, [lr, #-4]
bic r0, r0, #0xff000000
bl print_uint32
ldmfd sp!, {r0-r3, r12, pc}^
PS:您没有将SPSR恢复到中断任务的CPSR中,并且还会划分未通过cpu模式开关存储的寄存器。
答案 1 :(得分:1)
主板上的固件会更改ARM的执行模式和位置 与各种模式相关联的向量表。在我自己的情况下(裸机 在权限级别1执行并由BBB的uBoot启动的代码段代码,活动向量表位于地址0x9f74b000。
通常,您可以使用类似以下功能的内容来定位 活动向量表:
static inline unsigned int *get_vectors_address(void)
{
unsigned int v;
/* read SCTLR */
__asm__ __volatile__("mrc p15, 0, %0, c1, c0, 0\n"
: "=r" (v) : : );
if (v & (1<<13))
return (unsigned int *) 0xffff0000;
/* read VBAR */
__asm__ __volatile__("mrc p15, 0, %0, c12, c0, 0\n"
: "=r" (v) : : );
return (unsigned int *) v;
}