如何在qemu gumstix(connex / PXA255)仿真中打印出字符串?

时间:2014-10-07 19:46:13

标签: arm qemu

从此网站:http://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/ 我可以使用C代码在qemu模拟器中打印出一个字符串。

volatile unsigned int * const UART0DR = (unsigned int *)0x101f1000;
void print_uart0(const char *s) {
 while(*s != '\0') { /* Loop until end of string */
 *UART0DR = (unsigned int)(*s); /* Transmit char */
 s++; /* Next char */
 }
}

我需要在q代码中使用gumstix connex board(使用-M connex选项)在C代码中执行相同的操作,它使用0x401000000x40700000作为内存映射的uart地址,但没有任何内容显示在屏幕上。

enter image description here enter image description here

我尝试了一些数据检查代码,但它仍然无法正常工作。

volatile unsigned int * const UART0DR = (unsigned int *)0x40100000;
volatile unsigned int * const UART_LSR = (unsigned int *)0x40100014;
#define LSR_TDRQ    (1 << 5)    // Transmit Data Request
void print_uart0(const char *s) {
 while(*s != '\0') { /* Loop until end of string */
    while(( *UART_LSR & LSR_TDRQ ) == 0 ); 
     *UART0DR = (unsigned int)(*s); /* Transmit char */
 s++; /* Next char */
 }
}

可能有什么问题? PXA255使用不同的方式使用uart吗?

我搜索了pxagumstix的源代码,也许gumstix可能会使用不同的方法在qemu中进行hart通信。

4 个答案:

答案 0 :(得分:1)

在链接页面中,您可能已注意到以下文字:

  

模拟QEMU内部串行端口的代码(此处位于源存储库中)实现了ARM的PL011 Prime Cell UART功能的子集

  

PL011串口的QEMU模型忽略了发送FIFO功能;在片上实际系统中,必须先在UARTFR寄存器中检查“发送FIFO满”标志,然后再写入UARTDR寄存器。

由于UART的实施不同,您无法在QEMU和PXA255上使用相同的代码。

要在PXA255板上正确使用UART功能,需要进行更多设置,通常需要执行以下操作:

  • 配置时钟子系统寄存器以确保UART外设从CPU上的主时钟系统接收时钟。
  • 根据所需用途配置UART外设寄存器。您可能需要配置控制波特率寄存器,奇偶校验控制,数据位数的寄存器。
  • 修改写入UART的代码。 UART外设通常包含一个FIFO(有时只是一个字节),在发送和接收期间使用。要传输字符,首先必须确保前一个字符已完成传输,然后将下一个字符发送到输出数据寄存器中。

无法替代详细阅读UART数据表并遵循其中列出的所有信息。

答案 1 :(得分:1)

除非你没有展示其他一些代码,否则你在这里遗漏了几件重要的事情:

  • 必须先启用UART模块的时钟和电源,然后才能运行。请参阅PXA255手册的第3部分。
  • 必须在UART正常工作之前配置UART使用的GPIO(例如,通过设置适当的引脚方向和备用功能)。请参阅PXA255手册的4.1节。
  • 在开始向其写入数据之前,必须配置UART(例如,波特率等)。 PXA255手册没有明确包含有关这些寄存器的信息;您需要交叉引用16550数据表。
  • 在向UART写入数据时,必须确保UART处于适当的状态以接收数据(例如,发送缓冲区未满),并等待它进入适当的状态(如果不是)。请参阅16550数据表,或有关使用此UART的一般教程。

QEMU中的UART实现旨在作为调试工具,而非真实设备中UART的完整仿真。仅仅因为在QEMU中有效的东西并不意味着它可以在真正的硬件上运行!

答案 2 :(得分:1)

对于UART的准确仿真,应该放松qemu。 下面的代码有效:

的Startup.s:

.global startup
startup:
   ldr sp, startup_stack_top
   bl c_startup
   b .
startup_stack_top:
   .word 0xa4000000

os.c:

void write_uart(char *str)
{
    char c;
    volatile char *uart = (char *)0x40100000;
    while (1) {
        c = *str;
        if (!c)
            break;
        *uart = c;
        str++;
    }
}
void c_startup() 
{
    write_uart("hello\r\n");
}

链接描述文件os.ld:

ENTRY(startup)
SECTIONS
{
   . = 0x0;
   .startup : { startup.o(.text) }
   .text : { *(.text) }
   .rodata : { *(.rodata) }
   .data : { *(.data) }
   .bss : { *(.bss COMMON) }
}

构建命令:

#pfx=arm-none-eabi-

$(pfx)as -g -march=armv5te startup.s -o startup.o
$(pfx)gcc -g -c -march=armv5te os.c -o os.o
$(pfx)ld -T os.ld os.o startup.o -o os.elf
$(pfx)objcopy -O binary os.elf os.bin
dd of=flash.img bs=128k count=128 if=/dev/zero
dd of=flash.img bs=128k conv=notrunc if=os.bin

运行命令:

qemu-system-arm -M connex -m 128M  -snapshot -pflash flash.img

答案 3 :(得分:0)

正如Austin Phillips指出的那样,它需要大量的设置代码才能使其与UART串行通信协同工作。让我感到困惑的是,我可以在没有qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin任何设置的情况下使UART通信工作,但这是多功能板仿真。我的猜测是,对于versatilepb板,UART设置刚刚在我的二进制运行之前完成。

模仿,我做的是使用uboot,它完成所有的UART设置,并从uboat加载我的二进制图像,一切正常。