我开始为BeagleBone黑编写一个玩具操作系统,它使用了基于ARM Cortex-A8的TI Sitara AM3359 SoC和uses引导程序。我有一个简单的、独立的hello world应用程序编写到UART0,到目前为止我可以加载U,现在我尝试继续中断处理程序,但是除了挂起设备之外,我什么也做不了。
根据AM335x TRM (从4099页开始,如果您感兴趣的话),中断向量表在ROM中映射为0x20000。ROM SWI处理程序在0x4030ce08处向RAM分支,这将分支到存储在0x4030ce28上的地址。(最初,这是0x20084中唯一的死循环。)
我的代码将所有ARM处理器模式的SP设置到RAM顶部的它们自己的区域,并在CPSR中启用中断,然后执行SWI指令,这条指令总是挂起。(也许会跳到某个死胡同指令?)我看了一堆样本,并阅读了我能找到的任何文档,我不知道我缺少了什么。
目前,我与板的唯一交互是通过UART0上与我的linux盒的串行连接。UART0初始化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“)。
我遗漏了什么?看来这应该能行。
发布于 2014-05-11 07:32:15
板上的固件改变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;
}发布于 2013-08-05 20:05:05
变化
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模式开关存储的寄存器。
https://stackoverflow.com/questions/17665505
复制相似问题