2015-06-15 50 views
2

我试图在QEMU(Cortex-A15的Versatile Express)上启动并运行一个小的ARM内核。目前它只是将sp设置为小堆栈的顶部,并将单个字符发送到UART0。ARMv7-A裸机调用堆栈问题


_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,我知道,执行进展通过_startstart,并成功地将'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        .... 
+0

PINSEL/UART /无论什么设置? UART是否通电? –

+0

外设由QEMU(使用'-kernel'启动)处理,它将二进制文件加载到内存0x10000处。由于我可以从'_start'和'start()'写入UART,因此UART已经上电。问题是在函数调用期间写入它。 –

+0

在调用开始之前安装异常向量。这会告诉你究竟发生了什么错误。如果你回到异常的原因,人们可以挖掘正确的方向。 –

回答

0

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

+0

事情是,我知道UART工作,因为第一个字符发送和打印。只有在使用打印功能不起作用的功能时。 –

+0

我从上面看到这是一个堆栈的东西 - 我很高兴你找到答案。我确实错过了投票,所以我很抱歉。 – sid1138