首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我的SWI指令挂起?(BeagleBone黑,ARM Cortex-A8 cpu)

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

Stack Overflow用户
提问于 2013-07-15 23:17:29
回答 2查看 2.5K关注 0票数 1

我开始为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,并允许通过串行连接加载二进制文件.

以下是相关的程序集:

代码语言:javascript
复制
.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}

这些调试打印产生预期值:

代码语言:javascript
复制
00020008: e59ff018
00020028: 4030ce08
4030ce08: e59ff018
4030ce28: 80200164

(根据objdump,0x80200164确实是_swi_handler。0xe59ff018是指令"ldr pc,pc,#0x20“)。

我遗漏了什么?看来这应该能行。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-11 07:32:15

板上的固件改变ARM执行模式和与各种模式相关联的向量表的位置。在我自己的例子中(在特权级别1执行并由BBB的uBoot启动的裸代码),活动向量表位于地址0x9f74b000。

通常,您可以使用如下函数来定位活动向量表:

代码语言:javascript
复制
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;
}
票数 1
EN

Stack Overflow用户

发布于 2013-08-05 20:05:05

变化

代码语言:javascript
复制
ldr r0, [lr, #-4]
bic r0, r0, #0xff000000
stmfd sp!, {lr}
bl print_uint32
ldmfd sp!, {pc}

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17665505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档