Arm 为什么我的SWI指令挂起?(BeagleBone黑色,手臂皮质-A8 cpu)

Arm 为什么我的SWI指令挂起?(BeagleBone黑色,手臂皮质-A8 cpu),arm,interrupt,beagleboard,cortex-a,Arm,Interrupt,Beagleboard,Cortex A,我开始为编写一个玩具操作系统,它使用基于ARM Cortex-A8和U-Boot引导加载程序。我有一个简单的独立的hello world应用程序写入UART0,到目前为止我可以通过U-Boot加载,现在我正试图继续中断处理程序,但我无法让SWI做任何事情,只能挂起设备 根据AM335x TRM(如果您感兴趣,请从第4099页开始),中断向量表映射到ROM中的0x20000处。ROM SWI处理程序分支到0x4030ce08处的RAM,该RAM分支到存储在0x4030ce28处的地址。(最初,这是

我开始为编写一个玩具操作系统,它使用基于ARM Cortex-A8和U-Boot引导加载程序。我有一个简单的独立的hello world应用程序写入UART0,到目前为止我可以通过U-Boot加载,现在我正试图继续中断处理程序,但我无法让SWI做任何事情,只能挂起设备

根据AM335x TRM(如果您感兴趣,请从第4099页开始),中断向量表映射到ROM中的0x20000处。ROM SWI处理程序分支到0x4030ce08处的RAM,该RAM分支到存储在0x4030ce28处的地址。(最初,这是0x20084处唯一的死循环。)

我的代码将所有ARM处理器模式的SP设置到RAM顶部各自的区域,并启用CPSR中的中断,然后执行一条始终挂起的SWI指令。(可能是跳转到某个死循环指令?)我看了一堆样本,阅读了我能找到的任何文档,但我看不到我遗漏了什么

目前,我与主板的唯一交互是通过UART0上的串行连接与我的linux机箱进行的。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”)

我错过了什么?看来这应该行得通。

改变

ldr r0, [lr, #-4]
bic r0, r0, #0xff000000
stmfd sp!, {lr}
bl print_uint32
ldmfd sp!, {pc}


PS:您不需要将SPSR恢复到中断任务的CPSR中,您还需要清除cpu模式开关未存储的寄存器。

板上的固件会更改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;
}
静态内联无符号整数*获取向量地址(void)
{
无符号整数v;
/*读SCTLR*/
__asm\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
:“=r”(v):);

如果(v&(1)SWI CC应该做什么?也许它需要以某种方式设置寄存器或模式?只是猜测,因为没有调试器,您将很难准确地看到发生了什么。是的,很遗憾,我没有JTAG调试器。SWI忽略其参数,并导致软件中断,该中断会跳到in中的相应位置terrupt vector table。因此,假设它应该命中ROM表中到RAM表的分支,然后分支到_swi_处理程序。我传递给它的0xCC值只是为了测试目的-在_swi_处理程序中的前两条指令应该将swi指令加载到r0中,并清除掉swi,只留下参数。谁知道呢?我们需要看到v电路板
0x0
处的值(或实向量所在的位置)。在ARM上,它不是向量表,而是向量代码。我不知道这是否有任何关联。
0x0+swi_offset
如何进入例程?我会切换GPIO以知道它正在进入例程。Cortex处理器允许将异常表映射到0x0和0xffff0000以外的值。对,正如我所说,该表位于如调试结果所示,0x20008是[0x20028]或0x4030ce08的分支。同样,0x4030ce08是到[0x4030ce28]的跳转,其中包含我的处理程序的地址0x80200164。切换GPIO是一个好主意。这比我当前收到的串行消息更简单。使GPIO切换尽可能简单。显式加载每个寄存器,不使用堆栈或任何内存。可能是SWI处理程序无法获得控制,或者环境不正确。有些时间表明明显的是有帮助的;-)谢谢。这不是我目前的问题,但我相信最终会成为一个问题。嗯,因为它是cortex-A8 cpu,您是否尝试过干预VBAR寄存器并创建自己的向量表?请参阅“3.2.68.c12,安全或非安全向量基址寄存器”在cortex-A8 TRM中。在线版本:是的,我假设ARM只是因为OP的硬编码lr delta,他没有提到任何地方的thumb。啊。自从我还在使用CPU时,我就假设向量表仍然在TRM中的地址,所以我根本没有检查VBAR。谢谢!我被其他项目从这个项目中拉了出来ects,但我今晚会回去试试。谢谢!
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;
}