【问题标题】:Issues with ARMv7-A bare metal call stack [duplicate]ARMv7-A 裸机调用堆栈的问题 [重复]
【发布时间】:2015-06-15 15:27:12
【问题描述】:

我正在尝试在 QEMU(Cortex-A15 的 Versatile Express)上启动并运行一个小型 ARM 内核。目前它只是将sp 设置为一个小堆栈的顶部,并将单个字符发送到UART0。


_start.arm:

.set stack_size, 0x10000
.comm stack, stack_size

.global _start
_start:
    ldr sp, =stack+stack_size
    bl start
1:
    b 1b
.size _start, . - _start

start.c:

/* UART_0 is a struct overlaid on 0x1c090000 */

void printChar(char c)
{
    while (UART_0->flags & TRANSMIT_FULL);
    UART_0->data = c;
}

void start()
{
    while (UART_0->flags & TRANSMIT_FULL);
    UART_0->data = 'A';

    printChar('a');
}

从 GDB,我知道执行过程通过_start 进入start 并成功将'A' 发送到 UART_0。 printChar 被调用并完成,但似乎没有向串口打印任何内容。在没有 GDB 的情况下运行时,内核会反复打印 'A',但我不确定这是处理器重置还是错误跳转。

来自objdump

Disassembly of section .stub:
00010000 <_start>:
   10000:   e59fd004    ldr sp, [pc, #4]    ; 1000c <__STACK_SIZE+0xc>
   10004:   eb000016    bl  10064 <start>
   10008:   eafffffe    b   10008 <_start+0x8>
   1000c:   000200d0    .word   0x000200d0

Disassembly of section .text:
00010010 <printChar>:
   10010:   e52db004    push    {fp}        ; (str fp, [sp, #-4]!)
   10014:   e28db000    add fp, sp, #0
   10018:   e24dd00c    sub sp, sp, #12
   1001c:   e1a03000    mov r3, r0
   10020:   e54b3005    strb    r3, [fp, #-5]
   10024:   e1a00000    nop         ; (mov r0, r0)
   10028:   e3a03000    mov r3, #0
   1002c:   e3413c09    movt    r3, #7177   ; 0x1c09
   10030:   e1d331ba    ldrh    r3, [r3, #26]
   10034:   e6ff3073    uxth    r3, r3
   10038:   e2033020    and r3, r3, #32
   1003c:   e3530000    cmp r3, #0
   10040:   1afffff8    bne 10028 <printChar+0x18>
   10044:   e3a03000    mov r3, #0
   10048:   e3413c09    movt    r3, #7177   ; 0x1c09
   1004c:   e55b2005    ldrb    r2, [fp, #-5]
   10050:   e6ff2072    uxth    r2, r2
   10054:   e1c320b2    strh    r2, [r3, #2]
   10058:   e24bd000    sub sp, fp, #0
   1005c:   e49db004    pop {fp}        ; (ldr fp, [sp], #4)
   10060:   e12fff1e    bx  lr

00010064 <start>:
   10064:   e52db008    str fp, [sp, #-8]!
   10068:   e58de004    str lr, [sp, #4]
   1006c:   e28db004    add fp, sp, #4
   10070:   e1a00000    nop         ; (mov r0, r0)
   10074:   e3a03000    mov r3, #0
   10078:   e3413c09    movt    r3, #7177   ; 0x1c09
   1007c:   e1d331ba    ldrh    r3, [r3, #26]
   10080:   e6ff3073    uxth    r3, r3
   10084:   e2033020    and r3, r3, #32
   10088:   e3530000    cmp r3, #0
   1008c:   1afffff8    bne 10074 <start+0x10>
   10090:   e3a03000    mov r3, #0
   10094:   e3413c09    movt    r3, #7177   ; 0x1c09
   10098:   e5d32002    ldrb    r2, [r3, #2]
   1009c:   e3a02000    mov r2, #0
   100a0:   e3822041    orr r2, r2, #65 ; 0x41
   100a4:   e5c32002    strb    r2, [r3, #2]
   100a8:   e5d32003    ldrb    r2, [r3, #3]
   100ac:   e3a02000    mov r2, #0
   100b0:   e5c32003    strb    r2, [r3, #3]
   100b4:   e3a00061    mov r0, #97 ; 0x61
   100b8:   ebffffd4    bl  10010 <printChar>
   100bc:   e24bd004    sub sp, fp, #4
   100c0:   e59db000    ldr fp, [sp]
   100c4:   e28dd004    add sp, sp, #4
   100c8:   e49df004    pop {pc}        ; (ldr pc, [sp], #4)

000100cc <UART_0>:
   100cc:   1c090000                                ....

【问题讨论】:

  • PINSEL/UART/其他设置在哪里? UART 上电了吗?
  • 外围设备由 QEMU 处理(使用-kernel 启动),它将二进制文件加载到0x10000 的内存中。 UART 肯定是通电的,因为我可以从_startstart() 给它写信;问题是在函数调用期间写入它。
  • 在调用 start 之前安装一个异常向量。这会告诉你到底出了什么问题。如果您返回异常原因,人们将能够朝正确的方向挖掘。
  • @Notlikethat 让我印象深刻,就是这样!堆栈在 Flash 中,我只需要将它移到 PSRAM 中。
  • 好东西。顺便说一句,不要因为受骗而感到羞耻 - 裸机都是关于出乎意料的方式,事情可能会因不明显的症状而出错;)

标签: c assembly arm bare-metal


【解决方案1】:

我可能错过了一些东西,但我没有看到你在哪里启用了中断,或者轮询看看你是否可以发送下一个字符。如果您启用了中断并正确设置了 UART 硬件,那么您的驱动程序可能存在错误。如果您没有正确设置 UART 硬件,它可能不会产生中断,或者它可能没有正确执行 FIFO,或者其他任何问题。

【讨论】:

  • 问题是,我知道 UART 正在工作,因为发送并打印了第一个字符。只有在使用打印不起作用的功能时。
  • 我从上面看到这是一个堆栈问题 - 我很高兴你找到了答案。我确实错过了投票,所以我很抱歉。
猜你喜欢
  • 1970-01-01
  • 2012-05-15
  • 2011-07-05
  • 2018-05-11
  • 2019-08-10
  • 2011-11-28
  • 2017-06-07
  • 1970-01-01
  • 2018-04-28
相关资源
最近更新 更多