在嵌入式平台上,printf
所需的系统调用通常不可用。标准的解决方案是编写简单的存根,例如。对于_write
。
我不需要也不想要printf。我需要snprintf
的内部字符串格式。有没有什么方法可以得到它,而不必根除系统调用,这将永远不会被调用?
为了获得内部字符串格式化例程而不得不为系统调用编写存根,这似乎是倒退。
更新
如果我snprintf
一个常量字符buf,它链接良好。这可能是因为编译器去掉了snprintf
,只使用了puts
。
但是如果我有一个"%d"
的字符串,我会得到链接器错误。
编译命令(这篇文章的word wrapped):
$ make flash -B
arm-none-eabi-gcc src/main.c -W -Wall -Wextra -Werror
-Wundef -Wshadow -Wdouble-promotion -Wformat-truncation
-Wconversion -Wno-attributes -DSTM32F446RE -DSTM32F446XX
-DSTM32F4 -g3 -Os -fno-common -ffunction-sections
-fdata-sections -fanalyzer -I. -I./libopencm3/include
-MMD -mcpu=cortex-m4 -mthumb -mfloat-abi=hard
-mfpu=fpv4-sp-d16 -Tconfig/link.ld
--static -nostartfiles -L./libopencm3/lib -lopencm3_stm32f4
-Wl,--fatal-warnings -Wl,--gc-sections -Wl,--cref
-Wl,-Map=firmware.map
-o firmware.elf
错误:
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(lib_a-sbrkr.o): in function `_sbrk_r':
/build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v7e-m+fp/hard/newlib/libc/reent/../../../../../../../../newlib/libc/reent/sbrkr.c:51: undefined reference to `_sbrk'
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(lib_a-abort.o): in function `abort':
/build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v7e-m+fp/hard/newlib/libc/stdlib/../../../../../../../../newlib/libc/stdlib/abort.c:59: undefined reference to `_exit'
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../
...
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libg.a(lib_a-readr.o): in function `_read_r':
/build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v7e-m+fp/hard/newlib/libc/reent/../../../../../../../../newlib/libc/reent/readr.c:49: undefined reference to `_read'
collect2: error: ld returned 1 exit status
2条答案
按热度按时间44u64gxh1#
我会使用一个独立的版本,使最小或零系统调用,并使用堆栈,所以你不必担心并发。
我以前见过一个
sprintf
& friends实现,它根本不调用文件系统。我使用的是Arm mbed项目中的printf。sprintf本身不需要IO,但是因为包含了printf,所以你只需要提供一个小存根:适用于
fpuctc
、FILE
和stdout
我的存根是:
有一个问题,它会与,<stdio.h>但你可能想避免该标题无论如何冲突。它将不可避免地从
reent.h
和诸如此类的东西中拖进来,看起来你的构建不支持。初始化stdout
条目,使其putc_func
驱动您的uart,或任何您更喜欢认为是stdout
的东西。我建议不要删除像
write
和sbrk
这样的东西,因为迟早,你会不小心在newlib中调用一些东西,* 需要这些东西才能正常工作 *,然后你会想为什么你的标准库不能正常工作。如果这些东西不起作用,那么远离newlib中需要它们的部分-如果你不小心调用它们,链接器错误很快就会告诉你,而不是它偶然失败。9wbgstp72#
(Part问题是有些东西想要中止,中止调用printf(而不仅仅是snprintf)。
你可以直接取消abort来防止这种情况。
它看起来也像是有东西想要malloc。如果你有一个嵌入式版本的话,你可能还想去掉malloc,或者使用标准的c库malloc,但是stub out _sbrk告诉它从哪里获取内存。