新闻详情

新闻详情

首页 / 资讯中心 / 详情

ICP、ISP、IAP一次讲透:单片机固件烧录方式全解析

发布时间:2026/9/29 1:54:17来源:尧图网络
ICP、ISP、IAP一次讲透:单片机固件烧录方式全解析
1. 烧录的本质你以为是“复制文件”其实是在“烙”芯片1.1 从“空白芯片”说起为什么要烧录很多刚接触单片机的人会把“烧录”理解成“把程序复制进芯片”这个说法听着没毛病但会带来一个认知偏差你会下意识觉得它和往U盘里拷文件是一回事。直接把程序拖进去不就行了为什么还非要搞出ISP、ICP、IAP这么一堆名词实际上烧录和复制文件有本质区别。芯片出厂时内部Flash存储器是“空白”的也就是全部为0xFF状态没有任何可执行代码。你拿到的MCU其实就是一块“什么都不会”的硅片它的一切行为——从引脚电平、UART波特率到中断优先级、时钟树配置——都是由内部Flash中的机器码决定的。烧录的本质就是把编译好的机器码按照芯片厂商标定的时序协议逐字节写入Flash存储单元同时完成必要的校验和配置。这个过程不像存取文件那样由操作系统统一管理而是需要编程器或者芯片内部预置的引导代码直接和Flash控制器打交道每条命令都要精确到时钟周期。这也是为什么烧录工具、烧录方式会有如此多的讲究。1.2 Flash的物理特性决定了烧录方式想理解ISP、ICP、IAP为什么长成现在这个样子先得搞清楚Flash存储器的几个物理限制。Flash写入的最小单位通常是“页”Page擦除的最小单位是“扇区”Sector或“块”Block。你没法只修改一个字节——必须先擦除整个扇区再整体写入。擦除操作会让扇区全部变回0xFF写入则是把某些位从1改成0。注意这个过程不可逆想改回去就得再擦一遍。Flash有擦写寿命限制常见的NAND Flash约10万次MCU内置Flash通常是1万到10万次不等。有了这些基础我们再回头看三种烧录方式就会清楚很多它们本质上是“不同的烧录执行者、不同的触发时机、不同的物理链路”的排列组合。2. ICPIn-Circuit Programming在电路编程最直接也最“硬核”2.1 ICP的基本原理ICP全称In-Circuit Programming中文常译为“在电路编程”。它的核心特点是通过外部编程器直接通过芯片的调试接口如JTAG、SWD访问芯片内部的Flash控制器把固件写进去。所谓“在电路”意思是芯片不需要从目标板子上拆下来直接通过板上的调试接口引脚就能完成烧录这是目前量产和调试阶段用得最普遍的方式之一。ICP的工作流程大致是这样的外部编程器通过JTAG/SWD接口与芯片建立连接。编程器发送特定的调试协议命令比如ARM的CoreSight调试接口命令。芯片进入调试模式CPU被暂停编程器获得对Flash控制器的直接访问权限。编程器执行擦除、写入、校验等操作。烧录完成后复位芯片程序开始运行。这个过程中芯片内部的CPU实际上“不干活”它只是被动地配合外部主机访问Flash。你可以把ICP想象成医生用内窥镜直接伸进病人体内做手术——外部设备直接操作内部器官Flash。2.2 JTAG和SWD两个常见的ICP接口JTAGJoint Test Action Group联合测试工作组是历史最悠久的调试/烧录接口之一标准IEEE 1149.1。它通常占用5个引脚TCK、TMS、TDI、TDO、TRST。注意JTAG并不仅仅用于烧录它还用于边界扫描测试Boundary Scan Test是PCB工厂测试的重要工具。SWDSerial Wire Debug串行线调试是ARM公司推出的更精简的调试接口只用2根线SWDIO和SWCLK。数据结构上SWD比JTAG更高效传输速率在同等时钟下也更高。现在很多MCU项目调试和烧录都直接选SWD省引脚。两者共同的特点是它们都是“调试口”不是“烧录口”。也就是说你不烧录时它照样可以用来实时调试、断点、单步烧录只是它的一个功能。这是ICP和ISP最大的区别之一。2.3 ICP的实际场景和显而易见的短板ICP的应用场景非常广研发调试阶段每次改完代码要快速下载验证SWD接口一键烧录效率最高。小批量产使用脱机烧录器如J-Link批量烧录底座多台同时烧速度用秒来计算。bootloader损坏后的恢复IAP或ISP之后如果boot损坏导致芯片变“砖”ICP是唯一的救回手段。但ICP有一个很明显的短板必须依赖外部硬件。你需要一台烧录器/调试器还要接线。对于已经装在设备内部、没有引出调试接口的产品ICP就无能为力了。而且某些封装比如BGA引脚无法引出JTAG/SWDICP也会受限。3. ISPIn-System Programming在系统编程Bootloader是背后的“翻译官”3.1 ISP的真正原理芯片出厂时已经内置了一段引导程序ISP全称In-System Programming中文叫“在系统编程”。很多人会把ISP和ICP搞混因为从用户视角看两者都是在板子上烧录。但内部原理完全不同。ISP的核心在于芯片出厂时厂商已经在ROM里预置了一段引导代码Bootloader。这段代码负责通过某个约定的通信接口UART、SPI、USB、I2C等接收外部数据然后调用芯片内部的Flash编程驱动把数据写入Flash。所以ISP烧录时真正执行Flash写入的其实是芯片自己——外部主机只是负责把固件文件“喂”给芯片它不用直接操作Flash控制器。听起来好像没啥大不了但试想一下这意味着芯片只需要有UART或者USB接口就能实现烧录不需要JTAG/SWD不需要外部编程器。一颗芯片、一对串口线、一个USB转串口模块就能完成烧录。3.2 ISP的启动机制与常见物理链路芯片怎么决定进入ISP模式还是正常运行用户程序通常根据特定引脚的电平或启动配置决定STC8051系列冷启动断电再上电时如果P3.0/P3.1电平满足条件内置引导程序接管串口进入ISP模式。STM32通过BOOT0/BOOT1引脚电平选择启动源。BOOT01时从系统存储器System Memory启动那里存的就是ISP引导代码。NXP LPC系列通过ISP引脚如ISP_EN在复位时拉低芯片进入UART ISP模式。这些引导代码支持的多为串口通信协议协议格式通常是厂商私有的比如STC的串口协议就是不公开的所以你必须使用厂商提供的ISP下载软件STC-ISP、Flash Loader等来配合。常见的ISP物理链路包括链路类型典型应用速率/特点UARTSTC8051、STM32、GD32、HC32最普及最高可达几Mbps取决于波特率USBSTM32 DFU直接USB枚举无需外部模块SPI部分高端MCU、Nor Flash注意区分高速适合大镜像文件CAN汽车电子领域比较常见抗干扰能力强适合车载设备另外很多工程师用“串口下载”一词其实口语中的串口下载通常就是指ISP因为UART是最常见的ISP物理链路。3.3 关于STM32/GD32的ISP烧录实操细节以STM32F1/F4为例完整的ISPUART烧录流程是这样的把BOOT0引脚拉高BOOT1拉低让芯片从系统存储器启动。通过USB转TTL模块连接UART1PA9/PA10或UART2根据型号。给芯片上电注意顺序是先接线再上电。运行STM32CubeProgrammer或Flash Loader Demonstrator选择串口、设置波特率连接芯片。加载Hex/Bin文件执行擦除、编程、校验。编程完成后把BOOT0拉低复位芯片程序正常启动。GD32F103的ISP流程与STM32F103基本一致因为它本身就是兼容意法半导体引脚定义的国产替代芯片。GD32的ISP也走串口BOOT01从系统引导区启动。不过注意一点GD32部分型号的ISP协议和STM32不完全相同建议使用GD官方或适配过的工具如GD32 MCU ISP Programmer不要直接用STM32CubeProgrammer去烧容易报连接失败或校验错误。3.4 ISP烧录的隐藏“坑”与边界用ISP烧录时有几个很现实的问题得注意Bootloader占用空间芯片出厂内置的ROM引导程序不算用户Flash但ISP模式下用户Flash会被完整擦除所以不存在空间占用冲突。这一点和IAP不同。波特率匹配ISP下载失败最常见的根因是波特率过高或线材过长导致误码。建议先用低波特率如9600或115200建立连接再抬高。实测下来115200以下基本稳定460800以上对线材和电平转换模块的要求明显变高。冷启动时序STC芯片要求“点击下载后再给芯片上电”如果你顺序搞反了工具就会一直提示“等待上电”。新手第一次用往往卡在这里好几天。ISP不是万能的对于已经把BOOT引脚复用为GPIO、无法拉高的产品或者没有引出串口的设备ISP方案直接失效。4. IAPIn-Application Programming在应用编程让设备运行时自己烧自己4.1 先理解IAP的“自反性”IAP全称In-Application Programming中文叫“在应用编程”。它的核心特征是芯片在运行用户程序的过程中由用户程序自己完成对Flash的擦写从而实现固件在线升级。注意这个区别ICP和ISP都是“外部主机”驱动的只有IAP是“设备自己”驱动的。这是IAP最本质的特征也是它被大量用于OTAOver-The-Air空中升级的原因——设备可以在收到新固件后自己把自己更新掉不需要任何外部硬件或人工干预。IAP的实现通常需要将Flash划分为两个区域Bootloader区存放引导程序。上电后CPU首先执行Bootloader它负责检查是否需要更新App、是否需要从某个通道串口、CAN、WiFi模块等接收新固件以及跳转到App区。App区存放应用程序即实现产品功能的代码。App运行过程中可以接收新固件数据并写入预留的Flash区域或者在收到升级指令后重启进入Bootloader由Bootloader完成完整升级。4.2 完整的分区设计与流程拆解拿一个经典案例来说以GD32F103为例如果芯片Flash为64KB典型分区可以这样规划区域起始地址大小内容Bootloader0x08000000~16KB引导程序负责串口/OTA升级与App跳转App0x08004000~32KB应用程序参数存储区0x0800C000~4KB存放升级状态、版本号等关键参数升级暂存区可选0x0800D000剩余存放接收到的升级包也可直接边收边写注意GD32F103和STM32F103的Flash扇区大小并不完全相同GD32F103一般是4KB一个扇区小容量型号STM32F103大容量型号是前4个扇区各16KB、后续扇区各64KB。做IAP分区前务必备份芯片手册确认。典型的IAP升级流程如下设备正常运行App。App程序周期性检查升级标志如GPIO引脚状态、串口收到特定指令、云端下发OTA指令。App判断需要升级保存新固件到暂存区或直接通知Bootloader“准备接收”然后软复位。CPU复位后从0x08000000执行Bootloader。Bootloader首先判断升级标志位是否为“有升级请求”。若需要升级Bootloader通过串口/CAN/以太网接收固件包每收到一包数据就调用Flash写驱动写入App区边收边写全部写完后进行CRC校验。校验通过清除升级标志位跳转执行App区代码校验失败则保留旧App继续运行或者再次进入接收模式重传。跳转AppBootloader设置好栈指针从App区首地址读取MSP初值、设置向量表偏移然后跳转到App的复位函数。4.3 关键代码与底层逻辑以GD32F103为例这里贴一段核心逻辑供参考。首先是Bootloader中的跳转代码/* Bootloader跳转至App的C语言实现 */ typedef void (*pFunction)(void); uint32_t app_jump_address 0x08004000; /* App起始地址 */ uint32_t app_msp_value; pFunction app_reset_handler; /* 检查App区首字是否为合法栈顶地址RAM范围内 */ app_msp_value *(volatile uint32_t *)app_jump_address; if ((app_msp_value 0x20000000) (app_msp_value 0x20010000)) { /* 取App复位函数地址 */ app_reset_handler (pFunction)(*(volatile uint32_t *)(app_jump_address 4)); /* 设置主栈指针 */ __set_MSP(app_msp_value); /* 设置向量表偏移使App的中断能正确响应 */ SCB-VTOR app_jump_address; /* 跳转 */ app_reset_handler(); }这里有几个非常关键的细节必须是先设置向量表偏移再跳转。否则App里的UART中断、定时器中断一律进错向量直接跑飞。跳转前要把用到的外设停掉、中断关闭。如果Bootloader在跳转前还在开着某个中断跳转后该中断会以App的外设状态去执行轻则异常重则HardFault。检查栈顶地址合法性是一个很有效的健壮性手段。很多量产设备在Bootloader里加了这个判断后遇到App区为空或部分写入的情况就不会跑飞了。4.4 “IAP Boot里定义的变量复位后会怎样”——这个热搜问题确实很多人搞错搜索热词里有一条很有意思的“iap boot里面定义的变量复位后会怎样”。这个问题新老工程师都会踩坑值得展开说清楚。这里要区分“变量”的存储位置与生命周期。Bootloader代码中定义的局部变量和全局变量在默认情况下存储在RAM中。上电复位Power-on ResetPOR的情况芯片刚刚上电RAM的内容是“未知”的实际上大部分MCU的SRAM会初始化为0x00但手册不会做出保证。Bootloader的启动代码startup文件会把全局变量和static变量初始化——注意是“初始化”不是“恢复”。所以复位后变量取的是你写在代码里的初始化值而不是复位前的值。软件复位Software Reset如NVIC_SystemReset()的情况RAM不会被清空所以在“复位瞬间”变量的物理值还在。但启动代码紧接着就会执行.data段的拷贝和.bss段的清零把你的全局变量覆盖回初始值所以效果和上电复位一样。复位后Bootloader再次启动想要“记住”上次的状态该怎么做答案很简单写到Flash的专用参数区或者用芯片的备份寄存器Backup Register。以GD32F103为例/* 记录Bootloader中的状态到Flash参数区 */ void save_upgrade_status(uint32_t status) { uint32_t addr 0x0800C000; /* 参数区起始地址 */ uint32_t status_addr addr (FLASH_PAGE_SIZE * 0); flash_unlock(); flash_page_erase(status_addr); flash_word_program(status_addr, status); flash_lock(); } uint32_t read_upgrade_status(void) { return *(volatile uint32_t *)0x0800C000; }还有一种更优雅的方案是用“备份SRAM”或“备份寄存器”这类存储区在软件复位后不会被清除但不适用于上电复位。所以如果升级流程涉及断电后再上电比如用户拔电重启后才触发升级那只有Flash方案稳妥。4.5 几个具体芯片的IAP重点搜索热词里有多颗具体芯片的IAP需求这里一并说下STM32H750VBT6这颗芯片很有意思它虽然拥有1MB Flash但实际只有128KB的Flash剩余空间无物理介质做IAP时分区规划要特别谨慎很多网友试图把App放到超过128KB的地址结果写进去读出来全是0xFF。建议的做法是利用外部QSPI Flash存放App通过Bootloader映射到地址空间执行。HC32L136这是华大半导体小华的低功耗MCU国产芯片在IAP实现上和STM32类似但需要注意的是其Flash操作需要调用芯片厂商提供的驱动库不要直接照搬STM32的Flash寄存器代码。另外它的中断向量表偏移机制也略有区别不支持SCB-VTOR的方式需要在代码中做向量重定向。GD32F103前面讲了完整的流程。GD32对STM32的兼容只是“软硬件大致兼容”Flash模块内部控制寄存器名称和状态位不完全一样用ST标准外设库去操作GD32的Flash会有兼容性问题。建议直接用GD32提供的Firmware Library。5. ICP / ISP / IAP三者到底怎么选一次说透5.1 一张表读懂核心区别对比维度ICP在电路编程ISP在系统编程IAP在应用编程谁在执行烧录外部编程器芯片内置ROM引导程序用户自己的App代码是否需要外部编程器需要J-Link、ST-Link等不需要只需串口/USB线完全不需要设备自升级是否占用用户Flash否否引导代码在ROM是需预留Bootloader区域触发方式外部工具主动连接特定引脚电平 复位时序软件运行中自行触发典型接口JTAG、SWDUART、USB、SPI任意通信接口UART/SPI/CAN/USB/WiFi等能否实现远程升级不能基本不能可以OTA的基础适合场景研发调试、量产烧录产线烧录、售后补烧产品固件在线升级、维修站升级烧录速度快SWD可达MHz级时钟中等受串口波特率限制取决于通信协议可以做得很快Boot损坏后能否恢复能不能ROM也被跳过不能这里有个容易混淆的点得专门强调很多人以为ISP和IAP都是“在线升级”因此混为一谈。实际上ISP是“用系统里的预设程序去做外部指令的搬运工”它本质还是外部主机在控制而IAP是“应用程序自己理解升级协议自己搬砖”。IoT设备的OTA升级底座是IAP不是ISP。5.2 选型决策树与实战判断实际项目怎么选我的建议是分阶段来看研发期无条件选ICPSWD/JTAG因为你要频繁烧录、断点调试这是效率最高的路子。量产的第一次烧录如果产线有烧录工装选ISP或ICP都行。ISP的好处是只要引出了串口就能烧不用买昂贵的脱机烧录器ICP的好处是速度快适合大批量。但注意很多国产MCU量产烧录还需要先“加密”或“读保护”ICP在這方面支持更全。售后升级/远程升级必须有IAP能力。先用ICP或ISP把Bootloader烧进去之后所有升级走IAP通道。如果产品需要远程OTA那Bootloader本身也得支持OTA更新自身即Bootloader也要有覆盖性升级机制或者拆成Bootloader1 Bootloader2双保险模式。这个“双Bootloader”的概念对做量产产品的朋友特别重要。为什么因为Bootloader如果升级失败且自身不带恢复机制芯片就彻底变砖了只能返厂拆壳用ICP救。很多工程师第一版只做单Bootloader App升级App很顺直到某天想升级Bootloader的串口波特率配置时升级了一半断电然后整个产品废掉。双Bootloader回滚机制虽然不是绝对必要的但如果在手成本允许强烈建议加上。6. 实操避坑与经验笔记6.1 烧录失败排查的固定套路碰到烧录失败不要急着换线、重装驱动按下面的顺序排查大多数问题能在5分钟内定位先查供电目标板必须在烧录过程中保持稳定供电。尤其用USB转串口模块给目标板供电时USB端口的电流限制会导致电压被拉低烧录中途直接失败。这种情况在STC的ISP和STM32的串口ISP中非常常见。建议独立供电或者用带稳压芯片的USB模块。再查电平匹配目标板是3.3V逻辑你用5V的USB转串口模块去接虽然很多模块号称兼容3.3V但实际高电平容易被识别异常导致通信误码。直接用3.3V的UART模块如CP2102、CH340G配置为3.3V模式最省心。然后查复位/BOOT引脚这部分要做成“能现场测量”的状态。比如用万用表确认BOOT0引脚是不是真的被拉高了——很多开发板的BOOT拨码开关接触不良拨了半天实际电平没变。最后才考虑速率和协议问题把波特率降到9600再试一次如果低速率能连上说明链路没问题而是速率设置的锅。6.2 IAP代码中最容易被忽视的三个“雷”雷点一向量表偏移之后调试器的断点全部失效如果你在IAP的App里开了调试器SWD跳转后调试器的断点信息会错乱常见表现是在App里设置的断点断不在正确位置或者断在完全无关的地方。这不是你代码写错了而是调试器没有处理向量表偏移。解决方法是更新调试器固件/软件或者在调试会话中手动指定VTOR的值。雷点二App编译链接时的起始地址设置IAP的App工程链接脚本必须把起始地址设为App分区首地址如0x08004000如果忘了改编译出来的App自带的中断向量表位于0x08000000运行时就和Bootloader冲突了。这类问题排查起来很隐蔽因为程序多数情况下能跑起来——只要你不触发任何中断它就看似正常一旦按下按键产生一个外部中断直接死机。排查手法是看map文件里的vector_table和reset_handler地址。雷点三升级过程中断电这是所有IAP方案都绕不开的话题。任何“边收边写”的升级方案都必须引入CRC校验和失败回滚机制。实测下来即使加了CRC校验如果升级过程中断电导致App区和数据区部分写入下次上电Bootloader会陷入“升级标志位存在但数据不完整→反复重试→无法跳转App”的循环。可靠的方案是设计“临时区 交换区”的双区机制新固件先写入临时区彻底校验通过后才整体拷贝/交换到App区。这不仅解决断电问题还能应对“升级包本身损坏”的情况。6.3 一些搜索词里的其他信息点“ISP图像处理”、“ISP Pipeline”、“FPGA ISP”这些热词搜索其实是另外一套技术体系——Image Signal Processor图像信号处理器。它们和芯片烧录中的ISP完全同名但不同义。大家在查资料时要注意区分在嵌入式烧录语境里ISPIn-System Programming在摄像头/图像领域ISPImage Signal Processor。遇到资料先看上下文别拿图像处理的知识去理解烧录。同理“ICP配准”是医学影像/三维点云领域的术语和芯片烧录的ICP也不是一回事“IAP应用内购买”是苹果iOS生态的概念和嵌入式IAP半毛钱关系没有。这三个缩写本身就属于多领域复用我见过不少新手在查资料时被带偏方向先点破一下你们就不会踩这个坑了。7. 一点经验之谈做嵌入式这些年我对烧录这件事最大的体会是不要把它想成“配工具”的过程而要想成“和芯片协作”的过程。芯片手册上关于Flash操作的时序图、关于启动模式的引脚配置表才是真正决定ISP/IAP方案成败的地方。很多看似玄妙的烧录问题最后翻到参考手册都能找到答案。另外说一个个人偏好产品量产时不管烧录用的是ISP还是ICP我都强烈建议在PCB板上保留SWD调试接口的焊盘即使不引出连接器。哪怕正式产品永远不会接调试器这个焊盘也是你最后的救命稻草——IAP玩砸了、ISP进不去了的时候能飞线接个SWD把芯片救回来。这可以说是踩过无数次坑之后沉淀下来的血泪经验了。如果你也想做IAP方案却还没动手不妨先拿手边的一块STM32或者GD32开发板按文中的分区和跳转代码跑一遍。别看理论好像有点绕真正把Bootloader烧进去、App跑起来、再通过串口升级一次之后你对整个过程的把握会完全不一样。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

