尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

S12S BDM硬件握手协议:ACK脉冲原理与嵌入式调试实战

S12S BDM硬件握手协议:ACK脉冲原理与嵌入式调试实战
📅 发布时间:2026/6/20 3:49:02

1. 项目概述:深入S12S BDM硬件握手协议

在嵌入式开发,尤其是汽车电子和工业控制领域,Freescale(现NXP)的S12系列微控制器因其高可靠性和丰富的片上调试资源而被广泛使用。作为一名长期与这类芯片打交道的工程师,我深知一个稳定、高效的调试接口对于项目进度和问题排查有多么重要。今天,我们不谈那些基础的调试概念,而是聚焦于一个常被忽略但至关重要的底层机制——S12S系列背景调试模块(Background Debug Module, BDM)的硬件握手协议。

简单来说,硬件握手协议是BDM通信的“心跳”和“确认回执”。想象一下,你通过串口给设备发送指令,如果设备不给你任何回应,你怎么知道它收到了?是网络延迟了,还是指令本身有误?在调试场景下,主机(你的电脑+调试器)向目标MCU发送诸如读取内存、单步执行等命令,目标MCU的CPU执行这些命令的速度(总线时钟)可能因为VCO频率设置而改变。如果主机只是傻等一个固定的最慢超时时间,效率会极其低下。硬件握手协议,特别是其中的ACK(确认)脉冲,就是为了解决这个“盲等”问题而生的。它让目标MCU在成功执行完一个命令后,主动“拍一下”主机,说:“嘿,活干完了,数据准备好了,你可以来取了。” 这不仅大幅提升了通信效率,更是实现可靠同步调试的基石。

本文将基于S12P家族参考手册,为你彻底拆解S12S BDM的硬件握手协议。我会从协议产生的背景和要解决的核心问题讲起,然后深入ACK脉冲的时序细节、命令执行流程,并重点剖析当中断、等待模式出现时,协议如何应对,以及至关重要的命令中止(Abort)流程。最后,我会分享在设计和实现BDM调试器硬件(POD)及底层固件时,围绕这个协议所积累的一系列实战经验和避坑指南。无论你是正在开发自己的BDM调试工具,还是希望更深入地理解手头商用调试器的工作原理,这篇文章都将提供直接的参考。

2. 硬件握手协议的核心原理与ACK脉冲详解

2.1 协议诞生的背景:为何需要握手?

在早期的BDM调试中,或者在一些简化实现里,主机发送命令后的常见策略是“固定延时等待”。主机需要预估一个“最坏情况”下的命令执行时间,这个时间必须覆盖CPU总线可能的最低运行频率。例如,如果CPU总线时钟最低可至1MHz,而某个内存写操作可能需要几十个周期,主机就必须等待数百微秒甚至更长时间,以确保命令被执行完毕。这种方法简单粗暴,但存在明显缺陷:

  1. 效率低下:在CPU以更高频率运行时,大部分时间都在无谓的等待中浪费。
  2. 可靠性存疑:如果因为某些原因(如CPU进入STOP或WAIT低功耗模式),命令永远无法完成,主机会一直等待直到超时,而这个超时时间需要设置得非常长,影响用户体验。
  3. 时序耦合过紧:主机必须精确知道目标系统的最低可能频率,这在动态调整时钟的应用中变得复杂。

硬件握手协议就是为了解耦主机与目标CPU的执行时序。它的核心思想是事件驱动:主机发送命令,然后监听一个特定的硬件信号(ACK脉冲)。只有收到这个确认信号后,才进行下一步操作(读取数据或发送新命令)。这样,无论CPU跑得多快或多慢,主机都能以最优速度响应。

2.2 ACK脉冲:协议的物理载体

在S12S BDM中,这个硬件握手信号通过唯一的双向调试引脚BKGD来实现。ACK脉冲不是一个简单的电平变化,而是一个具有严格时序定义的脉冲序列。

