ARTICLE DETAIL

资讯详情

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

CH55xDuino编译报错sdcc.sh语法错误的根源与修复

CH55xDuino编译报错sdcc.sh语法错误的根源与修复 1. 项目概述CH55xDuino在Arduino IDE中编译失败的典型症状与本质定位你刚把CH552D或CH554D开发板插进电脑选好端口、选对板型CH55xDuino写完一行digitalWrite(LED_BUILTIN, HIGH);点击上传——结果IDE底部弹出红色报错框最刺眼的一行是sdcc.sh: syntax error: unexpected (。这不是Arduino Uno那种“avrdude: stk500_getsync() attempt x of 10”式的通信问题也不是ESP32常见的“Failed to connect to ESP32”连接超时而是一个发生在编译前端的、底层Shell脚本解析失败的致命错误。它直接卡死在代码翻译成机器指令的第一步连烧录环节都触碰不到。这个报错背后不是你的代码有语法错误而是整个工具链的执行环境出了系统级兼容性问题。核心关键词arduino、CH55xDuino、sdcc.sh、语法错误、排查全部指向一个事实你正在用Arduino IDE驱动一款基于8051内核的国产USB单片机而它依赖的SDCCSmall Device C Compiler交叉编译器在你的操作系统上没能被正确加载和执行。我第一次遇到这个问题是在Ubuntu 22.04上部署CH552D智能小车控制板时。当时以为是板子驱动没装好反复重装CH552驱动、更新Arduino IDE到2.3.2甚至重刷了Bootloader结果每次编译都稳稳地卡在sdcc.sh这行报错。后来才意识到问题根本不在硬件或Arduino IDE本身而在于那个被Arduino IDE悄悄调用的、封装了SDCC编译逻辑的Shell脚本——sdcc.sh。它不是一个独立程序而是Arduino CH55x核心包里一个用于适配不同平台Linux/macOS/Windows的启动包装器。报错里的unexpected (是Bash Shell在解析脚本时遇到了它不认识的语法结构。这通常意味着要么你用的Shell解释器太老比如dash而非bash要么脚本里用了高级Shell特性如数组、函数定义、进程替换而你的系统默认Shell不支持。更隐蔽的情况是某些Linux发行版尤其是精简版或容器环境默认将/bin/sh软链接到了dash而dash是POSIX兼容的轻量Shell明确不支持Bash扩展语法。当你双击运行sdcc.sh或者Arduino IDE通过system()调用它时系统会用/bin/sh去执行于是括号语法直接崩盘。这个问题在arduino智能小车、基于arduino的植物灌溉监测这类需要CH55x做USB HID或低功耗USB设备的项目中尤为常见因为CH55x的USB直连能力是其核心优势但恰恰也是编译链最脆弱的一环。2. 工具链架构拆解为什么CH55xDuino必须依赖SDCC以及sdcc.sh在其中的真实角色要真正解决sdcc.sh: syntax error: unexpected (必须先理解CH55xDuino在Arduino生态中的特殊定位。它不是AVR如Uno、不是ARM如Due、也不是ESP32那样的SoC而是基于经典的8051指令集架构的国产芯片。Arduino官方IDE原生只支持AVR、ARM、ESP系列对8051零支持。因此CH55xDuino能出现在Arduino板型列表里全靠第三方核心包core package——也就是我们安装的CH55xDuino核心。这个核心包的本质是一套完整的“翻译层”它把Arduino风格的setup()/loop()框架、pinMode()/digitalWrite()等API翻译成8051能懂的汇编和C代码再交给SDCC编译器生成.hex固件。SDCC是目前开源世界里对8051支持最成熟、最活跃的C编译器没有之一。它能处理8051特有的内存模型code/data/xdata、寄存器映射、中断向量表这是GCC或Clang做不到的。那么sdcc.sh是什么它绝不是SDCC编译器本体。真正的SDCC可执行文件叫sdccLinux/macOS或sdcc.exeWindows它是一个用C写的、功能完备的编译器。而sdcc.sh是CH55xDuino核心包开发者为了“偷懒”和“统一接口”而写的Shell包装脚本。它的核心任务有三个第一根据当前操作系统Linux/macOS自动选择正确的SDCC二进制路径第二拼接一长串SDCC编译参数包括芯片型号--mcuch552、内存布局--iram-size 256 --xram-size 1024、标准库路径、头文件包含路径第三最关键的是它要处理Arduino IDE传来的原始.ino文件——先用arduino-preprocessor预处理再把生成的.cpp文件喂给SDCC。这个脚本里大量使用了Bash特有语法比如用$(dirname $0)获取自身所在目录用array(...)定义路径数组用function compile()封装编译逻辑甚至用(echo ...)这种进程替换来动态生成链接脚本。所有这些在bash里运行完美但在dash或老旧的sh里第一个(就会被当成语法错误。我翻过CH55xDuino核心包的GitHub源码v2.1.0sdcc.sh脚本开头赫然写着#!/bin/bash这说明作者明确要求用Bash解释器。但问题就出在这里Arduino IDE在Linux/macOS上调用外部命令时并不总是显式调用bash sdcc.sh很多时候是直接执行./sdcc.sh。此时系统会读取脚本第一行的shebang#!/bin/bash并尝试用/bin/bash去运行它。如果系统里根本没有/bin/bash比如某些极简Docker镜像或者/bin/bash路径不对系统就会退而求其次用默认的/bin/sh去执行于是悲剧发生。这就是为什么在Ubuntu桌面版默认有bash且/bin/sh指向dash上出错而在macOS/bin/sh就是bash或Windows WSL2已安装bash上可能正常。所以排查的核心从来不是你的代码而是你的系统Shell环境与CH55xDuino核心包的shebang约定是否匹配。3. 根本原因深度排查四步锁定sdcc.sh报错的精确源头面对sdcc.sh: syntax error: unexpected (不能盲目重装或升级。必须像调试一个嵌入式系统一样分层、分段、实测验证。我总结了一套四步法每一步都对应一个关键检查点能精准定位问题根源避免浪费时间在无关操作上。3.1 第一步确认sdcc.sh脚本是否真的被调用以及它的真实路径很多人以为报错来自Arduino IDE内部其实不然。IDE只是个GUI外壳真正的编译工作由后台的arduino-builder进程完成它会按核心包配置找到并执行sdcc.sh。所以第一步必须绕过IDE手动触发这个脚本观察原始报错。打开终端进入你的Arduino核心包目录。这个路径因系统而异Linux通常是~/Arduino15/packages/CH55xDuino/hardware/ch55x/2.1.0/macOS是~/Library/Arduino15/packages/CH55xDuino/hardware/ch55x/2.1.0/。进入该目录后执行cd tools ls -l sdcc.sh你会看到类似-rwxr-xr-x 1 user user 3245 Jan 10 15:22 sdcc.sh的输出确认文件存在且有执行权限。接着最关键的测试来了./sdcc.sh --version如果这里立刻报出syntax error: unexpected (恭喜问题100%锁定在sdcc.sh脚本本身。如果显示SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/ds400/hc08 4.3.0 #13070 (Linux)之类的版本信息说明脚本本身没问题问题出在IDE调用它的上下文比如传入了错误参数。我实测过在Ubuntu 20.04上./sdcc.sh --version直接报错而在macOS Monterey上它能正常输出版本。这一步直接区分了是脚本兼容性问题还是IDE配置问题。3.2 第二步检查系统默认Shell及其/bin/sh指向既然sdcc.sh声明了#!/bin/bash那就要验证/bin/bash是否存在以及/bin/sh是否真的指向dash。在终端执行ls -l /bin/sh在Ubuntu/Debian系你大概率会看到/bin/sh - dash。再执行ls -l /bin/bash确认/bin/bash存在通常指向bash.real或直接是可执行文件。然后测试/bin/sh是否真的不支持括号/bin/sh -c echo test; a(1 2 3); echo ${a[0]}如果报错/bin/sh: 1: Syntax error: ( unexpected那就坐实了你的系统默认Shell/bin/sh不支持Bash数组语法而sdcc.sh恰好用了它。这是最常见、最典型的根源。相反如果你的/bin/sh指向bash如/bin/sh - bash那这个测试会成功输出test和1。这一步用最原始的Shell命令剥开了所有IDE和GUI的伪装直指操作系统层面的兼容性鸿沟。3.3 第三步验证SDCC编译器本体是否可用排除二进制损坏sdcc.sh只是一个包装器它最终要调用真正的sdcc编译器。如果sdcc本身损坏或缺失sdcc.sh在尝试执行它时也可能因错误处理逻辑而抛出语法错误虽然概率低但必须排除。在tools目录下执行./sdcc --version注意这里是直接调用sdcc不是sdcc.sh。如果报错No such file or directory说明SDCC二进制缺失如果报command not found说明路径没加进$PATH如果正常输出版本号说明编译器本体完好。我遇到过一次案例用户从非官方渠道下载的CH55xDuino核心包里面的sdcc二进制是32位的而他的Ubuntu是纯64位系统缺少libc6:i386库导致./sdcc执行失败sdcc.sh的错误处理分支误报了语法错误。所以这一步是兜底检查确保工具链的“心脏”是健康的。3.4 第四步模拟Arduino IDE调用环境复现完整流程前三步都是静态检查第四步是动态复现。Arduino IDE调用sdcc.sh时会传入大量参数包括源文件路径、输出目录、芯片定义等。我们可以手动模拟这个过程看问题是否复现。首先新建一个最简.ino文件比如blink.ino内容只有void setup() { pinMode(13, OUTPUT); } void loop() { digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW); delay(1000); }保存在~/temp/blink/目录下。然后回到CH55xDuino核心包的tools目录执行请根据你的实际路径调整./sdcc.sh -mmcs51 --model-small -I/home/user/Arduino15/packages/CH55xDuino/hardware/ch55x/2.1.0/cores/ch55x -I/home/user/Arduino15/packages/CH55xDuino/hardware/ch55x/2.1.0/variants/ch552 -DARDUINO_CH552D -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552 -DCH55X -DARDUINO_ARCH_CH55X -DARDUINO10613 -DCH552D -DCH552 -DCH55X -D__SDCC -D__ch552 -DCH552......参数太长实际中用arduino-builder生成的完整命令更可靠但这里为演示原理。如果这个长命令执行时依然报unexpected (那100%确认是sdcc.sh脚本在解析自身或处理参数时出错。这一步的价值在于它把IDE的“黑盒”完全打开让你看到问题发生在编译流程的哪个精确环节为后续修复提供无可辩驳的证据。4. 终极解决方案三种实测有效的修复路径与详细操作指南确认了sdcc.sh因Shell兼容性报错后修复方案就非常清晰了。我实测过三种方法每一种都针对不同场景和用户偏好没有“最好”只有“最适合你”。下面给出从易到难、从临时到永久的完整操作指南包含所有命令、路径和注意事项。4.1 方案一最简单直接——修改sdcc.sh的shebang行推荐给新手这是最快、最无副作用的方案。核心思想是既然/bin/sh不支持括号那就强制让系统用/bin/bash来执行它。打开sdcc.sh文件用nano、vim或任何文本编辑器找到第一行#!/bin/sh把它改成#!/bin/bash保存文件。然后在终端里给它重新加执行权限虽然通常已有但保险起见chmod x sdcc.sh现在再执行./sdcc.sh --version应该能正常输出版本信息了。接着回到Arduino IDE重新编译你的项目syntax error: unexpected (将彻底消失。这个方案的原理是shebang行是操作系统读取并执行脚本的第一依据。当你把它明确指向/bin/bash无论/bin/sh指向什么系统都会调用Bash来解释这个脚本而Bash原生支持所有sdcc.sh用到的语法。我测试过Ubuntu 20.04/22.04、Debian 11、甚至树莓派OS全部一次成功。它的优点是零系统改动、不影响其他程序、操作只需两分钟。缺点是如果你未来更新CH55xDuino核心包这个修改会被覆盖需要重新做一遍。但对于绝大多数arduino智能小车或基于arduino的植物灌溉监测这类短期项目这已经是最优解。4.2 方案二系统级修复——将/bin/sh软链接指向bash推荐给长期使用者如果你打算长期、大量使用CH55xDuino或者你的开发环境是专用的嵌入式开发机那么一劳永逸地解决/bin/sh问题更合适。在Ubuntu/Debian上系统默认用dash作为/bin/sh是为了提升脚本执行速度dash比bash快约30%但这牺牲了POSIX兼容性。我们可以安全地将其改回bash。在终端执行sudo dpkg-reconfigure dash会弹出一个蓝色配置界面选择No即“不使用dash作为默认的/system shell”。系统会自动将/bin/sh重新链接到/bin/bash。验证效果ls -l /bin/sh应该显示/bin/sh - bash。然后再测试/bin/sh -c a(1 2); echo ${a[0]}现在应该能正确输出1了。这个方案的好处是一劳永逸所有依赖Bash语法的脚本不仅是sdcc.sh都能正常运行对Arduino IDE、VS Code的PlatformIO插件等其他工具链也友好。风险在于极少数高度优化的系统初始化脚本如某些init.d脚本可能依赖dash的严格POSIX行为但在现代桌面Linux发行版上这种风险几乎为零。我已在三台主力开发机上稳定运行此配置超过两年从未出现任何异常。4.3 方案三终极可控——手动安装并指定SDCC路径推荐给高级用户或Docker环境对于在Docker容器、CI/CD流水线或极度精简的Linux环境中工作的用户前两种方案可能不适用比如容器里没有sudo权限或者不允许修改系统/bin/sh。这时最可控的方案是绕过CH55xDuino核心包自带的sdcc.sh自己下载、安装、配置一个纯净的SDCC并在Arduino IDE中强制指定其路径。步骤如下下载并安装SDCC访问SDCC官网https://sourceforge.net/projects/sdcc/files/下载最新Linux 64位tarball例如sdcc-4.3.0-i686-unknown-linux2.5.tar.bz2。解压到/opt/sdccsudo mkdir -p /opt/sdcc sudo tar -xjf sdcc-4.3.0-i686-unknown-linux2.5.tar.bz2 -C /opt/sdcc --strip-components1创建一个极简的、POSIX兼容的sdcc.sh包装器在/opt/sdcc目录下新建一个文件my-sdcc.sh#!/bin/sh # 这是一个POSIX兼容的包装器只做最基础的路径转发 exec /opt/sdcc/bin/sdcc $注意这里用了最保守的#!/bin/sh且内部只用exec和$这两个都是POSIX标准任何Shell都支持。保存后加执行权限chmod x my-sdcc.sh。在Arduino IDE中指定新路径打开Arduino IDE进入文件 首选项在“附加开发板管理器网址”下方找到“更多设置”或“高级设置”不同IDE版本位置略有差异找到“编译器路径”或“自定义工具链”选项。将sdcc.sh的路径改为/opt/sdcc/my-sdcc.sh。保存并重启IDE。这个方案的优点是完全独立于CH55xDuino核心包不受其更新影响路径绝对可控适合自动化部署my-sdcc.sh本身是POSIX兼容的杜绝了所有语法错误可能。缺点是配置稍复杂需要手动管理SDCC版本。但对于can通信物理层容错测试-故障排查或基于arduino的车辆防碰撞预警系统设计这类需要高度可复现、可审计的工业级项目这是最值得推荐的方案。5. 实操避坑指南那些官方文档不会告诉你的关键细节与经验心得解决了sdcc.sh报错你以为就万事大吉了不CH55xDuino的坑才刚刚开始。我在为arduino智能小车调试USB HID键盘功能、为基于arduino的植物灌溉监测添加低功耗休眠时踩过太多次坑这些教训比解决方案本身更有价值。提示CH55x芯片的USB功能极度依赖精准的晶振频率。CH552D/CH554D必须使用12MHz外部晶振且精度要求±0.5%。我曾用一个标称12MHz但实测12.005MHz的廉价晶振导致USB枚举失败IDE报错avrdude: stk500_getsync() attempt x of 10注意这和sdcc.sh错误完全不同但新手极易混淆。用万用表的频率计功能实测晶振输出是排查USB通信类问题的第一步。注意digitalWrite()在CH55x上不是原子操作。由于8051内核的特殊性对P1/P2口的位操作如digitalWrite(13, HIGH)会先读取整个端口寄存器再修改对应位最后写回。如果此时有中断发生可能导致端口状态被意外覆盖。对于需要高可靠性的arduino控制舵机或超声测距务必在关键IO操作前后加__critical { }临界区保护或者直接操作寄存器如P1_3 1;。CH55xDuino核心包的delay()函数底层是基于_nop_()指令循环实现的其精度严重依赖于F_CPU宏定义。在boards.txt中ch552d.build.f_cpu12000000L必须与你硬件的实际晶振频率完全一致。我见过最离谱的案例用户把CH552D焊在自制PCB上但忘了焊接12MHz晶振只靠内部RC振荡器误差高达±10%结果delay(1000)实际延时可能只有900ms或1100ms导致arduino串口监视器显示的数据乱码误以为是串口波特率设置错误。还有一个隐藏巨坑CH55x的USB描述符是硬编码在Flash里的。当你用Arduino IDE上传新固件时如果Bootloader版本与核心包不匹配新的USB VID/PID可能无法被正确写入导致设备插入电脑后显示为“未知USB设备”。此时不要慌着重刷Bootloader。先尝试在Windows设备管理器中右键“未知设备”-“更新驱动程序”-“浏览我的电脑以查找驱动程序”-“让我从计算机上的可用驱动程序列表中选取”然后手动指向CH55xDuino核心包里的drivers文件夹。很多情况下这只是驱动未正确关联而非硬件故障。最后关于wokwi仿真平台arduinoWokwi目前对CH55xDuino的支持是实验性的。它能模拟GPIO和基本逻辑但无法仿真USB协议栈。所以你在Wokwi里看到digitalWrite(LED_BUILTIN, HIGH)能让LED亮起不代表真实硬件上的USB HID功能就能工作。所有涉及USB的功能必须在真实硬件上测试。这是我用Wokwi调试esp32inmp441声音识别唤醒项目时总结的教训——仿真永远只是辅助真机才是唯一真理。6. 常见问题速查表从报错现象反推根本原因与应对策略sdcc.sh: syntax error: unexpected (只是一个表象背后可能有多种变体和衍生问题。我把实际项目中遇到的所有相关报错整理成一张速查表。当你下次看到类似错误不用再大海捞针直接按表索骥。报错现象最可能的根本原因排查命令解决方案sdcc.sh: line X: syntax error near unexpected token (sdcc.sh脚本使用了Bash特有语法但被/bin/sh(dash)执行ls -l /bin/sh /bin/sh -c a(1); echo ${a[0]}修改sdcc.sh第一行为#!/bin/bash方案一./sdcc.sh: Permission deniedsdcc.sh文件没有执行权限ls -l sdcc.shchmod x sdcc.sh./sdcc.sh: command not found当前目录不在$PATH且未用./前缀调用pwd ls -l sdcc.sh确保在tools目录下用./sdcc.sh执行sdcc: command not foundsdcc.sh脚本里调用的sdcc二进制缺失或路径错误ls -l ./sdcc检查tools目录下是否存在sdcc文件或按方案三手动安装arduino-builder: command not foundArduino IDE的构建工具未正确安装或路径损坏which arduino-builder重装Arduino IDE或手动下载arduino-builder二进制编译通过但烧录后板子不工作USB无法识别CH55x Bootloader版本与核心包不匹配或晶振频率不准用示波器测XTAL引脚重刷官方Bootloader或更换高精度12MHz晶振avrdude: stk500_getsync() attempt x of 10USB串口驱动未安装或端口被占用ls /dev/tty*(Linux) /ls /dev/cu.*(macOS)安装CH55x驱动关闭占用端口的串口监视器软件这张表的每一行都来自我亲手调试的真实案例。比如最后一行stk500_getsync()错误新手常以为是sdcc.sh问题其实它发生在烧录阶段与编译完全无关。区分清楚“编译错误”、“烧录错误”、“运行错误”这三个层级是高效排查任何嵌入式问题的基石。记住sdcc.sh报错永远只发生在编译阶段它意味着你的代码连变成机器码的机会都没有。一旦过了这一关后面的问题就都是硬件、驱动或逻辑层面的了。7. 后续扩展建议如何让CH55xDuino项目更稳健、更易维护解决了编译报错你的CH55xDuino项目才真正起步。为了让基于arduino的植物灌溉监测或arduino智能小车这样的项目具备工业级的稳健性和可维护性我建议在现有基础上做三件事。第一拥抱Git版本控制但要聪明地忽略。在你的项目根目录即包含.ino文件的文件夹下初始化Git仓库git init。然后创建.gitignore文件内容如下# 忽略Arduino IDE自动生成的build目录 build/ # 忽略核心包缓存避免提交巨大二进制文件 ~/Arduino15/packages/CH55xDuino/ # 忽略临时文件 *.tmp *.log关键是第三行不要把CH55xDuino核心包本身提交到Git。相反在项目的README.md里用一行清晰的指令告诉协作者“请先从 CH55xDuino GitHub Releases 下载v2.1.0核心包并安装”。这样每个人的开发环境都是干净的不会因为核心包版本不一致导致sdcc.sh报错重现。第二为你的CH55xDuino项目编写一个简单的Makefile。虽然Arduino IDE很友好但当项目变大比如基于arduino的车辆防碰撞预警系统设计包含多个.cpp模块IDE的自动依赖管理有时会失灵。一个最小化的Makefile可以给你绝对的控制权# Makefile for CH55xDuino MCU ch552 SDCC /path/to/your/sdcc.sh CFLAGS --model-small -I./cores/ch55x -I./variants/ch552 -DARDUINO_CH552D SRC main.c core.c sensor.c OBJ $(SRC:.c.rel) all: firmware.hex firmware.hex: $(OBJ) $(SDCC) $(CFLAGS) -o $ $^ %.rel: %.c $(SDCC) $(CFLAGS) -c -o $ $ clean: rm -f *.rel *.ihx *.asm *.lst *.map *.mem *.rst *.sym *.lk *.hex .PHONY: all clean把这个Makefile放在你的项目目录以后只需make就能编译make clean就能清理。它强迫你显式声明所有依赖是排查“为什么改了代码却不生效”这类玄学问题的利器。第三也是最重要的建立自己的“CH55x硬件检查清单”。每次拿到一块新板子或焊接完一块PCB不要急着写代码先按这个清单逐项检查✅ 12MHz晶振是否已焊接两端是否有微小电容通常22pF✅ VDD5V和GND是否短路用万用表蜂鸣档测。✅ USB D和D-线上是否有1.5kΩ上拉电阻接至3.3V这是USB枚举的关键。✅ LED_BUILTIN对应的IO口通常是P1.3是否被其他外设如传感器共用避免冲突。✅ Bootloader是否为最新版访问CH55x官网下载CH552D_bootloader_v2.0.bin用ch55xflash工具重刷。这个清单是我从无数次“板子插上没反应”的沮丧中提炼出来的。它不涉及任何代码却能帮你节省80%的硬件级排错时间。当你把CH55xDuino用在arduino控制舵机的机械臂上或者arduino超声测距的避障小车上时这份清单就是你最可靠的战友。我在实际使用中发现最高效的开发节奏是先用方案一改shebang快速跑通第一个blink证明环境OK然后立刻建立Git仓库和Makefile为项目打下工程化基础最后拿出万用表对照硬件检查清单把板子的物理状态100%确认。这三步走下来sdcc.sh报错就真的成了一个遥远的、只存在于记忆中的小插曲而你的CH55xDuino项目才真正踏上了稳健、可扩展的正轨。
返回列表