- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在运行带有 ARM Cortex-M3 (STM32F205) 的裸机嵌入式系统。当我尝试将 snprintf()
与 float 一起使用时,例如:
float f;
f = 1.23;
snprintf(s, 20, "%5.2f", f);
我将垃圾放入 s
。格式似乎受到尊重,即垃圾是一个格式正确的字符串,包含数字、小数点和两个尾随数字。但是,如果我重复 snprintf
,字符串可能会在两次调用之间发生变化。
float 学似乎以其他方式工作,snprintf
与整数一起工作,例如:
snprintf(s, 20, "%10d", 1234567);
我将 newlib-nano
实现与 -u _printf_float
链接器开关结合使用。编译器是 arm-none-eabi-gcc
。
我确实非常怀疑内存分配问题,因为打印整数时没有任何问题,但 float 的表现就好像它们在这个过程中被破坏了一样。 printf
系列函数使用 float 调用 malloc
,而不是整数。
我在此上下文中使用的唯一不属于 newlib
的代码是我的 _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;
current_block_address = current_heap_end;
// increment and align to 4-octet border
incr = (incr + 3) & (~3);
current_heap_end += incr;
// Overflow?
if (current_heap_end > &_Heap_Limit)
{
errno = ENOMEM;
current_heap_end = current_block_address;
return (caddr_t) - 1;
}
return (caddr_t)current_block_address;
}
据我所知,这应该可行。似乎没有人用负增量调用它,但我猜这是由于 newlib malloc
的设计所致。唯一有点奇怪的是第一次调用 _sbrk
的增量为零。 (但这可能只是malloc
对堆起始地址的好奇。)
堆栈不应与堆冲突,因为两者大约有 60 KiB RAM。链接器脚本可能很疯狂,但至少堆和堆栈地址似乎是正确的。
最佳答案
由于其他人可能会被同样的错误所咬,所以我发布了我自己的问题的答案。然而,@Notlikethat 的评论提出了正确的答案。
这是不可偷窃的教训。我借用了 STMCubeMX 代码生成器附带的 gcc 链接描述文件。不幸的是,脚本连同启动文件已损坏。
原始链接描述文件的相关部分:
_estack = 0x2000ffff;
及其在启动脚本中的对应部分:
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
...
g_pfnVectors:
.word _estack
.word Reset_Handler
...
第一个中断 vector 位置(0)应该总是指向启动栈顶。当到达复位中断时,它还会加载堆栈指针。 (据我所知,后者是不必要的,因为 HW 在调用重置处理程序之前无论如何都会从第 0 个 vector 重新加载 SP。)
Cortex-M 堆栈指针应始终指向堆栈中的最后一项。启动时堆栈中没有任何项目,因此指针应指向实际内存上方的第一个地址,在本例中为 0x020010000。使用原始链接描述文件,堆栈指针设置为 0x0200ffff,这实际上导致 sp = 0x0200fffc(硬件强制字对齐堆栈)。在此之后,堆栈错位了 4。
我通过删除 _estack
的常量定义并将其替换为 _stacktop
来更改链接描述文件,如下所示。内存定义之前就在那里。我更改名称只是为了查看该值的使用位置。
MEMORY
{
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
}
_stacktop = ORIGIN(RAM) + LENGTH(RAM);
在这之后 _stacktop
的值是 0x20010000,我的数字漂浮得很漂亮...同样的问题可能出现在使用双倍长度参数的任何外部(库)函数中,正如 ARM Cortex ABI 声明的那样调用外部函数时,堆栈必须对齐到 8 个八位字节。
关于c - snprintf() 使用 newlib nano 打印垃圾 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28746062/
我从 https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads 下载了工具链“gcc-arm-none-eabi-6-2
**摘要:**本文介绍了LiteOS-M内核Newlib C的实现,特别是文件系统和内存分配释放部分,最后介绍了Newlib钩子函数。 本文分享自华为云社区《鸿蒙轻内核M核源码分析系列二十 Newli
我一直在将 newlib 移植到我的非常小的内核中,但我很困惑:每当我包含一个引用系统调用的函数时,我的程序将在执行时出现页面错误。如果我调用一个不引用系统调用的函数,比如 rand(),就不会出错。
我想使用预装的 mips 交叉编译器 (mips-linux-gnu-gcc) 构建 newlib 库。编译器默认链接 glibc。 $ mips-linux-gnu-gcc -v Using bui
我是一名使用 IA-32 类型处理器的嵌入式软件工程师。我们正在寻找一个编译器工具链 - 最好是免费的。 我们曾经使用 Mentor Graphics CodeBench Lite,但它不再可用。 我
我想编写自己的内核,但我一直坚持为我的交叉编译器移植 newlib。 newlib 是哪个版本我要下载吗? 系统调用stubs放在哪里?最少的实现就足够了吗?如果我决定稍后编辑系统调用,是否必须重建
我正在使用 this tutorial创建一个交叉编译器。 我跟着 gcc 交叉编译器教程去了 porting newlib .一切正常,直到我尝试通过发布来编译它 make all install
我正在使用 GCC 交叉编译器 (arm-none-eabi-) 开发一个用于 ARM 架构(裸机)的程序。为了保持较小的代码大小,我使用“--specs=nano.specs”链接器标志来链接 ne
我在使用 newlib 的 printf 函数时遇到一个奇怪的问题,它被重定向到 uart 端口。 这个问题可以用一个例子很好地说明。 printf(" hi "); ... ...//some ot
我正在使用 Eclipse 开发裸机应用程序。我链接到 newlib,所以我提供了我自己的 _sbrk() 实现。此功能通常包含在我的项目中,并且一切正常。 现在我尝试将这个函数移动到我在过去几个月开
我正在尝试将 printf 数据发送到我的 uart 设备。我已经适本地编写了 write_r() 函数。 我遇到的问题是, 当我说printf("我叫山姆\n我很好"); 下次我说 printf("
我正在尝试为我的操作系统移植 NewLib(我正在学习本教程:http://wiki.osdev.org/Porting_Newlib),但我有一些问题。 LibGloss 完成并编译后,我究竟什么时
我想使用 newlib 而不是 glibc 来编译小的静态二进制文件。 (我不打算交叉编译,因为二进制文件将被同一台计算机使用。)我相信我需要为此编译一个单独的 gcc 吗? 我编译了gcc: ./c
在尝试构建 newlib 1.20.0 时...我按照这个教程http://wiki.osdev.org/OS_Specific_Toolchain#newlib.2Flibc.2Fsys.2Fmyo
我正在使用 gcc-arm-none-eabi 4.9 2014q4 为 Cortex-M4 编写裸机应用程序。当应用程序加载时,对 _sbrk 的第一次调用似乎无效。 我已经实现了 _sbrk 如下
我正在使用 luaL_newlib(luaState, afbFunction),其中 afbFunction 是静态 luaL_Reg 数组。不幸的是,luaL_Reg 只支持两个字段:name 和
我正在尝试为我的爱好内核构建一个工具链,但在构建 Newlib 时遇到了问题。每当我尝试在 newlib/libc/sys/下的内核目录中运行 autoreconf 时,我都会收到错误消息: conf
这是我的第一篇文章,它涵盖了我已经尝试断断续续工作了大约一年的内容。 从本质上讲,它可以归结为以下内容:我有一份 newlib 的副本,我正试图在 LPC2388(来自 NXP 的 ARM7TDMI)
我正在使用 i686 机器作为构建平台为 ARM 设置交叉编译工具链。 我已经能够使用工具链编译基本的 C 程序并在目标 ARM 设备上运行它,但由于 Newlib 仅构建静态库,文件大小最终太大。
我将 arm-none-eabi 工具链与 newlib 结合使用,以使用 ARM Cortex-M0+(特别是工具链的 MCU-on-eclipse 版本)来定位自定义板。我正在使用 -nostar
我是一名优秀的程序员,十分优秀!