AI 不只是会写代码了:我让它真正操控 STM32 硬件
我写了一个 AI Agent,它能直接操控 STM32 硬件:从代码生成到编译烧录到自动调 Bug,全程不用人管
——开源项目 Gary CLI 技术深度解析:如何用大模型 + Function Calling 构建嵌入式开发的全自动闭环
文章定位:技术深度长文 + 项目宣传 + 能力展示 + 开源引流
阅读对象:嵌入式工程师、AI Agent 开发者、自动化开发爱好者、投资人/潜在合作方
一、写在前面
我是一个嵌入式工程师。
每次开始一个新 STM32 项目,工作流几乎都差不多:打开 STM32CubeMX,点一堆外设配置;生成工程;进 Keil 或者 VS Code 继续写代码;编译;烧录;上电;发现 LED 不亮;开始翻 Reference Manual 查寄存器;改代码;重新编译;重新烧录;再看串口;发现串口也没输出;怀疑时钟树;怀疑 GPIO;怀疑下载器;最后甚至怀疑自己。
一个看起来再简单不过的功能,比如“做一个呼吸灯”,从想法出现到真正跑在板子上,中间往往要花掉几十分钟。真正用于“思考逻辑”的时间其实很少,大部分时间都耗在工具链、配置流程、编译报错、下载流程和硬件联调上。
我一直在想一个问题:
既然大模型已经可以写代码,那它为什么不能继续往前走一步,直接把代码编译、烧录到 STM32 上,再根据真实硬件反馈自动修?
如果它能做到这一点,那么它就不再只是一个“代码补全工具”,而是一个真正意义上的 嵌入式开发 Agent。
于是,我做了 Gary CLI。
它不是一个简单的“让 AI 帮你生成 main.c”的脚本,而是一个可以和 STM32 开发流程真正闭环的 Agent:
- 你用自然语言描述需求
- 它自动理解任务并生成代码
- 它调用工具创建/修改工程
- 它自动编译
- 自动烧录到开发板
- 自动读取真实硬件反馈
- 如果发现不对,继续自我修复
- 直到结果满足目标
换句话说,Gary 试图让 AI 从“会写代码”进化成“真的把硬件做对”。
这篇文章,我不只想展示“我做了一个很酷的项目”,更想完整拆开它背后的设计逻辑:
- 为什么传统嵌入式开发这么耗时?
- 为什么大模型写嵌入式代码仍然不够?
- Gary CLI 的整体架构是怎么设计的?
- Function Calling 在这里到底起了什么作用?
- 硬件在环(HIL)闭环是怎么跑起来的?
- 它现在已经能做到什么?
- 它未来能演进到什么程度?
如果你是嵌入式开发者,我希望你看完之后会有一个感觉:
原来 STM32 开发真的可以被重新定义。


二、为什么我会做 Gary CLI
做嵌入式的人都知道,真正让人疲惫的往往不是“不会写功能逻辑”,而是整个流程太碎、太长、太依赖人工介入。
你要先配置工程,再写代码,再处理编译问题,再连接下载器,再烧录,再观察现象,再定位问题。很多错误甚至不是高级逻辑错误,而是极其机械的流程性错误:
- GPIO 模式配错了
- 定时器时钟没开
- 串口引脚复用错了
- 波特率和时钟树不匹配
- DMA 没初始化
- 下载脚本写错路径
- 工程文件引用丢失
- 编译器选项不一致
这些问题,本质上并不需要人类“创造性思维”来解决,但它们会大量吞噬工程师的时间。
更关键的是,现在大家都在说“AI 写代码”,但在嵌入式开发里,只会写代码其实远远不够。
因为嵌入式开发不是一个纯文本世界。
一个函数写得再漂亮,只要烧到板子上 LED 不亮,它就是失败的。
一个驱动逻辑看起来再合理,只要串口没输出,它就是没完成。
一个 PID 算法推导得再工整,只要电机抖成一团,它就还不能用。
所以我越来越明确地意识到:
嵌入式 AI 的关键,不是“代码生成”,而是“结果闭环”。
也就是说,一个真正有价值的 AI 嵌入式系统,必须具备下面这些能力:
- 能理解自然语言需求
- 能把需求拆成可执行步骤
- 能操作工具链而不只是吐代码
- 能接触真实硬件而不是只在沙盒里想象
- 能根据真实反馈自动修复错误
- 能把整个过程持续迭代,直到功能成立
Gary CLI 就是在这个目标下诞生的。
它最初并不是为了“做个项目拿来展示”,而是我真的想解决自己的痛点:
我希望以后做 STM32,不再是我亲自去搬运每一个重复步骤,而是我只负责描述目标,剩下的执行交给 AI。
这件事一旦成立,意义就不只是“省时间”了。
它意味着:
- 嵌入式开发门槛会被降低
- 开发速度会被大幅拉高
- 试错成本会被明显降低
- 原型验证会快很多
- 一个人就能做出过去需要小团队协作完成的东西
从这个角度看,Gary 不是一个“AI 帮我写代码”的工具,而是一个想把 嵌入式开发从手工流水线升级成自治系统 的尝试。


