赞
踩
本文将详细阐述如何利用 printf
来打印字符串,在此过程中使用了一个开源的库 xprintf
。xprintf
是一个紧凑的字符串 I/O 库,它非常适用于程序存储器不足以用于常规 printf 函数的微型微控制器。通过调用 xprintf
函数成功输出了“Hello RISC-V World!”,同时还对该库的使用方法以及如何进行编译等内容加以介绍。xprintf
库的地址为:http://elm-chan.org/fsw/strf/xprintf.html,下载后使将使用xprintf.c
和xprintf.h
两个文件。
// ------------------------------------------------------------------------------------------------- // Copyright 2024 Kearn Chen, kearn.chen@aliyun.com // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ------------------------------------------------------------------------------------------------- // Description : // 1. Run Hello World! // ------------------------------------------------------------------------------------------------- task initcase; load_instr("hello_world_test/hello_world_test.bin"); endtask task testcase; #2_000_000; endtask
在验证用例中,任务initcase
加载Bin文件到仿真模型中,任务testcase
延迟2毫秒,等待CPU执行完软件指令。
// ------------------------------------------------------------------------------------------------- // Copyright 2024 Kearn Chen, kearn.chen@aliyun.com // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ------------------------------------------------------------------------------------------------- #include "xprintf.h" void xfunc_output_callback(int c) { *((volatile unsigned int *)0xc0000) = c; } void simulation_finish(void) { *((volatile unsigned int *)0xc0004) = 0x12345678; } int main(void) { xfunc_output = xfunc_output_callback; xprintf("Hello RISC-V World!\n"); simulation_finish(); while(1); }
上述代码中,首先是初始化打印输出的回调函数,在回调函数中,将要输出的字符写入地址0xc0000寄存器中,这个寄存器在之前的文章【RISC-V设计-12】- RISC-V处理器设计K0A之验证环境中第4部分有描述,写入此寄存器的数据会存入到一个队列里面,在遇到输出字符为\n
时,将整个队列内的输出到终端。在输出完字符后,调用simulation_finish
函数,仿真运行结束。在xprintf
库中,有一些宏定义,如下所示,根据需要可以打开和关闭。
#define XF_USE_OUTPUT 1 /* 1: Enable output functions */
#define XF_CRLF 0 /* 1: Convert \n ==> \r\n in the output char */
#define XF_USE_DUMP 0 /* 1: Enable put_dump function */
#define XF_USE_LLI 0 /* 1: Enable long long integer in size prefix ll */
#define XF_USE_FP 0 /* 1: Enable support for floating point in type e and f */
#define XF_DPC '.' /* Decimal separator for floating point */
#define XF_USE_INPUT 0 /* 1: Enable input functions */
#define XF_INPUT_ECHO 0 /* 1: Echo back input chars in xgets function */
ENTRY( _start ) __stack_size = 2048; PROVIDE( _stack_size = __stack_size ); MEMORY { ROM (rx) : ORIGIN = 0x00000, LENGTH = 512K RAM (xrw) : ORIGIN = 0x80000, LENGTH = 256K } SECTIONS { .init : { _sinit = .; . = ALIGN(4); KEEP(*(SORT_NONE(.init))) . = ALIGN(4); _einit = .; } >ROM .text : { . = ALIGN(4); *(.text) *(.text.*) *(.rodata) *(.rodata*) *(.gnu.linkonce.t.*) . = ALIGN(4); } >ROM .fini : { KEEP(*(SORT_NONE(.fini))) . = ALIGN(4); } >ROM PROVIDE( _etext = . ); PROVIDE( _eitcm = . ); .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } >ROM .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); } >ROM .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } >ROM .ctors : { KEEP (*crtbegin.o(.ctors)) KEEP (*crtbegin?.o(.ctors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } >ROM .dtors : { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } >ROM .dalign : { . = ALIGN(4); PROVIDE(_data_vma = .); } >RAM AT>ROM .dlalign : { . = ALIGN(4); PROVIDE(_data_lma = .); } >ROM .data : { . = ALIGN(4); *(.gnu.linkonce.r.*) *(.data .data.*) *(.gnu.linkonce.d.*) . = ALIGN(8); PROVIDE( __global_pointer$ = . + 0x800 ); *(.sdata .sdata.*) *(.sdata2*) *(.gnu.linkonce.s.*) . = ALIGN(8); *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) . = ALIGN(4); PROVIDE( _edata = .); } >RAM AT>ROM .bss : { . = ALIGN(4); PROVIDE( _sbss = .); *(.sbss*) *(.gnu.linkonce.sb.*) *(.bss*) *(.gnu.linkonce.b.*) *(COMMON*) . = ALIGN(4); PROVIDE( _ebss = .); } >RAM AT>ROM PROVIDE( _end = _ebss); PROVIDE( end = . ); .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : { PROVIDE( _heap_end = . ); . = ALIGN(4); PROVIDE(_susrstack = . ); . = . + __stack_size; PROVIDE( _eusrstack = .); } >RAM }
# ------------------------------------------------------------------------------------------------- # Copyright 2024 Kearn Chen, kearn.chen@aliyun.com # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ------------------------------------------------------------------------------------------------- PREFIX := riscv-none-embed- LINKER := ../common/link.ld OBJECT += ../common/startup.o OBJECT += ../common/xprintf.o OBJECT += main.o CFLAGS := -march=rv32e -mabi=ilp32e -I../common LFLAGS := -march=rv32e -mabi=ilp32e -T$(LINKER) -nostartfiles TARGET := $(notdir $(shell pwd)) all : $(TARGET).asm $(TARGET).bin %.bin : %.elf $(PREFIX)objcopy -Obinary $< $@ %.asm : %.elf $(PREFIX)objdump -D $< > $@ %.elf : $(OBJECT) $(PREFIX)gcc $(LFLAGS) -o $@ $^ $(PREFIX)size $@ %.o : %.S $(PREFIX)gcc $(CFLAGS) -c -o $@ $< %.o : %.c $(PREFIX)gcc $(CFLAGS) -c -o $@ $< clean : @rm -rf *.o *.elf *.asm *.bin ../common/*.o .PHONY: clean all .SECONDARY:
上述脚本中所使用的startup.o文件为startup.S文件所编译产生,这个文件在之前的文章【RISC-V设计-09】- RISC-V处理器设计K0A之CIC中第5部分已有介绍,这个文件为RISCV-K0A
的启动文件,同时还具有中断处理的功能。编译结果如下
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -I../common -c -o ../common/startup.o ../common/startup.S
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -I../common -c -o ../common/xprintf.o ../common/xprintf.c
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -I../common -c -o main.o main.c
riscv-none-embed-gcc -march=rv32e -mabi=ilp32e -T../common/link.ld -nostartfiles -o hello_world_test.elf ../common/startup.o ../common/xprintf.o main.o
riscv-none-embed-size hello_world_test.elf
text data bss dec hex filename
3164 0 2056 5220 1464 hello_world_test.elf
riscv-none-embed-objdump -D hello_world_test.elf > hello_world_test.asm
riscv-none-embed-objcopy -Obinary hello_world_test.elf hello_world_test.bin
*Verdi* FSDB WARNING: The FSDB file already exists. Overwriting the FSDB file may crash the programs that are using this file.
*Verdi* : Create FSDB file 'novas.fsdb'
*Verdi* : Begin traversing the scopes, layer (0).
*Verdi* : End of traversing.
[MCU_INFO] : Hello RISC-V World!
$finish called from file "../env/slave_model.v", line 136.
$finish at simulation time 43210
本文介绍了如何在RISCV-K0A
上使用xprintf
库文件,并通过xprintf
输出了"Hello RISC-V World!"到终端显示。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。