You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

裸机Cortex-M33使用iostream遇链接错误与硬故障的解决求助

针对ARM Cortex-M33 QEMU环境下C++ iostream链接错误与硬故障的解决方案

一、修复__dso_handle与_fini未定义的链接错误

1. 完善链接脚本配置

不仅要添加.init_array和.fini_array段,还要确保它们被正确关联到初始化/终止逻辑:

/* 在FLASH段内添加以下内容 */
.init_array :
{
  PROVIDE_HIDDEN (__init_array_start = .);
  KEEP (*(SORT(.init_array.*)))
  KEEP (*(.init_array))
  PROVIDE_HIDDEN (__init_array_end = .);
} > FLASH

.fini_array :
{
  PROVIDE_HIDDEN (__fini_array_start = .);
  KEEP (*(SORT(.fini_array.*)))
  KEEP (*(.fini_array))
  PROVIDE_HIDDEN (__fini_array_end = .);
} > FLASH

/* 在Reset_Handler中加入标准库初始化/终止调用 */
Reset_Handler:
  /* 保留原有栈初始化、向量表拷贝等代码 */
  bl __libc_init_array  /* 调用全局构造函数 */
  bl main
  bl __libc_fini_array /* 调用全局析构函数 */
  b . /* 死循环防止返回 */

2. 标准化编译链接选项

放弃手动链接crtbegin.o/crtend.o,改用工具链自带的specs文件简化依赖管理:

  • 编译时添加:-fno-exceptions -fno-rtti -specs=nano.specs -specs=semihosting.specs
    • -fno-exceptions/-fno-rtti:禁用嵌入式环境不必要的C++特性,减少依赖
    • -specs=nano.specs:使用轻量化的newlib-nano标准库
    • -specs=semihosting.specs:启用半主机模式支持
  • 链接时指定必要库:-lc -lstdc++ -lsupc++ -lrdimon
    • 确保C/C++标准库、半主机运行时的依赖被正确链接

示例完整编译链接命令:

arm-none-eabi-g++ -mcpu=cortex-m33 -mthumb -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -specs=nano.specs -specs=semihosting.specs -c main.cpp -o main.o
arm-none-eabi-g++ -mcpu=cortex-m33 -mthumb -ffunction-sections -fdata-sections -specs=nano.specs -specs=semihosting.specs -T link.ld main.o -o app.elf -lc -lstdc++ -lsupc++ -lrdimon

二、解决std::cout触发硬故障的问题

半主机模式下,默认的std::cout未适配嵌入式环境,需重定向输出到半主机的printf实现:

#include <iostream>
#include <streambuf>
#include <cstdio>

class SemiHostStreamBuf : public std::streambuf {
protected:
    int overflow(int c) override {
        if (c != EOF) {
            putchar(static_cast<char>(c));
        }
        return c;
    }
};

static SemiHostStreamBuf semi_host_buf;
static std::ostream semi_host_cout(&semi_host_buf);

// 在main函数前初始化,替换std::cout的缓冲区
__attribute__((constructor)) void setup_cout() {
    std::cout.rdbuf(&semi_host_buf);
}

此后std::cout的输出会通过半主机的putchar转发,避免调用未实现的系统调用导致硬故障。

同时需确保QEMU启动时启用半主机模式:

qemu-system-arm -machine your-cortex-m33-board -semihosting -kernel app.elf

三、crt文件未被识别的处理方案

无需手动编写crti.c/crtn.c,直接使用工具链自带的crt文件:

  1. 通过以下命令获取工具链crt文件路径:
arm-none-eabi-gcc -print-file-name=crti.o
  1. 在链接时用-L参数指定该路径,或确保编译时工具链能自动检索到(使用正确的specs文件时工具链会自动处理)。

内容的提问来源于stack exchange,提问作者cberk1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:10:17