三、Gary CLI 到底是什么
一句话概括:
Gary CLI 是一个面向嵌入式开发的命令行 autonomous agent,它可以把自然语言需求转化为真实的 STM32 工程执行流程,并在真实硬件反馈下持续迭代。
这里面有几个关键词,值得展开说明。
1. 它是 CLI,而不是聊天玩具
我一开始就没打算把 Gary 做成一个“网页上聊两句,然后输出一段代码”的演示系统。
因为真正的开发行为发生在本地环境里:
- 工程文件在本地
- 编译器在本地
- CubeMX/Keil/STM32CubeCLT 在本地
- ST-Link 在本地
- 串口设备在本地
- 开发板就在 USB 口上
所以 Gary 采用 CLI 形态是非常自然的。它可以直接嵌进真实开发环境,而不是停留在一个远离生产流程的展示层。
2. 它不是单次生成器,而是 Agent
单次生成器的特点是:用户提一个需求,模型吐一段代码,任务结束。
Agent 的特点则完全不同。它更像一个“任务执行者”:
- 它要规划步骤
- 它要调用外部工具
- 它要读取中间结果
- 它要基于反馈继续行动
- 它要在失败后重新尝试
Gary 的关键价值就在这里:
它不是一次性回答问题,而是持续推动任务直到完成。
3. 它工作的对象不是纯软件,而是“硬件+软件系统”
这是 Gary 最特别的地方。
很多 AI Coding Agent 本质上还是在文件系统里工作:读代码、改代码、运行测试、修复报错。
而 Gary 面对的是更复杂的对象:
- GPIO
- UART
- SPI / I2C
- ADC
- PWM
- 中断
- 寄存器
- 开发板外设
- 真实电路行为
它必须面对“代码正确但硬件不工作”的现实,这也意味着它必须具备读取硬件反馈并继续行动的能力。
4. 它瞄准的是嵌入式开发闭环
Gary 的价值不是“帮你省掉写一两个函数”,而是把下面这整个闭环串起来:
需求 → 工程生成 → 代码实现 → 构建 → 烧录 → 反馈采集 → 错误修复 → 功能达成
一旦闭环真正跑通,Gary 的上限就不会只是“辅助工具”,而是可能成为一种新的开发范式。
图4:Gary CLI 命令行界面图

图5:Gary 的能力边界示意图

