Hi, all I am trying to run a standalone C program "Hello World" on qemu-system-mipsel, but it failed to print the message via serial port.
What I have done now (step by step): 1. Successfully run a standalone C program "Hello World" on qemu-system-arm, by following this guide: http://balau82.wordpress.com/2010/02/14/simplest-bare-metal-program-for-arm/ 2. Try to run the same standalone C program on qemu-system-mipsel, but it failed. I used GDB to trace the program, and I can make sure the program is working fine, it just failed to print the message via serial port, which mapped to address 0x3f8. I know the qemu MIPS system emulator -m "mipssim" has a PC style serial port (8250 UART). And my code about operating the serial port is following the 8250 spec (http://wiki.osdev.org/Serial_ports) But now, I am stuck to make the 8250 serial port work, any suggestion or sample codes will be appreciated. Here is my compile/link/run commands, and the codes: mips-linux-gnu-gcc -mips32 -EL -c startup.s -o obj/startup.o mips-linux-gnu-gcc -mips32 -EL -static -Wall -Werror -g -msoft-float -nostdlib -fno-exceptions -fno-builtin -nostartfiles -nodefaultlibs -fno-stack-protector -c test.c -o obj/test.o mips-linux-gnu-ld -mips32 -EL -T test.ld obj/startup.o obj/test.o -o bin/test.elf mips-linux-gnu-objcopy -O binary bin/test.elf bin/test.bin qemu-system-mipsel -M mipssim -nographic -kernel bin/test.elf or qemu-system-mipsel -M malta -nographic -kernel bin/test.elf file: test.ld --------------- ENTRY(_Reset) SECTIONS { . = 0x80100400; .startup . : { obj/startup.o(.text) } .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) } . = . + 0x1000; /* 4kB of stack memory */ stack_top = .; } file: startup.s ----------------------- .text .globl _Reset _Reset: lui $sp, %hi(stack_top) addiu $sp, $sp, %lo(stack_top) lui $t9, %hi(c_entry) addiu $t9, %lo(c_entry) jalr $t9 nop hang: b hang file: test.c --------------- void c_entry() { #if 1 init_serial(); print_uart0("Hello world!\n"); #endif #if 0 *(char *)0x3f8 = 'H'; //this also failed too #endif } #define UART0_BASE 0x3f8 /* 8250 COM1 */ void init_serial() { volatile char * addr; addr = (volatile char*)(UART0_BASE + 1); *addr = 0x00; addr = (volatile char*)(UART0_BASE + 3); *addr = 0x80; addr = (volatile char*)(UART0_BASE + 0); *addr = 0x03; addr = (volatile char*)(UART0_BASE + 1); *addr = 0x00; addr = (volatile char*)(UART0_BASE + 3); *addr = 0x03; addr = (volatile char*)(UART0_BASE + 2); *addr = 0xc7; addr = (volatile char*)(UART0_BASE + 4); *addr = 0x0b; } int is_transmit_empty() { volatile char *addr = (volatile char *)(UART0_BASE + 5); return *addr & 0x20; } void write_serial(char a) { while (is_transmit_empty() == 0); volatile char *addr = (volatile char*)UART0_BASE; *addr = a; } void print_uart0(const char *s) { while(*s != '\0') { /* Loop until end of string */ write_serial( *s ); s++; /* Next char */ } }