QEMU OpenSBI 裸机开发之格式化打印
格式化打印代码也跟之前的基本一样,就是将字符输出函数从原来的直接操作16550寄存器改为通过SBI接口进行字符输出,其他的都一样,将printf函数定义在printf.c中,如下所示。
#include <stdarg.h> #include "sbi.h" static void uart_putc(char c) { sbi_console_putchar(c); } //printf functions static char digits[] = "0123456789abcdef"; static void print_int(int xx, int base, int sign) { char buf[16]; int i; unsigned int x; if(sign && (sign = xx < 0)) x = -xx; else x = xx; i = 0; do { buf[i++] = digits[x % base]; } while((x /= base) != 0); if(sign) buf[i++] = '-'; while(--i >= 0) uart_putc(buf[i]); } static void print_ptr(unsigned long x) { int i; uart_putc('0'); uart_putc('x'); for (i = 0; i < (sizeof(unsigned long) * 2); i++, x <<= 4) uart_putc(digits[x >> (sizeof(unsigned long) * 8 - 4)]); } // Print to the console. only understands %d, %x, %p, %s. void printf(char *fmt, ...) { va_list ap; int i, c; char *s; if (fmt == 0) return; va_start(ap, fmt); for(i = 0; (c = fmt[i] & 0xff) != 0; i++) { if(c != '%'){ uart_putc(c); continue; } c = fmt[++i] & 0xff; if(c == 0) break; switch(c){ case 'd': print_int(va_arg(ap, int), 10, 1); break; case 'x': print_int(va_arg(ap, int), 16, 1); break; case 'p': print_ptr(va_arg(ap, unsigned long)); break; case 's': if((s = va_arg(ap, char*)) == 0) s = "(null)"; for(; *s; s++) uart_putc(*s); break; case '%': uart_putc('%'); break; default: // Print unknown % sequence to draw attention. uart_putc('%'); uart_putc(c); break; } } }
将“start.c”中的打印换成printf,如下所示。
#include "printf.h" void start(void) { printf("%s %d.\r\n", __func__, __LINE__); }
在命令行执行“make qemu”,可以在最后看到打印的函数名以及行号信息,如下所示。
gewenbin@gewenbin-virtual-machine:~/Desktop/qemu_test/lesson13$ make qemu riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -c -o printf.o printf.c riscv64-unknown-elf-ld -z max-page-size=4096 -T kernel.ld -o kernelimage entry.o start.o printf.o riscv64-unknown-elf-objdump -S kernelimage > kernel.asm riscv64-unknown-elf-objdump -t kernelimage | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > kernel.sym qemu-system-riscv64 -machine virt -bios fw_jump.elf -kernel kernelimage -m 128M -smp 1 -nographic OpenSBI v0.8-81-g7dcb1e1 ____ _____ ____ _____ / __ \ / ____| _ \_ _| | | | |_ __ ___ _ __ | (___ | |_) || | | | | | '_ \ / _ \ '_ \ \___ \| _ < | | | |__| | |_) | __/ | | |____) | |_) || |_ \____/| .__/ \___|_| |_|_____/|____/_____| | | |_| Platform Name : riscv-virtio,qemu Platform Features : timer,mfdeleg Platform HART Count : 1 Firmware Base : 0x80000000 Firmware Size : 112 KB Runtime SBI Version : 0.2 Domain0 Name : root Domain0 Boot HART : 0 Domain0 HARTs : 0* Domain0 Region00 : 0x0000000080000000-0x000000008001ffff () Domain0 Region01 : 0x0000000000000000-0xffffffffffffffff (R,W,X) Domain0 Next Address : 0x0000000080200000 Domain0 Next Arg1 : 0x0000000082200000 Domain0 Next Mode : S-mode Domain0 SysReset : yes Boot HART ID : 0 Boot HART Domain : root Boot HART ISA : rv64imafdcsu Boot HART Features : scounteren,mcounteren,time Boot HART PMP Count : 16 Boot HART PMP Granularity : 4 Boot HART PMP Address Bits: 54 Boot HART MHPM Count : 0 Boot HART MHPM Count : 0 Boot HART MIDELEG : 0x0000000000000222 Boot HART MEDELEG : 0x000000000000b109 start 5.
工程源码:链接:https://pan.baidu.com/s/1TnTYr7mywdKj5bxpdmWnyA,提取码:q772,见lesson13。
评论