2013-07-15 33 views
1

我开始为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]“。)

我错过了什么?它似乎这样应该工作。

+0

什么是SWI CC该怎么办?也许它需要寄存器或模式以某种方式设置?只是在没有调试器的情况下猜测,你将很难看清发生了什么。 –

+0

是的,可惜我没有JTAG调试器。 SWI忽略它的参数,并引起软件中断,该软件中断跳转到中断向量表中的相应位置。所以应该是,它应该将ROM表中的分支打到RAM表中,然后分支到_swi_handler。我传递它的0xCC值仅用于测试目的 - 在_swi_handler中的前两条指令应该将SWI指令加载到r0中,并清除SWI,只留下参数。 – justinian

+0

谁知道?我们需要看到板的0x0处的值(或者真正的矢量所在的位置)。在* ARM *上,它不是一个向量表,而是*向量代码*。我不知道这是否有任何相关性。 '0x0 + swi_offset'如何得到你的例程?我会切换GPIO以知道它正在进入例程。 Cortex处理器允许将异常表映射到0x0和0xffff0000以外的值。 –

回答

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; 
} 
+0

啊。我曾经假设自从我还在开发CPU时,向量表仍然在TRM的地址中,所以我根本没有检查VBAR。谢谢!我已经被其他项目从这个项目中拉出来了,但我今晚会回去尝试一下。谢谢! – justinian

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模式切换寄存器组。

+0

谢谢。这不是我目前的问题,但我相信这最终会成为问题。 – justinian

+0

嗯,因为它是一个cortex-A8 cpu,你有没有试过插手VBAR寄存器并创建你自己的向量表?请参见cortex-A8 TRM中的“3.2.68。c12,安全或非安全向量基址寄存器”。在线版本:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babfbcae.html – sgupta

+0

这只适用于基于手臂的swi调用,而不是基于拇指... –