我正在运行带有ARM Cortex-M3(STM32F205)的裸机嵌入式系统.当我尝试使用snprintf()浮点数时,例如:
float f;
f = 1.23;
snprintf(s, 20, "%5.2f", f);
Run Code Online (Sandbox Code Playgroud)
我得到了垃圾s.格式似乎很荣幸,即垃圾是一个格式良好的字符串,包含数字,小数点和两个尾随数字.但是,如果我重复snprintf,则字符串可能会在两次调用之间发生变化.
浮点数学似乎在其他方面起作用,并且snprintf与整数一起工作,例如:
snprintf(s, 20, "%10d", 1234567);
Run Code Online (Sandbox Code Playgroud)
我使用链接器开关的newlib-nano实现-u _printf_float.编译器是arm-none-eabi-gcc.
我确实怀疑内存分配问题,因为整数打印没有任何打嗝,但浮动表现就好像它们在过程中被破坏一样.该printf系列函数调用malloc用浮漂,不是整数.
唯一不属于newlib我在此上下文中使用的代码是my _sbrk(),这是必需的malloc.
caddr_t _sbrk(int incr)
{
extern char _Heap_Begin; // Defined by the linker.
extern char _Heap_Limit; // Defined by the linker.
static char* current_heap_end;
char* current_block_address;
// first allocation
if (current_heap_end == 0)
current_heap_end = &_Heap_Begin; …Run Code Online (Sandbox Code Playgroud) sigemptyset在Newlib下使用Cygwin 时,我们正在捕获编译器错误.C++编译器发生错误,但仅在-std=XXX使用时发生.如果没有标准选项,测试程序将按预期编译和执行.
测试程序如下,感兴趣的Cygwin标题如下.我没有在Cygwin标题中看到任何可疑的东西.
我曾经尝试过#define _GNU_SOURCE和伎俩#define _XOPEN_SOURCE 700.我也尝试过使用全局和std名称空间等技巧.相关,请参阅-D_XOPEN_SOURCE做什么/意味着什么?和c ++ 11中的命名空间问题?.
是什么导致编译失败,我该如何解决?
$ cat ~/test.cxx
#include <signal.h>
int main(int argc, char* argv[])
{
struct sigaction new_handler;
return sigemptyset(&new_handler.sa_mask);
}
Run Code Online (Sandbox Code Playgroud)
如果没有-std=XXX,它会导致:
$ g++ -c test.cxx
$
Run Code Online (Sandbox Code Playgroud)
使用a -std=XXX,它会导致:
$ g++ -std=c++03 -c test.cxx
test.cxx: In function int main(int, char**):
test.cxx:6:44: error: sigemptyset was not declared in this scope
return sigemptyset(&new_handler.sa_mask);
Run Code Online (Sandbox Code Playgroud)
当尝试sigemptyset在全局命名空间中使用时:
$ g++ -std=c++03 -c …Run Code Online (Sandbox Code Playgroud) 这个问题涉及arm-none-eabi-g ++ 6.2并且与newlib-nano相关联.
当我预处理C源代码时-specs=nano.specs,包含newlib.h目录中的文件newlib-nano:
echo '#include <string.h>' |\
/opt/gcc-arm-none-eabi-6_2-2016q4/bin/arm-none-eabi-gcc -specs=nano.specs -x c -E - |\
grep '^# 1 .*newlib\.h'
Run Code Online (Sandbox Code Playgroud)
产出# 1 "/opt/gcc-arm-none-eabi-6_2-2016q4/arm-none-eabi/include/newlib-nano/newlib.h" 1 3 4(如预期).这是因为该文件nano.specs包含(以及其他)行
%rename cpp nano_cpp
*cpp:
-isystem =/include/newlib-nano %(nano_cpp)
Run Code Online (Sandbox Code Playgroud)
但是,如果我通过相同的编译器提供C++源代码
echo '#include <string.h>' |\
/opt/gcc-arm-none-eabi-6_2-2016q4/bin/arm-none-eabi-gcc -specs=nano.specs -x c++ -E - |\
grep '^# 1 .*newlib\.h'
Run Code Online (Sandbox Code Playgroud)
输出读取# 1 "/opt/gcc-arm-none-eabi-6_2-2016q4/arm-none-eabi/include/newlib.h" 1 3.
换句话说:specs-file被忽略.
我知道我应该包含<cstring>而不是<string.h>在C++源代码中,并且GNU g ++通常被调用…/arm-none-eabi-c++而不是,…/arm-none-eabi-gcc -x …
Cygwin 常见问题解答包含以下“glibc 在哪里?”的信息 : Cygwin 不提供 glibc。它使用 newlib 来代替,它提供了很多(但不是全部)相同的功能。将 glibc 移植到 Cygwin 会很困难。
我很惊讶并检查了发布包,因为我之前使用过它。当我检查存储库时,似乎 glibc 实际上确实是 cygwin 的一部分,直到版本 2.10。谁能告诉我 glibc 后续版本的移植困难吗?
临时解决方法
我使用微小的printf解决了这个问题:
可能newlib printf占用了太多内存。此后,PC会更改一些奇怪的东西,从理论上讲,这应该是数组的结尾char[100]。
cp = buf + BUF
Run Code Online (Sandbox Code Playgroud)
稍后它尝试执行
*--cp = something
Run Code Online (Sandbox Code Playgroud)
它崩溃了。内存错误?有很多我不理解的事情。例如,我不确定链接描述文件是否正确,或者syscall函数是否正确。在获得进一步的了解之前,我必须坚持使用小巧的printf。
原版的
我有一个STM32F103RB板(Nucleo),而USART1才可以工作。另外,我测试了Newlib函数,并按puts()预期工作。但是,当我尝试printf()用于整数时,如下所示:
printf("ADC: %d\r\n", test);
Run Code Online (Sandbox Code Playgroud)
如果test < 10程序正常运行,但是test >= 10产生了严重故障。经过一些GDB调试后,我发现它是从vfprintf生成的:
#0 HardFault_Handler () at main.c:136
#1 <signal handler called>
#2 0x08005af4 in _vfprintf_r (data=<optimized out>, fp=0x20000384 <impure_data+852>, fmt0=fmt0@entry=0x20004f57 " \254\264", ap=...,
ap@entry=...) at ../../../../../../newlib/libc/stdio/vfprintf.c:1601
#3 0x08004fd0 in printf (fmt=0x800b4ac "ADC: %d\n\r") at ../../../../../../newlib/libc/stdio/printf.c:52
#4 0x080004e8 in main () at main.c:168
Run Code Online (Sandbox Code Playgroud)
我想不出任何解决方案。这是我的_sbrk():
caddr_t …Run Code Online (Sandbox Code Playgroud) 我需要将snprintf()移植到另一个不完全支持GLibC的平台上.
我正在寻找Glibc 2.14源代码中的基础声明.我遵循许多函数调用,但卡在vfprintf()上.然后它似乎调用_IO_vfprintf(),但我找不到定义.宏可能会混淆事物.
我需要查看扫描格式字符串的真实C代码,并计算在输入缓冲区足够大时它将写入的字节数.
我也尝试过查看newlib 1.19.0,但我遇到了_svfprintf_r().我无法在任何地方找到定义.
有人能指出我为snprintf()定义或另一个定义吗?
我是一名使用IA-32型处理器的嵌入式软件工程师.我们正在寻找一个编译工具链 - 更好的免费.
我们曾经使用Mentor Graphics CodeBench Lite,但它已不再可用.
我们已经查看了其他GCC发行版,但它们都没有glibc的裸机实现.除了newlib之外没有,但由于GPL和LGPL许可问题,我们无法使用它.我们是OEM,我们的客户(和我们)拥有专有代码.
欢迎任何建议.
我正在为STM32F7编写嵌入式软件,而我的libc是newlib-2.4.0.20160527。
我已经实现_sbrk()如下:
extern intptr_t g_bss_end; /* value after the last byte in .bss */
extern intptr_t g_msp_lim; /* stack buffer starts at this address */
intptr_t _sbrk(ptrdiff_t heap_incr)
{
static intptr_t heap_end = 0;
intptr_t prev_heap_end;
intptr_t new_heap_end;
if(heap_end == 0) {
heap_end = (intptr_t)&g_bss_end;
}
prev_heap_end = heap_end;
new_heap_end = prev_heap_end + heap_incr;
if(new_heap_end >= g_msp_lim) {
errno = ENOMEM;
return -1;
}
heap_end = new_heap_end;
return prev_heap_end;
}
Run Code Online (Sandbox Code Playgroud)
然后,当我执行以下操作时:
/* total capacity of my heap is …Run Code Online (Sandbox Code Playgroud) 我正在努力使用 GCC 将 printf 从 newlib 正确实现到我的 esp32 中。
我已经阅读了 newlib 文档,它为我提供了有关如何调用 printf 的一般信息,但没有向我解释后端实现。
根据我当前的研究,我确定 printf 将格式化字符串输出到 STDOUT。在 PC 上,这对我来说更容易理解,因为有一个控制台窗口可以显示 printf 的格式化输出,但是在嵌入式系统上,我知道您必须告诉库将 printf 的格式化输出重定向到哪里,这就是我正在想办法。
再次,根据我的研究,我了解到需要一些功能来完成此任务,特别是功能_write。
我发现如何弥合 printf 和使用该_write函数之间的差距非常困难。我希望这里有人能帮助我理解如何正确实现 printf。
如果我错过了一些清楚解释这一点的文档,那么请将我重定向到该文档。我尝试阅读 newlib 文档以及 GCC 相关文档,但没有真正提到如何使用 printf,但是有大量关于如何调用 printf 和格式化字符串的文档,但这部分很简单。我需要知道如何从 MCU 的 STDOUT 获取格式化字符串。
谢谢大家!