ACK脉冲的时序构成:根据手册描述,一个完整的ACK脉冲由两部分组成:

  1. 16个串行时钟周期的低电平脉冲:目标MCU将BKGD引脚驱动为低电平,持续整整16个BDM串行时钟周期。这个长低电平是ACK脉冲的主体,易于被主机检测。
  2. 一个短暂的高速脉冲(Speed-up Pulse):在16周期低电平之后,目标MCU会驱动一个短暂的高电平脉冲,然后立即将BKGD引脚释放回高阻态。这个高速脉冲的目的是为了确保BKGD线能够快速恢复到高电平(逻辑1),为下一次通信做好准备,因为总线上通常有上拉电阻,仅靠上拉恢复可能较慢。

这里需要理解一个关键概念:BDM串行时钟。它并非一个独立的时钟引脚,而是由目标MCU内部的VCO时钟分频而来(固定为VCO频率除以8)。主机在通信开始时,需要通过SYNC命令来测量这个时钟的频率。因此,主机知道的“周期”是时间单位,而目标MCU生成脉冲时计数的是它自己的时钟周期数。

ACK脉冲的触发时机:ACK脉冲并非对所有命令都立即响应。它只针对那些需要CPU执行的BDM硬件命令。具体来说:

  • 读命令(如READ_BYTE,READ_WORD):当BDM模块成功“窃取”一个总线周期,完成数据读取操作,并将数据准备好,可以供主机通过BKGD引脚串行读出时,发出ACK脉冲。
  • 写命令(如WRITE_BYTE,WRITE_WORD):当BDM模块通过BKGD引脚完整接收了主机发送的数据,并且成功利用一个总线周期将该数据写入目标内存/寄存器后,发出ACK脉冲。
  • 控制命令(BACKGROUND,GO,GO_UNTIL,TRACE1):当命令所请求的CPU状态切换完成时发出。例如,BACKGROUND命令在CPU从正常运行模式切换到背景调试模式时发出ACK;GO命令则在CPU退出背景模式时发出。

一个重要的时序约束:最小延迟手册特别强调,ACK脉冲不会早于命令结束后的第32个串行时钟周期发出。命令的结束点被定义为命令最后一个比特的第16个时钟节拍(即停止位)。这个至少32周期的延迟,是为了给主机留出足够的时间,从发送模式切换到接收模式,并准备好检测BKGD引脚上的这个低电平脉冲。如果没有这个延迟,主机可能还在驱动BKGD线,就会与目标MCU驱动的ACK脉冲发生电气冲突。

注意:ACK脉冲的发出没有上限延迟。因为命令的执行依赖于CPU总线,如果总线因为访问慢速外设(如外部Flash)而被占用,ACK脉冲可能会被大大延迟。这是协议设计时必须考虑的情况。

2.3 命令级交互流程剖析

为了更直观地理解,我们以最常用的READ_BYTE命令为例,拆解一次完整的带握手的交互过程:

  1. 主机发送阶段:主机首先通过BKGD引脚,按照串行协议发送8位的READ_BYTE指令操作码(Opcode)。
  2. 主机发送地址:紧接着,主机发送要读取的内存地址(通常是16位或24位,取决于MCU)。
  3. 目标解码与执行:目标MCU的BDM模块接收并解码该命令。随后,BDM会尝试“抢占”一个空闲的总线周期(或“窃取”一个周期),代表CPU去执行这个读内存操作。
  4. 目标发出ACK:当数据从总线上成功读取并暂存在BDM内部缓冲区后,BDM模块驱动BKGD引脚,产生前述的16周期低电平+高速脉冲的ACK信号,通知主机:“你要的数据我拿到了,随时可以来读。”
  5. 主机检测与响应:主机在发送完地址后,就将BKGD引脚设置为输入模式,并持续采样。一旦检测到那个长达16个主机预估周期的低电平(主机需要根据之前SYNC测量的频率来估算),就知道ACK来了。
  6. 主机读取数据:在ACK脉冲结束后,主机立即启动数据读取流程,通过BKGD引脚将BDM缓冲区里的数据(一个字节)移出来。这里有个细节:数据总是以字(16位)的形式发送,主机需要根据之前发送的地址是奇地址还是偶地址,来判断读取到的16位数据中哪个字节是有效的。