HoloCubic_AIO必装APP推荐:12款实用工具让你的小电视秒变智能中心 2026/9/29 2:50:15

HoloCubic_AIO必装APP推荐:12款实用工具让你的小电视秒变智能中心

HoloCubic_AIO必装APP推荐:12款实用工具让你的小电视秒变智能中心 【免费下载链接】HoloCubic_AIO HoloCubic超多功能AIO固件 基于esp32-arduino的天气时钟、相册、视频播放、桌面投屏、web服务、bilibili粉丝等 项目地址: https://gitcode.com/GitHub_Trending/h…

阅读更多 →
HoloCubic_AIO常见问题解答:从小白到高手的避坑指南 2026/9/29 2:50:15

HoloCubic_AIO常见问题解答:从小白到高手的避坑指南

HoloCubic_AIO常见问题解答:从小白到高手的避坑指南 【免费下载链接】HoloCubic_AIO HoloCubic超多功能AIO固件 基于esp32-arduino的天气时钟、相册、视频播放、桌面投屏、web服务、bilibili粉丝等 项目地址: https://gitcode.com/GitHub_Trending/ho/HoloCubic_A…

阅读更多 →
MoveIt2机械臂Demo配置真相:URDF/SRDF/控制器/RVIZ四层校准 2026/9/29 2:50:15

