ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CH55xDuino 编译报错 sdcc.sh syntax error 的排查与解决

CH55xDuino 编译报错 sdcc.sh syntax error 的排查与解决 直接说结论这个报错八成不是因为你程序写得有问题而是工具链脚本本身的解释器或格式出了问题。我用 CH55xDuino 折腾 CH552 的时候第一次编译就撞上了这堵墙sdcc.sh: syntax error: unexpected (这行字看起来像是代码语法错误实际上跟你的 Arduino 草稿代码一点关系都没有。它说的是sdcc.sh这个脚本在执行的时候shell 解析不了其中的某段写法。先交代一下背景。CH55xDuino 是一个把 CH55x 系列CH551、CH552、CH553、CH554 这些兼容进 Arduino IDE 的第三方开发板支持包。CH55x 是南京沁恒出的增强型 8051 内核单片机几块钱一片USB 支持还特别全很多玩 DIY 键盘、小玩具、USB 外设的朋友都盯上了它。要在 Arduino 生态里用编译器走的是 SDCCSmall Device C Compiler不是 AVR 那套 GCC。所以你会看到工具链目录里躺着一堆.sh脚本sdcc.sh就是用来在 Linux/macOS 下封装调用 SDCC 编译器的入口。问题就出在这个脚本的兼容性上。我是在 Ubuntu 下遇到这个报错的后来查了一圈发现 Windows Git Bash、macOS 的终端里也有人中招。这文章就把整个排查过程、背后的原理、还有最终的解决办法一次性讲清楚。1. 这个报错到底是怎么冒出来的第一次编译报错的时候我盯着屏幕看了半天第一反应是是不是自己代码里写了什么不规范的东西。但仔细一看报错信息是从 Arduino IDE 的编译输出窗口里跳出来的前面还挂着一大串路径和命令行最后才落到sdcc.sh: syntax error: unexpected (。这里有个关键点这个报错来自 shell 对脚本的解析阶段而不是 SDCC 编译器对 C 源码的编译阶段。shell 脚本是解释执行的Linux 下的sh、bash、dash各有各的语法子集。unexpected (这句话翻成人话就是脚本在执行到某一行时解释器觉得那个位置的圆括号是多余的、非法的。常见触发原因有四个脚本的 shebang 写的是#!/bin/sh但实际系统里/bin/sh指向的是dash而脚本里用了bash才支持的数组语法或$(...)嵌套写法。脚本文件是从 Windows 环境拷贝出来的行尾带着\r\nCRLFLinux 下的 shell 把\r当成命令的一部分解析就乱了。脚本里用了某个函数或命令的写法在当前 shell 版本里不支持比如function foo()这种混合风格。脚本文件本身被截断或编码异常比如下载不完整、编辑器自动加了 BOM 头。我当时的情况是第 1 种和第 2 种叠加。CH55xDuino 的 sdcc.sh 是为 bash 写的里面的写法在 dash 下跑不动同时我拿到手的包还带着 CRLF 行尾。2. 先定位脚本本身的问题遇到sdcc.sh报错第一件要做的事不是去改 Arduino 代码而是把脚本拉出来单独执行试试。找到脚本路径很直接Arduino 的编译输出窗口里通常会显示Compiling ... ...之后跟着的实际命令里面就有sdcc.sh的完整路径。另一种方法是在开发板支持包目录里搜一般在 Arduino 的hardware目录下路径类似~/Arduino/hardware/CH55xDuino/或 IDE 内置的packages目录下。找到脚本后先做三件事用head -n 20 sdcc.sh看开头确认 shebang 是哪一行有没有 BOM。用file sdcc.sh看文件类型正常的应该是ASCII text executable或UTF-8 Unicode text如果显示with CRLF line terminators就是 Windows 行尾。用bash -n sdcc.sh做一次语法检查这命令不会执行脚本只检查语法。我执行bash -n的时候报错直接定位到了具体行号比 Arduino IDE 里那句笼统的syntax error清楚得多。如果你的系统里bash都报语法错误那大概率就是 CRLF 或者编码问题如果bash -n能通过但编译时还是报错那就是 Arduino 调用的解释器不是 bash而是/bin/sh或dash。这里要额外说明一点在 Ubuntu 18.04 之后的系统上/bin/sh默认指向dash这是个 POSIX 兼容但比 bash 精简很多的解释器。很多从别处拿来的脚本作者在 bash 里写得顺手用了数组、[[ ]]条件、source之类的 bash 专属特性换到 dash 下一跑就翻车。sdcc.sh 里面就用了不少 bash 风格的处理所以直接用sh sdcc.sh跑大概率会炸。3. 解决 CRLF 行尾问题先解决最好处理的行尾。Windows 下下载的 zip 包解压到 Linux 里很多文本文件会带着 CRLF 行尾。shell 脚本对\r极其敏感每个命令结尾多了个回车符解释器会把它当成命令名的一部分后续解析全部错乱报错位置和真实原因经常对不上。处理方式有几种用sed -i s/\r$// sdcc.sh去掉行尾的\r。用dos2unix sdcc.sh如果系统装了 dos2unix 工具的话。用 Vim 打开执行:%s/\r//g后保存。我当时用的是 sed一行命令解决问题。执行完再用file sdcc.sh检查确认行尾变成LF。这里提醒一句不只是 sdcc.sh工具链目录下所有.sh脚本最好都一起处理因为编译过程中可能还有其他辅助脚本会被调用它们同样会踩 CRLF 的坑。如果你是在 Windows 上用 Git Bash 或 WSL也要注意编码问题。Git Bash 默认能容忍 LF 行尾但如果仓库的core.autocrlf设置不当clone 下来也可能出问题。WSL 就按 Linux 的方式处理上面的方法直接适用。4. 把脚本执行方式改成 bash行尾清掉之后再来解决解释器不匹配的问题。最简单粗暴的办法是改 shebang把#!/bin/sh改成#!/bin/bash。Linux 上/bin/bash基本是标配macOS 上/bin/bash也存在只是版本老一点但对于这个脚本来说足够用。打开sdcc.sh第一行如果写的是#!/bin/sh直接改成#!/bin/bash然后保存。之后可以再用bash -n sdcc.sh验证一次语法确认没有报错。但改 shebang 不是终点因为 Arduino IDE 在调用编译脚本时不一定遵守脚本第一行的 shebang。它可能直接用它在代码里写定的解释器去执行比如干脆就是sh sdcc.sh这种显式调用。所以光改 shebang 可能不保险更稳的做法是同时检查 Arduino 平台配置里是怎么调用 sdcc.sh 的。CH55xDuino 的平台配置文件是platform.txt里面定义了编译命令模板。找到包含sdcc.sh的那行比如recipe.c.preproc.pattern/bin/sh {runtime.tools.sdcc.path}/bin/sdcc.sh ...把/bin/sh改成/bin/bash改完之后保存重新打开 Arduino IDE不用全关重新编译一次也行但保险起见重启 IDE。也可以直接在终端里手动跑一遍脚本模拟 Arduino 的调用方式确认手动执行不再报错再回 Arduino IDE 里试。手动执行的示例如下cd /path/to/CH55xDuino/hardware/CH55xDuino chmod x sdcc.sh ./sdcc.sh --version能输出版本信息或帮助信息说明脚本已经可以正常解析执行了。5. 还有一个隐藏的坑编译工具的路径和权限解决完脚本解析问题编译可能还会报别的错这里提前打个预防针。CH55xDuino 依赖的 SDCC 工具链如果是通过 Arduino IDE 的 Boards Manager 自动下载安装的一般路径不会出问题。但如果是从 GitHub 上手动下的包或者 IDE 版本比较新、包的目录结构有调整就可能出现sdcc.sh: No such file or directory或permission denied的情况。先检查权限。脚本需要有可执行权限chmod x /path/to/CH55xDuino/hardware/CH55xDuino/*.sh chmod x /path/to/CH55xDuino/hardware/CH55xDuino/tools/linux/*再看路径。Arduino IDE 2.x 里开发板支持包的存放位置和 1.8 不一样2.x 默认放在~/Documents/Arduino/hardware或 IDE 数据目录里的packages文件夹。有时候用户之前装过旧版 CH55xDuino新版装完没覆盖干净两条路径同时存在platform.txt 里写死了一个不存在的路径就会报错。排查思路编译输出窗口里会打印完整的命令行里面有 sdcc.sh 的实际调用路径直接进文件管理器或终端确认文件是否真的在那里。如果路径下确实没有就把包重新解压或通过 Boards Manager 重装。如果是权限问题chmod 即可。6. 与 sdcc.sh 同病相怜的常见问题汇总CH55xDuino 这套板子支持包在 Linux 下还有其他几个高频报错我顺手整理一下反正在折腾的过程中早晚会碰到。第一个找不到 SDCC 编译器。报错一般是Cannot find sdcc或sdcc: command not found。这通常是环境变量问题或者工具链没有随开发板支持包一起下载。解决办法是手动下载 SDCC 工具链放进hardware/CH55xDuino/tools/对应平台目录下然后修改platform.txt里{runtime.tools.sdcc.path}的指向或者在终端里把 SDCC 的 bin 目录加入 PATH。更省事的方式是直接在 Arduino IDE 的 Boards Manager 里搜 CH55x让 IDE 自动拉依赖。第二个编译时提示缺少头文件比如ch55x.h找不到。这个多半是板级支持包的目录结构不对cores、libraries、variants这几个关键目录缺失或者放错位置。CH55xDuino 的仓库结构比较固定解压之后确认hardware/CH55xDuino这个目录下面紧挨着cores和variants不能多套一层目录否则 Arduino IDE 识别不到。很多人从 GitHub 下载 zip 解压后会得到一个CH55xDuino-master文件夹直接把这个文件夹改名成CH55xDuino放好路径不能有中文和空格。第三个上传时报错Serial: Error opening ... Permission denied。这个是 Linux 串口权限的老问题。当前用户不在dialout组里没有权限访问 USB 转串口设备。解决方法sudo usermod -a -G dialout $USER退出登录再重新登录或者重启系统。CH552 这类芯片用的是 USB 直接下载设备节点通常是/dev/ttyUSB0或/dev/ttyACM0用lsusb可以确认设备是否被识别。有些发行版还会把 CH55x 的 VID/PID 识别错需要手动写 udev 规则但大多数现代内核都已经支持。第四个macOS 上编不过报缺少stm32flash或python3。CH55xDuino 在 macOS 上需要额外装一些命令行工具比如python3和pip因为它的烧录脚本用了 Python 脚本做 USB 操作。如果你用的是 macOS 的 IDE 2.x建议先在终端里装好 Command Line Tools再确认python3 --version能正常输出。烧录阶段报ModuleNotFoundError的话就按缺哪个装哪个的原则补包。macOS 还有一个问题是系统自带的 bash 版本是 3.2比较老sdcc.sh 里如果用了较新的语法特性也可能出问题这时优先考虑用brew install bash装新版本并把脚本的 shebang 指到/opt/homebrew/bin/bash。7. 从报错现象到根因的排查方法论这次排查给我的最大感受是编译报错先看它发生在哪个阶段再想怎么修。Arduino IDE 的编译输出窗口虽然信息量大但很多人一看到syntax error就上头以为是自己的代码问题这是最容易走弯路的地方。实际上工具链脚本报错、头文件缺失、系统依赖不满足这些错误信息在输出窗口里的位置和格式都有区别学会区分就能少走很多冤枉路。我建议的排查顺序是看报错信息的来源——是sdcc.sh、python3、avrdude还是gcc先确认是哪个环节崩了。把报错信息复制到搜索引擎搜完整短语比搜半截话有效得多。手动在终端里执行报错的那条命令脱离 Arduino IDE 跑一遍往往能得到更完整的错误上下文。修复后再编译如果出现新的报错重复这个过程一次只解决一个问题。这个方法看起来笨但实际效率很高。因为 Arduino IDE 把很多细节藏起来了一个个点开菜单找还不如直接在终端里跟它硬碰硬。尤其像 CH55xDuino 这种非官方支持包社区维护者的测试环境可能跟你不一样别人没遇到而你遇到了那大概率就是环境差异造成的。8. 为什么推荐把这套板级支持包玩明白绕了这么大一圈有人可能想问CH55xDuino 值得折腾吗我的看法是如果你恰好在做需要 USB、又不想上 STM32 那么大成本的项目CH552 这东西确实是个性价比很高的选择。单独一片 CH552 芯片在某宝上几块钱能买到还自带 USB 控制器做个小键盘、宏板、USB 小风扇控制、LED 灯效控制器都挺顺手。CH55xDuino 的意义在于把 Arduino 的易用性带到了这颗小芯片上让不熟悉 8051 和 Keil 的人也能快速上手。而且在 Linux 下跑通这套工具链之后你会发现整个流程其实是透明的Arduino IDE 只是简单地把配置模板拼成命令行真正干活的是 SDCC 和 Python 脚本。理解了这一层以后遇到任何第三方开发板支持包报错都能用同样的方法拆解。所以这次排查不光是通过 sdcc.sh 解决了问题也顺带把 Arduino 背后那套编译机制摸了一遍。如果你还在纠结要不要入 CH55xDuino 的坑我的建议是先在 Wokwi 仿真平台或者实体开发板上跑一个 USB 串口回环的小例子确认编译上传链路通了再考虑具体项目。工具链这东西第一次配好之后就用得很顺后面基本不会再碰这些问题。
返回列表