这个过程清晰地展示了“命令-确认-数据”的握手流程。对于写命令,流程类似,只是ACK在数据写入完成后发出,之后主机就可以发送下一条命令了。

3. 协议使能、禁用与异常处理机制

3.1 协议的使能与禁用:ACK_ENABLE与ACK_DISABLE

硬件握手协议并非总是开启的。S12S BDM在上电复位后,默认状态是禁用硬件握手协议的。这样做是为了向后兼容那些不支持此协议的老款调试工具(POD)。协议的状态由两个特殊的BDM命令控制:

  • ACK_ENABLE命令:此命令用于启用硬件握手协议。一旦执行,目标MCU将在每个需要CPU执行的BDM命令完成后发出ACK脉冲。有趣的是,ACK_ENABLE命令本身也会产生一个ACK脉冲作为响应。这个特性可以被主机利用来探测目标是否支持硬件握手协议:主机发送ACK_ENABLE后等待ACK,如果收到ACK,说明目标支持;如果没收到(且超时),则说明目标可能是旧款芯片或不支持,主机应回退到固定延时等待模式。
  • ACK_DISABLE命令:此命令用于禁用ACK脉冲。禁用后,主机必须回到老办法,即在协议中适当的位置使用“最坏情况延迟”进行等待。

这种设计非常灵活,允许新的、支持握手的调试器与旧芯片工作,也允许新的芯片与旧的、不支持握手的调试器工作。

3.2 异常情况处理:当ACK永不到来

理想情况下,每个命令都有ACK响应。但现实很骨感,嵌入式系统异常众多。协议必须处理ACK丢失或无限延迟的情况。最常见的原因有两个:

  1. CPU进入了STOP或WAIT模式:如果主机发送了一个硬件命令(如WRITE_BYTE),但在此命令被CPU执行之前,CPU因中断或代码执行进入了低功耗的STOP或WAIT模式,那么该命令会被目标MCU丢弃。关键点:命令被丢弃,自然不会执行,也就不会产生ACK脉冲。
  2. 主机与目标失去同步:由于噪声、时序误差或软件错误,主机发送的命令可能没有被目标正确解码。目标可能将其视为无效命令而忽略,同样不会产生ACK。

在这种情况下,主机不能无限期地等下去。协议规定,如果一条命令没有被ACK,主机必须首先中止(Abort)这条挂起的命令,然后才能发送新的BDM命令。这就引出了下一个核心机制:硬件握手中止流程。

3.3 硬件握手中止流程:SYNC命令的第二种用途

中止一个未确认命令的标准方法是使用SYNC命令。SYNC命令本用于在通信开始时,让主机测量目标的BDM串行时钟频率。但在握手协议中,它被赋予了中止挂起ACK的职责。

标准中止流程(推荐):

  1. 主机驱动BKGD引脚为低电平,持续至少128个目标串行时钟周期(按主机已知的最低频率计算)。
  2. 主机驱动BKGD为高电平一个短暂的高速脉冲。
  3. 主机释放BKGD引脚至高阻态。
  4. 目标MCU检测到这个长的低电平脉冲(即SYNC请求),会执行以下操作:
    • 丢弃任何未完成的命令或未读取的数据位(软复位)。
    • 等待BKGD回到逻辑1。
    • 延迟16个周期。
    • 驱动BKGD低电平128个周期(以其自身的BDM时钟频率)。
    • 发出一个高速脉冲后释放引脚。
  5. 主机检测到这个SYNC响应脉冲。一旦这个交互完成,主机和目标就重新同步,之前未确认的命令及其对应的ACK脉冲都被认为已中止。主机此后可以安全地发送新的命令。