四、为什么普通大模型做不好 STM32 开发
很多人第一反应会是:
“大模型不是已经很会写代码了吗?那直接让它写 STM32 不就行了?”
表面上看,这个想法没错。实际上,问题远比想象中复杂。
1. 大模型只能看到文本,看不到硬件世界
模型生成代码,本质上是在做 token 预测。
它可以根据训练数据推断某个 HAL 函数该怎么写,也可以猜测 GPIO 初始化应该长什么样,但它并不知道:
- 你的板子现在有没有接上
- ST-Link 有没有识别到设备
- 烧录是否真的成功
- 串口有没有真实输出
- 电机有没有动
- LED 到底亮没亮
而嵌入式开发的成败,恰恰取决于这些“文本之外”的现实世界信息。
2. 代码正确不等于系统可用
在 Web 或普通后端开发里,一段代码通过单元测试,通常已经说明它有很高概率可用。
但在嵌入式领域完全不是这样。
你写的代码可能:
- 能编译,但外设不工作
- 能运行,但时序不对
- 能输出,但频率不对
- 能点亮,但占空比不对
- 能通信,但偶发丢包
- 能开机,但中断一来就 HardFault
所以嵌入式开发不能只停留在“源码层正确”,它必须走向“系统层验证”。
3. 普通生成模式没有行动能力
即便模型写得没问题,它也通常没有能力去主动执行:
- 它不会自己调用编译器
- 不会主动打开项目文件
- 不会操作烧录工具
- 不会去读取串口日志
- 不会看失败原因再继续修
没有工具调用能力,大模型永远只是一个旁观建议者,而不是执行者。
4. 没有闭环就没有真正的可靠性
大模型最大的问题不是“第一次会不会写错”,而是“写错之后怎么办”。
人类工程师之所以能把项目做出来,不是因为第一次就全写对,而是因为人类会:
- 看报错
- 改代码
- 再编译
- 再烧录
- 再观察现象
- 再推断问题
- 继续修
这其实就是一个闭环控制过程。
而如果 AI 没有这个闭环,它再聪明也只是一个高质量代码建议器,不是一个真正能完成任务的系统。
所以 Gary 的核心设计方向非常明确:
不是增强模型写代码的能力,而是给模型接上“手”和“眼”,让它具备执行、观察、修复的循环能力。
五、Gary CLI 的核心设计思路
Gary 的系统设计并不是从“怎么把模型接进来”开始的,而是从一个更实际的问题出发:
一个嵌入式任务要被自动完成,到底需要哪些最小能力单元?
我最后把它拆成了几个部分。
1. 自然语言理解层
用户不会用“请生成某个 C 文件的若干函数”这种方式提需求,用户会直接说:
- 帮我做一个 PA5 呼吸灯
- 配置 USART1 以 115200 输出 hello world
- 读取 ADC1 的某一路电压并通过串口打印
- 用 PWM 驱动一个舵机来回摆动
所以第一层一定是自然语言理解。模型需要把这些人类目标转化成结构化任务。
2. 任务规划层
一个嵌入式任务通常不是一步完成的。
比如“做一个呼吸灯”其实包含:
- 判断使用哪个定时器或 SysTick
- 配置 GPIO 输出或 PWM 通道
- 生成初始化代码
- 编写亮度渐变逻辑
- 构建工程
- 烧录上板
- 观察实际现象
- 若不符合目标,继续调整
所以 Gary 不能只是“收到需求就立刻写代码”,它要先能规划。
3. 工具调用层
这是 Gary 能从聊天机器人变成 Agent 的关键。
模型本身并不会编译,也不会烧录,更不会读串口。它必须通过工具系统来行动。
比如工具层可能负责:
- 读取和修改工程文件
- 调用 STM32 工具链
- 执行编译命令
- 调用烧录器
- 连接串口读取输出
- 获取寄存器/运行状态
- 分析失败日志
这一步一旦建立,模型就获得了“操作现实世界”的通道。
4. 状态反馈层
Agent 不是一直盲目向前跑,它必须不断读回状态:
- 编译通过了吗?
- 烧录成功了吗?
- 板子有没有响应?
- 串口是否输出预期内容?
- 任务是否真正完成?
没有反馈,后面的自我修复就无从谈起。
5. 自我修复闭环
这是我最看重的一层。
因为一个真正实用的系统,不是“第一次必须成功”,而是“即使第一次失败,也能自己靠反馈逐步逼近正确答案”。
Gary 的目标就是:
- 先执行
- 再观察
- 再诊断
- 再修改
- 再验证
直到完成。
这其实很像把嵌入式开发过程抽象成了一个闭环控制系统,而模型在里面扮演的是高层控制器。

