
1. 报错现场startup_stm32f103xb.s 第一行的短横线是哪里来的1.1 在 Windows 下用 gcc 编译 STM32最容易让人措手不及的报错在 Windows 下用 gcc 编译 STM32最容易让人措手不及的报错不是 main.c 写错而是 startup_stm32f103xb.s 第一行出现junk at end of line。我排查时先把 Codex 通道指到 TaoToken在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建 Key再让它读文件分析原因。完整的报错通常长这样startup_stm32f103xb.s:1: Error: junk at end of line, first unrecognized character is - startup_stm32f103xb.s:2: Error: bad size 0 in type specifier startup_stm32f103xb.s:2: Error: bad instruction startup_stm32f103xb.s看起来是 gcc 的汇编器在解析启动文件时直接放弃。但实际的坑往往不在编译器而在 VSCode 的 Makefile 配置功能。你按照原流程装好 Embedded IDE、装好 Makefile Tools、用 STM32CubeMX 生成 Makefile 工程第一次点编译就撞上这个错多半是Makefile: Configure On Open惹的祸。这个选项会在打开工程时自动执行一次 configure本意是让 VSCode 能正确解析编译参数但它会顺手改写一部分工程文件startup_stm32f103xb.s就是最常被改坏的那个。1.2 汇编器为什么对第一行这么敏感ARM 的启动文件是汇编源码逐行解析语法规则比 C 严格得多。正常的startup_stm32f103xb.s第一行通常是注释块以分号开头比如;********************或者是.syntax unified这类伪指令。汇编器看到分号就跳过去看到点开头的关键字就当作处理器指令。但被插件改写后文件里可能出现一个非常突兀的短横线-。汇编器不认识它把它当成了指令助记符的一部分或者多余 token于是报出junk at end of line。第二行的bad size 0 in type specifier和bad instruction都是连锁反应第一行解析失败后汇编器对后续行的格式判断全部失准每一行都跟着出问题。这也是为什么你会看到同一个文件连续报三行错但真正的源头只有一个。1.3 怎样快速确认文件被改过先别急着去改 makefile直接用 VSCode 打开报错指向的startup_stm32f103xb.s看文件最前面几行。如果第一行出现的不是注释符号而是-、这类明显不属于汇编语法的字符基本可以确定它被改过了。第二个线索是文件修改时间。用 STM32CubeMX 刚生成的工程startup 文件的时间应该和工程生成时间一致。如果这个文件的时间比工程生成时间晚说明在工程打开后有人动过它。第三个线索更简单把这份文件和你备份的原始模板做一次 diff差异集中在文件头部那就是插件格式化留下的痕迹。2. 排查工具准备在 TaoToken 拿 Key把 Codex 的 Base URL 指过来2.1 注册并创建 API Key确认报错和文件异常后我打算让 Codex 帮我做一次对比分析把报错和.s文件内容贴给它让它判断是不是被插件改过。但 Codex 要正常工作得先有一条可用的模型通道。我的做法是打开 TaoToken 注册账号进入控制台创建 API Key把生成的 Key 保存为YOUR_API_KEY。这一步对应原流程里「准备工具链」的位置。TaoToken 在这里只充当 Codex 的 API 通道不参与 gcc 和 STM32 的编译动作。编译还是在你的本地 VSCode 里手动执行Codex 只负责读代码、分析报错、给修复建议。不要把 TaoToken 理解成编译环境它是模型对话的接入层。2.2 修改 ~/.codex/config.tomlCodex CLI 的模型通道配置写在~/.codex/config.toml。打开文件把 provider 指到 TaoTokenmodel 你的模型ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY注意两点。第一base_url是https://taotoken.net/api末尾不要加/v1。官网落地页https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end用于注册、建 Key、看模型广场和用量而填进 Codex 的必须是接口地址 taotoken.net/api两者不要混用。第二model字段不要照抄网上的模型名打开模型广场复制一个当前可用的模型 ID 填进去。如果你用的是 Codex IDE 扩展而不是 CLI就把同样的 provider 信息填到模型供应商设置里字段保持一致。保存配置后在 shell 里导出环境变量export TAOTOKEN_API_KEYYOUR_API_KEYWindows PowerShell 用户写成$env:TAOTOKEN_API_KEYYOUR_API_KEY2.3 验证 Codex 通道是否通了配置是否生效跑一条最简单的命令就知道了。在工程目录下执行codex exec 列出当前目录下 startup_stm32f103xb.s 的前 10 行内容不要执行任何编译动作 --model-provider taotoken如果 Codex 能正常返回文件内容说明 Key、Base URL、模型 ID 都对了。如果报 404检查base_url是不是多了/v1如果报 401回 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 控制台重新复制 Key确认没有多余空格或缺失字符。3. 让 Codex 对照标准汇编格式确认 startup 文件被插件改过3.1 把报错和文件头部一起发给 Codex验证通道没问题后我把完整报错和.s文件最前面 10 行整理成一段文本让 Codex 分析。提问模板可以这样写下面是一个 STM32 工程用 gcc 编译时的报错 startup_stm32f103xb.s:1: Error: junk at end of line, first unrecognized character is - startup_stm32f103xb.s:2: Error: bad size 0 in type specifier startup_stm32f103xb.s:2: Error: bad instruction startup_stm32f103xb.s 这个工程是用 STM32CubeMX 生成的 Makefile 工程在 VSCode 中使用 Embedded IDE 编译。 startup 文件前几行如下 这里粘贴你本地的 startup_stm32f103xb.s 前 10 行 请判断 1. 报错是否由 startup 文件被改写引起的 2. 正常 startup 文件第一行应该是什么样子 3. 结合前 10 行内容指出具体是哪个字符不合法。不用一次提太多问题Codex 会按顺序回答。3.2 Codex 的分析逻辑Codex 给出的判断思路通常是这样junk at end of line表示汇编器在一行里解析到了预期之外的内容first unrecognized character is -已经精确指出了问题字符就是行首那个短横线。正常的 ARM 启动文件使用分号注释但有些编辑器或脚本会在行首插入-当作某种标记汇编器无法识别只能报错。bad size 0 in type specifier是第二行被牵连的典型错误。汇编器解析第二行时期望看到一个合法的指令格式比如.word、.thumb、ldr等。但因为第一行的语法错误上下文状态被破坏第二行的操作数无法被正确归类于是报出bad size。Codex 会提醒你不要单独去改第二行先把第一行恢复成合法内容后面几个错误会自动消失。3.3 把分析结论对应到自己文件上我照着 Codex 的建议重新打开startup_stm32f103xb.s发现第一行确实被写成了一个以-开头的怪异字符串第二行也只有半个指令。这说明问题不是编译器版本也不是 makefile 语法而是工程里某一步对启动文件做了不合理的格式化。到这里修复方向就很明确了恢复原始启动文件同时关掉那个会触发格式化的选项。编译动作仍然由你在本地 VSCode 里执行Codex 只负责把文件头和报错放在一起对照帮你定位到具体的行和具体字符。4. 修复关掉 Makefile: Configure On Open重新生成启动文件再编译4.1 取消勾选 Makefile: Configure On Open在 VSCode 里按Ctrl,打开设置搜索Makefile: Configure On Open把勾选取消。这个选项的作用是打开 Makefile 工程时自动执行 configure新版插件里默认不勾选但如果你用的工程是在旧版本下创建的或者你自己之前手动打开过设置可能还开着。关掉它之后VSCode 不会再在工程打开时自动碰你的启动文件。已经产生的损坏文件不会自动恢复所以还要继续下一步。4.2 删除被改写的 startup 文件并重新生成最干净的做法是删除被改写的文件再让 STM32CubeMX 重新生成一份原始版本。具体步骤关闭当前 VSCode 工程。找到工程目录下的startup_stm32f103xb.s把它删除或改名为.bak。打开 STM32CubeMX加载原有.ioc工程。保持现有配置不变重新生成 Makefile 工程。CubeMX 重新生成时会把startup_stm32f103xb.s按标准模板重新写出来。这个文件里的第一行会是正常的注释或伪指令不再有短横线污染。工程重新生成后VSCode 可能会提示检测到外部文件变化选择接受或全部还原。如果你手头有干净的备份也可以直接覆盖回去。不过用 CubeMX 重新生成更稳妥因为它能保证和当前芯片型号的启动文件完全匹配不需要手动核对版本。4.3 重新编译确认回到 VSCode打开 Makefile Tools 扩展面板确认 Make 程序的路径仍然指向.eide文件夹下的make.exe然后点编译按钮。这次启动文件应该顺利通过报错不再出现工程目录下会生成build文件夹里面包含.elf、.bin、.hex三个文件。如果仍然报错先检查是不是旧文件的缓存。把 VSCode 完全关闭再重新打开工程让插件重新加载 makefile。其次确认.s文件确实被 CubeMX 重新生成了而不是你删错了文件路径。5. 编译通过后烧录验证回 TaoToken 控制台对一下调用记录5.1 烧录看 LED 是否按预期闪烁编译生成的可执行文件已经躺在build文件夹里.bin、.elf、.hex任选一个都能烧写。如果你按原流程在main.c里加了HAL_GPIO_TogglePin和HAL_Delay(500)烧录后 LED 会以半秒间隔翻转电平。用逻辑分析仪抓一下引脚周期接近 1 秒说明 CPU 时钟、启动文件和 Makefile 全部恢复正常。这一步也验证了前面的判断gcc 工具链从头到尾没坏坏的只是被插件改写的启动文件。删除并重新生成之后编译链路完全恢复。5.2 回控制台看看 Codex 这次调用的记录排查过程中Codex 通过 TaoToken 通道发生了好几次模型调用这些调用都记在YOUR_API_KEY名下。你可以在 TaoToken 模型对话 里用同一把 Key 发一条测试消息确认模型 ID 和 Base URL 都没填错。如果接下来要长期写代码可以打开 Coding Plan 看套餐是否够用新建项目需要重新生成 Key 时去 控制台 API Keys 创建就好。之后想把 Claude Code 也接到同一个通道时参考接入文档核对环境变量。以后遇到启动文件类似的junk at end of line可以先按这个顺序排查看文件头是不是被改过关掉 Configure On Open重新生成启动文件再让 Codex 帮你复核一遍。这样一步步来比直接重装整个工具链快很多。