关键限制与注意事项:

  • 对读写命令的不确定性:对于BDM固件的读/写命令,在SYNC命令开始到其对应的ACK脉冲发出之间,存在一个短暂的延迟(Latency)。如果SYNC在这个延迟期内发出,读/写操作可能不会被中止,但对应的ACK脉冲会被中止。这意味着数据可能已经被修改或读取,但主机收不到确认。这需要主机软件逻辑进行容错处理。
  • 对GO/TRACE1/GO_UNTIL命令:这些控制命令本身不能被中止,只能中止其对应的ACK脉冲。例如,你发送了GO命令让CPU运行,然后想中止它,SYNC只能清除“等待ACK”这个状态,并不能让运行的CPU停下来。
  • 短中止脉冲(不推荐):手册提到,理论上主机可以发送一个短于128周期(但至少4周期)的低电平脉冲来中止ACK。目标会在BKGD引脚上检测到下降沿时中止挂起的命令和ACK。但强烈不推荐在实际应用中使用此方法,因为存在风险:如果这个短中止脉冲恰好与目标发出的ACK脉冲在时间上冲突(一个驱动低,一个驱动高速高),目标可能无法检测到中止脉冲,导致主机和目标失去同步,尤其是在中止读命令时,后果是灾难性的。

4. 协议在核心调试命令中的应用与联动

硬件握手协议与各类BDM命令深度耦合,理解它们之间的联动对于编写稳定的调试器固件至关重要。

4.1 读写命令(READ/WRITE)的握手

这是最常用的场景。握手确保了数据操作的原子性和可靠性。

  • 读命令后:ACK脉冲发出,意味着数据已就绪。主机必须在ACK脉冲结束后的512个串行时钟周期内启动数据读取。一旦超时,读命令将被丢弃,数据无法再获取。注意:当握手协议启用时,命令发出到ACK脉冲之间的超时(512周期)是被禁用的,主机可以等待任意长时间。但ACK发出后,读取数据的超时机制重新激活。
  • 写命令后:ACK脉冲发出,意味着数据已成功写入目标内存。此后主机可发送下一条命令。

4.2 控制命令的握手

控制命令的ACK标志着CPU状态的切换。

  • BACKGROUND命令:ACK在CPU从正常模式切换到背景调试模式时发出。可用于确认CPU是否成功进入调试状态。
  • GO命令:ACK在CPU退出背景调试模式(即开始运行用户程序)时发出。
  • GO_UNTIL命令:这是一个特殊的GO,ACK在CPU因断点匹配或执行BGND指令而再次进入背景调试模式时发出。它用于实现“运行到断点”功能。这里有一个棘手点:如果CPU执行了STOP或WAIT指令,命令会被丢弃且无ACK。主机无法区分是“遇到了断点但还没执行到”还是“进入了低功耗模式”。因此,任何未收到ACK的情况,都应先执行中止流程。
  • TRACE1命令:ACK在CPU执行完一条用户程序指令并返回背景调试模式时发出。用于实现单步调试。

4.3 电气冲突与设计考量

协议文档特意提到了BKGD引脚上可能发生的电气冲突。唯一可能发生冲突的场景是:一方驱动低电平,而另一方同时试图驱动一个高速高电平脉冲。其他情况下的“高电平”都是通过上拉电阻实现的,是“弱上拉”,而非主动驱动。

虽然发生冲突的概率很低(例如在POD刚连接到目标板,目标恰好处于调试模式并正在执行命令时),但协议本身并未防止这种情况。这意味着调试器(POD)的硬件设计必须能够承受这种短暂的冲突。通常的作法是在BKGD线上使用一个阻值合适的上拉电阻,并确保主机和目标MCU的驱动能力有限,这样即使发生冲突,电流也在安全范围内,不会损坏器件。这是调试工具硬件设计中的一个重要细节。

5. 实战经验与避坑指南

基于多年的嵌入式调试工具开发经验,我总结了一些在实现S12S BDM硬件握手协议时容易踩坑的地方和应对策略。

5.1 时钟同步与频率测量

一切的基础是主机必须准确知道目标MCU的BDM串行时钟频率。SYNC命令是完成这一步的唯一标准方法。