六、Function Calling 在 Gary 里面到底做了什么
很多人提到 Agent,第一反应就是“调用工具”。
但真正把工具调用落到嵌入式开发上之后,你会发现 Function Calling 的意义远不只是“帮模型执行命令”。
它实际上承担了三个核心角色。
1. 把模型的意图转化成可执行动作
模型擅长表达意图,比如:
- 需要创建一个 PWM 工程
- 需要修改某个初始化文件
- 需要编译当前项目
- 需要读取串口输出
- 需要重新烧录目标板
但这些都只是意图。
Function Calling 把这些意图转成结构化调用,让外部系统真正去执行。也就是说,它是从“认知”到“行动”的桥梁。
2. 让模型从自由文本思考进入受约束执行
如果没有 Function Calling,模型很容易陷入“描述怎么做”,而不是“真正去做”。
而一旦有了函数调用机制,模型就会被迫在有限工具集中完成任务,这会让它的执行过程更稳定、更可控,也更容易审计。
比如:
- create_project(...)
- edit_file(...)
- build_project(...)
- flash_firmware(...)
- read_uart(...)
- inspect_registers(...)
这样的函数集合,实际上构成了 Gary 的“行动空间”。
3. 为闭环修复提供可重复的接口
嵌入式自动化最怕的不是失败,而是失败后无法标准化处理。
Function Calling 的价值在于:失败场景也可以被结构化处理。
例如:
- 编译失败 → 调用读取构建日志工具
- 烧录失败 → 调用下载器状态检测工具
- 串口无输出 → 调用串口采集工具
- 输出异常 → 调用代码编辑工具继续修复
这意味着整个闭环不是拍脑袋,而是可以反复跑、可调试、可扩展的。
从这个角度说,Gary 并不是“LLM + 一些脚本”,而是:
LLM 作为高层决策器,Function Calling 作为动作接口层,外部工具作为执行器,真实硬件作为被控对象。
这已经非常接近一个完整自治系统的雏形了。
这里插图建议
图8:Function Calling 调用链示意图
内容建议:用户一句话 → LLM 输出函数调用 → 工具执行 → 返回结果 → LLM 再决策。
作用:帮助 AI 圈读者理解你的系统不是普通 prompt engineering。
图9:真实函数调用日志截图
内容建议:截取一段你系统里的函数调用日志。
作用:这个图的说服力很强,证明不是纸上谈兵。
七、从“生成代码”到“控制硬件”:Gary 的闭环是怎么跑起来的
Gary 最关键的地方,不是它能生成代码,而是它能把“代码生成”推进到“硬件验证”。
这个闭环大致是这样跑的。
第一步:接收目标
用户输入一句自然语言,比如:
帮我用 STM32 做一个呼吸灯,接在 PA5,上电后自动循环亮灭。
Gary 先识别出这是一个具体的嵌入式任务,并提取关键信息:
- 平台:STM32
- 外设:GPIO/定时/PWM
- 引脚:PA5
- 行为:亮度周期变化
- 触发方式:上电自动运行
第二步:规划任务与生成工程修改方案
接着它会规划:
- 当前项目是否已存在
- 是否需要创建或修改 CubeMX 配置
- 应该使用哪种方式实现呼吸效果
- 需要修改哪些源文件
- 需要如何组织主循环或定时中断
第三步:修改代码并触发构建
然后它通过工具去:
- 改工程文件
- 写入控制逻辑
- 执行构建命令
这一步如果编译报错,它不会停在“报错了”,而是继续读取日志并修复。
第四步:烧录到硬件
如果编译通过,就继续烧录固件到开发板。
这是很多“AI 写嵌入式代码”系统根本没有真正做到的一步。
因为一旦真的走到这一步,你面对的就是现实世界,而不是文字游戏。
第五步:采集硬件反馈
烧录后,Gary 需要知道结果对不对。
这时候就要从真实硬件里拿反馈:
- 串口日志
- 运行状态
- 寄存器信息
- 可能还有其他传感/观测方式
第六步:判断是否符合目标
如果目标是“串口输出 hello world”,那它就要检查串口里是不是真的出现了 hello world。
如果目标是“某个功能动作达成”,那它就要根据观测结果判断是否真正成功。
第七步:如果失败,进入自我修复
比如:
- 没有串口输出 → 可能波特率、时钟、引脚复用有问题
- LED 不亮 → 可能 GPIO 模式、管脚映射、时序逻辑有问题
- 程序跑飞 → 可能中断配置或内存访问异常
Gary 会把这些反馈重新喂给模型,再进行下一轮修改。
这时候,它已经不是一个代码生成器,而是真正在执行“感知—决策—行动—再感知”的循环。
八、Gary 已经做到了什么
一个技术项目最怕讲得很大,但拿不出已经完成的能力。
所以这里我更愿意直接说现实一点:Gary 现在已经在做的,不是一个“未来概念”,而是一套已经具备实际执行能力的系统雏形。
根据当前的实现方向,它至少体现出了几个非常关键的能力:
1. 自然语言驱动嵌入式任务
你不需要先手写完整工程逻辑,而是可以先说需求,再让系统开始执行。
这意味着交互方式发生了改变:
过去是“人写实现,机器执行”。
现在是“人写目标,Agent 生成并执行实现”。
2. 能真正接入 STM32 开发流程
Gary 不是停留在“输出一段建议代码”的层面,而是进入到了真实工具链流程:
- 处理工程
- 编译
- 烧录
- 反馈读取
这是它和很多演示型 AI 项目最本质的区别。
3. 开始具备硬件在环自我纠错能力
这点非常关键。
只要系统能基于硬件反馈继续修复,那么它就已经从静态生成器变成了动态闭环系统。
哪怕现在这个能力还在持续增强中,它的方向已经非常明确,而且价值极高。
4. 具备扩展为通用嵌入式 Agent 平台的潜力
如果今天 Gary 可以操作 STM32,明天理论上就可以逐步扩展到:
- 更多 STM32 系列芯片
- 不同 IDE / 工具链
- RTOS 工程
- 多外设联动任务
- 调试器反馈
- 更复杂的传感器与执行器系统
它的想象空间远不只是“自动写一个点灯程序”。
这里插图建议
图8:Gary 已实现能力清单图

