为什么我的SWI指令挂起? (BeagleBone Black,ARM Cortex-A8 cpu)

时间:2013-07-15 23:17:29

标签: arm interrupt beagleboard cortex-a

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

我错过了什么? 似乎就像这应该有效。

2 个答案:

答案 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;
}