操作要点:

  1. 初始通信:在发送任何其他命令前,先发SYNC命令。主机以自己预估的最低频率(根据芯片手册中VCO可能的最低频率除以8计算)发送128周期的低电平。
  2. 测量响应:主机精确测量目标返回的128周期低电平脉冲的持续时间T_target。
  3. 计算频率:目标BDM时钟周期T_cycle = T_target / 128。频率F_bdm = 1 / T_cycle。
  4. 容错:协议允许主机测量的频率有百分之几的误差。通信协议本身对时钟容差有一定容忍度。但为了稳定,测量应尽可能准确。

避坑提示:

  • 不要在目标MCU时钟尚未稳定(例如刚上电或时钟切换过程中)时进行SYNC测量,否则后续通信会全部错乱。
  • 测量时,主机的定时器精度要足够高。对于可能高达几十MHz的VCO频率,BDM时钟也有几MHz,128个周期的时间很短,需要高精度定时器或输入捕获功能。

5.2 ACK脉冲的可靠检测

检测ACK脉冲是握手协议成功的关键。主机在发送完需要ACK的命令后,应立即将BKGD引脚配置为高阻输入(或带上拉的输入),并启动边沿检测或周期性的电平采样。

实现策略:

  • 使用硬件外设:如果主控MCU有灵活的数字接口或通信外设(如UART在单线模式下、或支持双向开漏的I2C),可以尝试利用其硬件检测起始位(下降沿)或超时的功能来检测ACK的长低电平。
  • 软件轮询:更通用的方法是定时器中断配合GPIO采样。在命令发送结束后的第32个周期开始,启动一个采样循环。由于ACK脉冲至少持续16个目标周期,而主机已知目标频率,可以计算出需要采样多长时间窗口。在窗口内检测到持续的低电平,即可认为ACK有效。
  • 防误判:总线上的噪声可能产生毛刺。软件上应做滤波处理,例如连续采样多个点均为低电平才确认。

5.3 超时与中止流程的稳健实现

一个健壮的BDM驱动库必须妥善处理超时和中止。

超时管理清单:

  1. 命令到ACK的超时:如果握手协议已启用,此超时应设置得非常长(例如秒级),以应对CPU因访问慢速设备或执行长代码而导致的延迟。如果协议未启用,则使用计算出的“最坏情况延迟”。
  2. ACK后读取数据的超时:固定为512个目标串行时钟周期。主机必须在收到ACK后,按此时限启动并完成数据读取。
  3. 位传输超时:任何两个连续下降沿之间若超过512个目标周期,目标端会发生“软复位”,当前命令/数据被丢弃。主机在发送每一位时也需遵守此时限。

中止流程实现建议:

  • 统一使用标准SYNC中止:坚决避免使用“短中止脉冲”。无论何种命令未响应,都统一发起标准的128周期SYNC命令来中止。
  • 中止后的状态恢复:执行完SYNC中止流程后,主机和目标应处于一个已知的、同步的初始状态。主机软件应清除内部所有关于上一条命令的状态标记,准备发送新命令。
  • 针对控制命令的特殊处理:对于GO,TRACE1,GO_UNTIL命令,如果因目标进入STOP等模式而无ACK,使用SYNC中止后,主机需要重新读取CPU状态寄存器,以确认CPU当前实际处于何种模式(运行、调试、停止),而不能假设CPU一定回到了调试模式。

5.4 调试器(POD)硬件设计要点

硬件设计直接影响协议的稳定性。

  • BKGD引脚驱动电路:必须采用开漏(Open-Drain)或开集(Open-Collector)驱动方式,配合上拉电阻。确保主机和目标MCU都不会对总线输出“强高电平”,从而避免电气冲突。典型的做法是用一个三极管或MOS管,或者使用带开漏模式的GPIO。
  • 上拉电阻值:需要权衡。电阻值太小,驱动冲突时电流大,但上升沿快;电阻值太大,抗噪能力差,上升沿慢。根据通信速率(BDM时钟频率)和布线长度,通常在1kΩ到10kΩ之间选择。建议在PCB上预留位置,方便调试。
  • 电平兼容:确保主机(可能是3.3V MCU)与目标S12S MCU(通常是5V)之间的BKGD引脚电平兼容。可能需要使用电平转换电路或选择兼容5V输入的3.3V MCU。
  • ESD与过压保护:BKGD线通常连接到调试接口(如6芯BDM接头),暴露在外,应添加TVS管等保护器件。