九、这个项目真正难的地方,不是写代码,而是把世界接进来
如果只是做一个能生成 STM32 示例代码的助手,其实并不算特别难。
真正难的是:
怎么让一个语言模型稳定地接触真实硬件世界,并且在这个过程中不失控。
这里面至少有几个现实难点。
1. 工具链碎片化
嵌入式开发环境天然是碎片化的:
- 不同芯片系列
- 不同 IDE
- 不同构建系统
- 不同烧录方式
- 不同调试接口
- 不同串口设备命名
- 不同工程目录结构
要让 Agent 稳定工作,就必须把这些差异抽象掉一部分,不然模型根本无法形成稳定执行策略。
2. 现实世界反馈不总是干净的
代码世界里的错误往往是明确的,例如编译器报错会告诉你哪一行有问题。
但硬件世界不是这样。
它可能只是:
- 没反应
- 闪得不对
- 输出乱码
- 偶尔成功
- 上电正常,复位不正常
- 单步正常,全速异常
这些反馈高度模糊,对模型推断能力和系统反馈设计都提出了更高要求。
3. 闭环系统必须控制行动成本
一个 Agent 如果没有边界,很容易陷入无休止重试:
- 一直改代码
- 一直编译
- 一直烧录
- 一直读不到有效反馈
所以系统不仅要能行动,还要能限制行动、评估收益、设定停止条件。
4. 必须在“通用性”和“可靠性”之间做权衡
做得越通用,越容易不稳定。
做得越针对场景,越容易快速跑通。
Gary 的一个现实路线应该是:
先把若干高频 STM32 场景做深做稳,再逐步扩展边界。
而不是一开始就试图吃掉整个嵌入式世界。
十、Gary 为什么可能不只是一个开源项目,而是一种新的方向
我越来越觉得,Gary 真正有价值的地方,不只是“它能帮我省事”,而是它有机会触碰一个更大的方向:
让 AI 真正参与现实世界的工程执行。
过去很多 AI 系统本质上都还停留在信息世界里:
- 写文案
- 写代码
- 总结资料
- 回答问题
- 生成图像
但嵌入式开发不一样,它天然是连接数字世界和物理世界的接口层。
代码最终会变成:
- 电平变化
- 信号输出
- 电机转动
- 传感器采样
- 屏幕刷新
- 执行机构动作
所以如果 AI 能够可靠地进入嵌入式开发链路,那它其实是在迈向一个更大的命题:
AI 不只是理解世界,而是开始操作世界。
从这个视角看,Gary 的潜在意义包括:
- 让硬件原型开发速度显著提升
- 让个人开发者获得更强的工程杠杆
- 让教育场景中的嵌入式学习难度下降
- 让更多非资深工程师也能快速验证硬件创意
- 为更高层次的机器人/自动化系统提供底层开发自治能力
如果未来继续往前走,它甚至可能不只是一个 CLI 工具,而会变成:
- 一套嵌入式自治开发平台
- 一个软硬件一体化开发环境
- 一块为 AI 原生开发准备的控制板
- 一个面向现实系统构建的 Agent 基础设施
这件事的上限,我认为远没有被看到头。
十一、我为什么选择开源
如果只是为了做一个“看起来很厉害”的东西,其实完全可以只做 demo,不必开源。
但我还是选择把 Gary 做成开源项目,因为我希望这件事不仅属于我自己。
一方面,开源是最好的验证方式。
真正有价值的项目,不怕别人看结构,不怕别人跑流程,不怕别人提 issue。相反,只有把它放到真实社区里,才能知道它到底是不是有意义。
另一方面,这个方向本身就值得被更多人一起推进。
AI + Embedded 这件事,今天依然是很早期的。
很多问题没有标准答案,很多基础设施还不存在,很多最佳实践也还没形成。
开源可以让这条路走得更快。
对我来说,开源 Gary 还有一个很现实的原因:
我希望让更多人看到,嵌入式开发并不是只能继续沿用几十年前那套低效率工作方式。
我们完全可以把它重新组织一遍。
这里插图建议
图9:GitHub 仓库截图