MoveIt2机械臂Demo配置真相:URDF/SRDF/控制器/RVIZ四层校准

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Dendron 任务笔记(Task Notes)实战指南:从 frontmatter 字段到状态管理命令 2026/9/29 2:50:15

Dendron 任务笔记(Task Notes)实战指南:从 frontmatter 字段到状态管理命令

知识管理知识库 【免费下载链接】dendron The personal knowledge management (PKM) tool that grows as you do! 项目地址: https://gitcode.com/gh_mirrors/de/dendron 点击查看 免费下载 本文以 Dendron 测试工作区(test-workspace/vault&#xff09…

阅读更多 →
Jspreadsheet (Jexcel) 表格样式定制:初始化 `style` 配置与 `getStyle`/`setStyle` 编程式样式管理 2026/9/29 2:50:15

Jspreadsheet (Jexcel) 表格样式定制:初始化 `style` 配置与 `getStyle`/`setStyle` 编程式样式管理

前端UI组件 【免费下载链接】ce Jspreadsheet is a lightweight JavaScript data grid component for creating interactive data grids with advanced spreadsheet controls. 项目地址: https://gitcode.com/gh_mirrors/ce/ce 点击查看 免费下载 Jspreadsheet&…

阅读更多 →
Hermes 更新与维护:用 config.yaml 让 Agent 持续进化 2026/9/29 2:50:08

Hermes 更新与维护:用 config.yaml 让 Agent 持续进化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