5.5 常见问题排查速查表

现象可能原因排查步骤
发送SYNC后无响应1. 目标板未供电或复位。
2.BKGD引脚连接错误或断路。
3. 主机驱动能力不足或上拉电阻过大。
4. 目标MCU处于特殊模式(如安全模式禁用BDM)。
1. 检查目标板电源、复位信号。
2. 用示波器测量BKGD线波形,看主机发出的128周期低电平和高速脉冲是否正常。
3. 检查上拉电阻值,尝试减小电阻。
4. 确认芯片是否处于安全模式,尝试全片擦除。
能SYNC但后续命令无ACK1. 握手协议未启用(默认禁用)。
2. 主机计算的时钟频率误差太大,导致无法正确解析ACK。
3. 命令格式错误,目标未识别。
4. CPU处于STOP/WAIT模式。
1. 发送ACK_ENABLE命令,并检查是否收到其ACK。
2. 重新测量SYNC响应,校准频率。
3. 用逻辑分析仪捕获完整的命令波形,比对手册中的编码格式。
4. 尝试发送SYNC中止后,再发送读取CPU状态寄存器的命令。
读命令后收到ACK,但读取的数据全为0或FF1. 数据读取时序错误,错位了。
2. ACK检测点太早或太晚,主机在错误的时间点开始读数据。
3. 目标地址非法或访问了受保护区域。
1. 确认在ACK脉冲完全结束(高速脉冲之后)才开始发送读数据的起始位。
2. 精确计算ACK脉冲的结束点。用示波器验证主机开始读数据的时刻。
3. 尝试读取一个已知的固定地址(如某个寄存器)。
偶尔通信失败,出现乱码1. 噪声干扰。
2. 时序临界,时钟频率测量有轻微误差,在长时间通信后累积导致错位。
3. 电源不稳定。
1. 检查BKGD线布线,远离噪声源,缩短走线。
2. 在通信若干条命令后,重新发起一次SYNC命令来重新同步时钟。
3. 检查目标板和调试器的电源纹波。
GO_UNTIL命令后程序运行但从未返回ACK1. 预设的断点条件永远未满足。
2. 程序跑飞或进入了死循环。
3. CPU进入了STOP模式。
1. 检查断点设置是否正确(地址、类型)。
2. 使用其他调试手段(如串口打印)确认程序流程。
3. 等待一个合理超时后,发送SYNC命令中止,然后尝试读取CPU状态。

深入理解并正确实现S12S BDM的硬件握手协议,是构建可靠底层调试工具的关键。它远不止是发送和接收几个脉冲那么简单,而是涉及精确的时序控制、异常状态处理和稳健的硬件设计。希望这份结合了手册原理与实战经验的详解,能帮助你在下一次与S12系列MCU的深度对话中,更加游刃有余。

相关新闻

  • 前向车辆最小转弯约束下的两点间最短路径生成工具(MATLAB实现+图形可视化)
  • 2026年即时零售无人仓加盟推荐:无人外卖仓/外卖闪电仓/前置仓无人仓/即时零售运营加盟全解析 - 海棠依旧大
  • 2026年东莞全域保洁服务公司推荐:开荒清洁/外墙清洗/石材养护/甲醛治理/油烟管道清洁/日常驻场保洁 - 海棠依旧大

最新新闻

  • Ascend大模型预训练实战:硬件适配、数据对齐与梯度防控
  • Redis Memory Analyzer与Python集成:API使用详解
  • 2026十大离婚律师综合口碑榜单,价格透明服务优质精选 - mypinpai
  • 深入解析S12XDBG硬件调试模块:从比较器、状态机到复杂断点实战
  • 从环境变量到密码安全:Aero处理敏感配置的完整方案
  • CANN/ge获取HCCL跟随流数量

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号