十二、如果你也是做嵌入式的,你应该能理解这种感觉
我做 Gary 的过程中,最强烈的感觉其实不是“我做了个炫酷项目”,而是:
我真的不想再重复那些明明可以被自动化掉的事了。
我不想再为了一个简单功能,机械地:
- 点配置
- 改文件
- 编译
- 烧录
- 看报错
- 再改
- 再烧
这些动作本身当然重要,但它们不应该继续大量占据工程师的生命时间。
工程师最有价值的部分,应该放在:
- 定义目标
- 设计系统
- 判断方案
- 做关键取舍
- 验证边界条件
- 创造新东西
而不是一直被困在重复流程里。
所以 Gary 对我来说,不只是一个项目,也是一种很明确的态度:
让机器去承担重复执行,让人回到真正有创造力的位置上。
我觉得这件事,在嵌入式领域尤其值得做。
因为这个行业太久没有被真正意义上的“生产力工具革命”触碰到了。
十三、Gary 接下来会往哪里走
如果只把 Gary 看成“现在能自动做几个 demo”,那就低估它了。
我更关心的是接下来怎么把它往真正可持续的方向推进。
我认为接下来至少有几个重要方向:
1. 提升闭环修复成功率
这决定它是不是一个真正能交付结果的 Agent。
2. 扩展更多 STM32 与外设场景
例如:
- UART
- ADC
- PWM
- I2C/SPI
- DMA
- 定时器
- 多任务/RTOS
3. 增强对硬件反馈的理解能力
比如更丰富的串口日志分析、寄存器状态读取、错误模式归因等。
4. 做出更稳定的技能系统
把常见嵌入式任务沉淀成可复用技能模块,减少每次都从零推理的成本。
5. 从工具走向平台
一旦某些能力足够成熟,Gary 就不该只是一个命令行程序,而应该逐渐变成面向现实开发场景的平台型产品。
这也是我对它最长期的期待。
十四、结语
Gary CLI 这件事,对我来说并不是“给 AI 套个 STM32 外壳”这么简单。
它真正吸引我的地方在于:
它在尝试把语言模型从“会说、会写”推进到“会做、会验证、会修复”。
而嵌入式开发,恰好是最适合验证这件事的土壤之一。
因为这里有明确目标、有真实反馈、有执行链路,也有足够复杂的问题空间。
如果这条路继续走下去,我相信它最终改变的不会只是 STM32 开发效率。
它可能会改变我们理解“AI 工程系统”的方式。
未来的软件 Agent 会越来越多。
但真正有价值的,可能是那些能走出屏幕、接触设备、影响现实结果的 Agent。
Gary 正在朝这个方向走。
而我也希望,有更多人能看到这件事的意义。
如果你对这个项目感兴趣,欢迎来看看、提建议、提 issue,或者一起把这条路走下去。
Gary CLI 目前已经开源。
如果你对 AI Agent、STM32 自动化开发、硬件在环自修复这类方向感兴趣,欢迎交流。
我也很希望认识做嵌入式、Agent、机器人、智能硬件方向的朋友。
项目地址:https://github.com/PrettyMyGirlZyy4Embedded/garycli
官网:https://www.garycli.com
协议:Apache-2.0 开源
如果觉得有用,请给个 ⭐ Star,这是对开源项目最好的支持。
"Just Gary Do it."