1. 项目概述DPAA2架构下的SEC服务交付核心在嵌入式系统尤其是高性能网络与安全处理领域NXP的DPAA2架构提供了一套精密的硬件加速与资源管理方案。这套架构的核心目标是将数据平面的繁重处理任务如加解密、包分类、压缩从通用CPU上卸载到专用硬件加速器从而释放CPU算力实现极致的吞吐量与确定的低延迟。然而硬件加速器的高效共享与安全隔离始终是此类系统设计的核心挑战。想象一下在一个多用户、多业务共存的网络设备中如何确保一个用户的VPN加解密数据流绝不会被另一个用户的防火墙处理任务窥探或干扰DPAA2的答案就藏在帧队列Frame Queues, FQs、帧描述符Frame Descriptors, FDs以及一套严谨的多分区资源访问Multi-partition Resource Access机制之中。本文将以DPAA2中的安全引擎SEC模块为具体切入点深入拆解这套机制的工作原理。SEC作为执行加解密、哈希、认证等安全操作的硬件加速器是DPAA2架构中资源隔离要求最严苛的组件之一。我们将看到DPAA2如何通过队列管理器QMan和缓冲区管理器BMan将一次安全处理请求抽象为FD并通过FQ进行投递与回收。更重要的是我们将详细解析SEC如何利用隔离上下文标识符ICID和访问管理限定符AMQ在硬件层面为不同用户或分区Partition构建起坚固的“隔离墙”实现输入、控制、输出三类资源的安全分离与组合访问。理解这套机制不仅是驱动开发的基础更是设计安全、可靠、高性能嵌入式系统的关键。2. 核心概念拆解帧队列、帧描述符与缓冲区在深入SEC的细节之前我们必须先建立对DPAA2基础数据结构的清晰认知。这些概念是理解整个数据流和控制流的基石。2.1 帧队列工作的管道与门户帧队列是DPAA2架构中任务调度的核心抽象。你可以把它想象成一个邮筒或者一个先进先出的任务管道。应用程序或驱动不直接与SEC这样的硬件加速器对话而是将工作请求放入一个特定的帧队列。随后QMan会从队列中取出请求并递交给对应的加速器如SEC去执行。帧队列与任务环的本质区别SEC支持两种服务接口传统的任务环Job Ring和基于QMan的帧队列接口。任务环是一种更直接、但更“独占”的硬件资源。一个任务环在某一时刻只能被一个“所有者”如一个内核线程或一个进程高效使用。如果多个用户想共享一个任务环就需要上层软件如操作系统驱动进行复杂的协调、仲裁甚至需要动态地重新配置内存访问权限。这带来了显著的管理开销和性能瓶颈。而基于QMan的帧队列接口其革命性在于解耦了物理硬件资源与逻辑用户。SEC的QMan接口QI可以轻松处理来自数百万个不同帧队列的请求。每个帧队列在创建时就由可信的管理软件如Hypervisor或特权级驱动静态配置好了其关联的用户资源访问权限即ICID和AMQ。当SEC从某个队列取出一个FD时它同时也就获得了处理这个FD所需的所有权限信息。这意味着管理软件无需动态干预只需为每个用户分配一个预先配置好的队列即可实现安全的、隔离的硬件加速服务共享。这种设计极大地简化了多租户环境下的资源管理。帧队列描述符的配置创建一个帧队列并非只是分配一个ID。管理软件需要初始化一个帧队列描述符其中关键字段包括源队列ID用于队列刷新操作。响应队列ID指定处理结果或状态应返回给哪个队列。FQD_CTX包含核心的ICID、PL等访问控制参数。2.2 帧描述符工作的“任务单”如果说帧队列是管道那么帧描述符就是管道中流动的“包裹”或“任务单”。一个FD是一个标准化的数据结构它描述了一个待处理的“帧”。这个“帧”可以是一个网络数据包、一段待加密的数据块或者任何需要SEC处理的信息单元。FD的核心信息帧的起始内存地址和长度告诉SEC数据在哪里有多大。帧格式指明数据在内存中的组织形式主要有两种单帧数据连续存储在一个缓冲区中。帧列表数据分散在多个缓冲区中通过一个类似散列表的结构来管理。SEC主要支持一种特殊的双入口输入/输出帧列表格式。流上下文指针这是FD的灵魂所在。它指向一个流上下文数据结构该结构定义了如何处理这个帧以及处理后的结果如何返回。FD与SEC描述符的区分这里有一个至关重要的概念区分。FD是DPAA2层面的通用数据结构用于在QMan、BMan和各种加速器包括SEC之间传递任务。而SEC作业描述符或共享描述符是SEC模块内部使用的指令集具体定义了执行何种加密算法如AES-CBC、哈希算法如SHA-256等操作。SEC的QI或AI接口负责将接收到的FD结合其指向的FLC转换成SEC内部可执行的作业描述符。FD是“信封”里面的“信纸”才是SEC要执行的具体操作指令。2.3 缓冲区与缓冲区管理器数据本身存放在内存缓冲区中。BMan负责管理一个或多个缓冲区池。当SEC需要为输出数据分配新的缓冲区时例如解密后的数据比加密后的数据长它会通过QI向BMan申请。BMan根据帧队列配置中指定的缓冲区池ID从正确的池中分配缓冲区。同样处理完成后不再需要的输入缓冲区会被释放回池中。这种集中式的缓冲区管理提高了内存使用效率并确保了缓冲区在正确的安全域内被分配和释放。3. 多分区资源访问机制深度解析这是DPAA2架构中资源隔离设计的精髓也是SEC安全性的核心保障。其目的是允许一个硬件加速器SEC安全地访问来自多个不同用户分区的资源。3.1 隔离的基石ICID与AMQ在支持DPAA2的SoC中隔离上下文标识符是实施用户分区的硬件令牌。每个用户分区可以是一个虚拟机、一个容器或一个应用进程都会被分配一个唯一的ICID。所有对该分区资源的访问请求内存访问、队列访问、缓冲区池访问都必须携带这个ICID。系统内存管理单元会检查该ICID是否有权访问目标地址从而在硬件层面强制隔离。访问管理限定符是一组与ICID关联的属性用于进一步细化访问权限。例如特权等级用于区分用户态和内核态访问绕过内存转换位指示是否使用物理地址直接访问。ICID和AMQ共同构成了一个不可伪造的访问身份和权限集。关键点在于ICID和大部分AMQ由系统内可信的管理实体如Hypervisor、安全监控器分配和管理。普通用户分区甚至可能不知道自己的ICID是什么更无法修改它。用户只能有限地修改一部分被许可的AMQ。这种强制访问控制模型确保了隔离的不可绕过性。3.2 资源访问模式SEC通过QMan出队响应中携带的访问管理限定符使用控制字段来动态决定如何处理一次服务请求中涉及的三种不同类型的事务输入事务读取输入数据FD指向的帧数据。控制事务读取控制信息FLC和紧随其后的共享描述符SD。输出事写入输出数据处理结果。AUC字段定义了四种资源访问模式决定了输入、控制、输出事务分别使用哪套ICID/AMQ。3.2.1 单分区资源访问模式这是最简单、最常用的模式。在此模式下AUC0。输入、控制、输出事务全部使用同一套ICID和AMQ。这意味着请求服务的用户分区自己提供了输入数据、控制描述符并接收输出数据。SEC就像一个完全受用户控制的“服务器”用户拥有全部自主权但也被严格限制在自己的资源边界内无法触及其他分区的任何资源。这种模式适用于独立的、自包含的安全处理任务。3.2.2 输入控制的双分区资源访问模式在此模式下AUC1。输入和控制事务使用同一套ICID/AMQ来自FQD_CTX.ICID/.PL而输出事务则使用另一套来自FQD_CTX.ICID_2/.PL_2。这建立了一种“主从”关系。输入/控制分区主决定SEC做什么执行什么算法并将结果写入输出分区从的内存。这种模式适用于可信服务提供者场景。例如一个可信的安全服务分区主为多个不可信的用户分区从提供加解密服务。用户分区提供待处理的数据输入并指定输出位置但加解密的密钥和算法由可信的安全服务分区通过控制描述符提供用户分区无法窥探或修改。3.2.3 输出控制的双分区资源访问模式此模式与上一种对称AUC2。输入事务使用一套ICID/AMQ而控制和输出事务使用另一套ICID_2/PL_2。此时控制/输出分区主决定SEC做什么并从输入分区从的内存读取数据。这种模式适用于数据采集或监控场景。例如一个日志审计分区主有权从各个被监控的用户分区从的内存中读取数据并进行安全哈希以生成完整性报告。被监控的分区提供数据但无法控制审计的算法和结果存放位置。3.2.4 三分区资源访问模式这是隔离性最强的模式AUC3。输入、控制、输出事务分别使用三套独立的ICID/AMQICID, ICID_2, ICID_3。在这种模式下输入分区和输出分区完全隔离。控制分区作为一个可信的第三方提供处理逻辑SD。输入分区提供源数据输出分区接收结果但两者互不知晓对方也无法访问对方的数据。控制分区作为中介确保处理按既定规则进行。这种模式完美实现了“红黑分离”常用于需要最高级别数据隔离的场景例如在不同安全域之间进行格式转换或协议适配。3.3 安全限制与执行保障多分区访问能力是一把双刃剑用不好就会成为打破隔离的漏洞。因此SEC在硬件层面实施了一系列严格的限制确保上述模式不会被滥用。3.3.1 流上下文选择限制FLC中有一个隔离上下文限制字段。当AUC2或3即控制与输入可能不同时ICR字段可以强制施加匹配规则ICR0严格匹配。服务请求中使用的输入和输出ICID必须与FLC中预编程的IICID和OICID字段完全一致。这确保了该FLC只能被特定的输入-输出分区对使用。ICR1要求输入和输出ICID相同。即使队列配置允许它们不同使用此FLC时也必须相同。这适用于那些设计上就不支持跨分区输出的描述符。ICR3无限制仅限可信实体。只有被明确信任的控制分区例如AIOP才能使用这种FLC因为它可以跨任意分区组合工作。如果一次服务请求选择的FLC不符合其ICR规则SEC将直接产生一个隔离违规错误拒绝执行。这防止了恶意用户通过尝试不同的队列和FLC组合来“撞库”式地访问非授权资源。3.3.2 内联作业描述符与替换作业描述符的限制内联作业描述符和替换作业描述符是两种允许在FD中直接携带SEC指令的机制提供了极高的灵活性。然而在跨分区场景下如果允许输入分区可能不可信随意指定指令同时又能通过队列配置访问其他分区的资源那隔离将形同虚设。因此SEC硬性规定只有当AUC0或1即输入和控制分区相同时才允许使用IJD和RJD。因为此时能提供指令的输入分区和能通过控制事务访问SD的分区是同一个它无法利用此机制越权访问其他分区的资源。3.3.3 控制替换作业描述符为了在跨分区场景下仍能提供一定的灵活性SEC引入了控制替换作业描述符。CRJD不是放在FD输入分区中而是放在控制分区内存中紧跟在共享描述符SD之后。只有FLC中的CRJD位被设置时SEC才会去执行这段CRJD。这样一来CRJD的内容完全由可信的控制分区决定和提供。用户输入分区只能通过FD中的一个标志位选择“执行”或“不执行”这段预设的CRJD但完全无法改变其内容。这既保证了安全又允许控制分区实现一些每帧可变的微调操作例如基于每帧的IV更新。3.3.4 非本地跳转限制SEC描述符支持跳转指令。但非本地跳转指令虽然可以指定一个目标描述符地址却不能改变获取该描述符时所使用的ICID/AMQ。这意味着跳转后的描述符仍然必须位于当前控制事务所能访问的内存区域内。因此跳转指令无法被用来“跳”出当前控制分区的资源边界无法成为绕过隔离的工具。4. 流上下文SEC作业的执行蓝图帧描述符中的FLC字段是一个指针指向一个64字节的流上下文数据结构。这个结构是连接FD与具体SEC操作的核心桥梁包含了处理一个“流”一系列类似作业所需的所有元数据和配置。4.1 FLC的核心字段组解析FLC结构中的字段可以划分为几个功能组理解这些分组对于正确配置至关重要。4.1.1 作业调度与处理选项组这个组定义了作业如何被SEC核心执行。共享描述符长度指示紧随FLC之后的SD的长度以8字节为单位。它同时定义了CRJD的入口点SDL*8 FLC地址 64。关键资源ID用于标识一个可能被所有DECO描述符控制器争用的关键CHA加密硬件加速器资源。设置此ID可以帮助QMan进行更公平的作业调度避免多个DECO因等待同一稀缺资源而阻塞。控制替换作业描述符位指示SD之后是否存在CRJD。启用写安全位当复用输入缓冲区作为输出时此位确保SEC的写入操作是“写安全”的即不会覆盖尚未被读取的输入数据这对于“原地”加解密操作至关重要。禁用直通注解复制位决定是否将输入FD中的直通注解复制到输出FD。通常应保持清除以符合DPAA2规范但在需要严格隔离输入输出注解的场景下可以设置。启用应用特定注解输出位控制是否将SEC生成的应用特定注解写入输出帧。4.1.2 响应流上下文与属性组此组配置如何将处理结果或错误返回给请求方。响应FLC指定在返回给请求方的响应FD中FLC字段应填充的值。响应BMT指定响应FD中CBMT位的值。响应存储控制指定响应FD中SC位的值用于控制缓存预取行为。4.1.3 输出队列与流上下文组此组仅在多分区模式AUC2或3下使用配置如何将输出数据发送到输出分区。输出帧队列ID指定输出FD应入队到哪个队列属于输出分区。输出FLC指定在发往输出分区的输出FD中FLC字段应填充的值。输出BMT/SC对应输出FD的CBMT和SC位。4.1.4 用户认证与安全域ID组此组用于在多分区场景下加强访问控制。安全域ID在某些需要SDID的特定服务中使用当AUC3时可使用FLC中的SDID覆盖队列配置中的值。隔离上下文限制如前所述用于实施FLC级别的ICID匹配规则。输入/输出隔离ID当ICR0时用于与队列配置中的ICID进行匹配校验。4.1.5 存储配置文件组这是FLC中最复杂的部分之一它指导SEC实际上是QI/AI如何管理输出数据的缓冲区。缓冲区源决定输出缓冲区是重新分配还是复用输入缓冲区。帧格式指定输出帧是单缓冲区格式还是散列表格式。数据长度控制/数据长度用于估算输出缓冲区所需的大小。可以是基于输入长度的修正值也可以是一个固定值。直通注解空间/应用特定注解空间/数据头空间/散列头空间这些字段共同计算在输出缓冲区中为各种注解和数据预留的空间偏移量。缓冲区池记录指定最多两个缓冲区池的ID、缓冲区大小等信息用于分配新的输出缓冲区。4.2 存储配置文件的实战应用理解SP如何工作是高效使用SEC的关键。让我们看两个典型场景场景一AES-CBC解密输出比输入略短假设输入是一个加密的TCP载荷解密后需要去掉填充。BS0分配新缓冲区。FF0允许SEC根据数据量选择最合适的帧格式单缓冲或SG。DLC0, DL-16设置长度控制为“修正模式”并指定长度修正值为-16字节假设填充为16字节。SEC会计算输出长度 输入长度 (-16)。PTAR/ASAR/DHR根据是否需要保留直通注解、添加SEC注解、预留数据头空间来设置。BPV11, BPID10x100, PBS1...指定从ID为0x100的缓冲区池分配缓冲区并告知池中缓冲区的大小。场景二HMAC-SHA256生成原地更新需要对一段数据生成认证标签并追加到原数据尾部。BS1复用输入缓冲区作为输出。注意此模式下DL字段无效。FF2强制使用单缓冲区格式并要求SEC检查输入缓冲区是否有足够空间容纳输出原数据HMAC标签。DHR32设置数据头空间修正为32字节。这告诉SEC“输出数据将在输入数据的起始地址向后偏移32字节处开始存放”。因为我们要追加所以输出数据的起始地址和输入相同但需要为尾部新增的32字节HMAC标签预留空间。实际上对于追加场景DHR应为0而需要的是尾部空间。更常见的做法是使用数据长度控制来估算更大的输出或者确保输入缓冲区本身就有足够的空闲尾部空间。此例旨在说明DHR作为“修正值”的概念。在复用模式下DHR是作为对现有偏移的调整值可正可负来使用的。EWS1必须启用写安全。因为SEC在向缓冲区尾部写入HMAC标签时不能覆盖前方尚未读取的原始输入数据。写安全机制能保证这一点。关键心得SP的配置需要仔细计算数据长度和偏移。一个常见的错误是低估了输出长度导致缓冲区分配失败或数据截断。对于复用缓冲区的场景务必启用EWS并清楚理解DHR是作为偏移调整而非绝对预留空间。5. 完整数据流与SEC内部处理剖析现在让我们串联起所有组件跟踪一个FD从提交到结果返回的完整生命周期并窥探SEC内部的处理逻辑。5.1 一个FD的旅程从用户到SEC再返回假设一个运行在用户分区AICID0x100的应用程序需要加密一段数据并将结果发送到输出分区BICID0x200。一个可信的服务分区CICID0x300提供加密密钥和算法。队列配置管理软件预先创建并配置好一个帧队列Q1。设置其AUC3三分区模式ICID0x100输入ICID_20x300控制ICID_30x200输出。同时配置好对应的响应队列。FD准备应用程序准备一个FD。FD中包含了指向待加密数据缓冲区的指针以及一个FLC指针。这个FLC指针指向由服务分区C预先放置在内存中的FLC结构。该FLC的ICR字段可能设置为0且IICID0x100, OICID0x200以锁定该FLC只能用于从分区A到分区B的流。FLC中的OFQID字段指向属于分区B的一个输出队列Q2。入队应用程序通过QMan软件门户将FD入队到Q1。出队与权限获取SEC的QI模块向QMan请求从Q1出队工作。QMan返回FD同时返回出队摘要信息其中包含了AUC3以及ICID0x100, ICID_20x300, ICID_30x200的信息。权限验证与FLC获取QI收到出队响应后使用控制ICIDICID_20x300和相应的AMQ去访问FD中FLC指针所指向的内存读取FLC结构。SEC硬件检查FLC中的ICR规则。本例中ICR0它验证出队摘要中的输入ICID(0x100)是否等于FLC.IICID(0x100)输出ICID(0x200)是否等于FLC.OICID(0x200)。验证通过。QI根据FLC中的SDL继续使用控制ICID(0x300)读取紧随FLC之后的共享描述符。描述符转换与作业提交QI将FD、FLC、SD提供的信息整合、转换成SEC内部作业队列控制器理解的作业描述符。这个描述符包含了使用输入ICID(0x100)读取哪里FD中的数据地址的数据执行什么操作SD中的指令以及使用输出ICID(0x200)将结果写入哪里根据SP配置分配或复用缓冲区。SEC核心处理作业描述符被送入SEC内部的作业队列由可用的描述符控制器获取并执行。DECO指挥CHA加密硬件加速器完成实际的加密运算。读取输入数据使用输入ICID写入输出数据使用输出ICID。结果返回响应FD处理完成后SEC通过QI生成一个响应FD其中包含状态信息成功/错误码。这个响应FD使用响应ICID在此AUC3模式下响应ICID就是输入ICID0x100和响应队列ID被入队到最初FD中指定的响应队列最终被分区A的应用程序取回。输出FD同时加密后的数据被放入一个新的或复用的缓冲区并封装进一个输出FD。这个输出FD的FLC字段由FLC.OFLC配置CBMT由FLC.OBMT配置。该输出FD使用输出ICID(0x200)和FLC.OFQID被入队到属于分区B的队列Q2。分区B的应用程序可以从Q2中取出处理好的加密数据。5.2 SEC内部接口分工SEC内部模块的清晰分工是实现高效、安全处理的关键QMan接口负责与QMan通信处理FD的出队、入队解析出队摘要中的多分区权限信息并将FD转换为初步的作业描述符。它是面向DPAA2通用框架的“适配层”。AIOP接口功能与QI类似但服务于AIOP另一个加速器综合体发起的请求。AIOP可以将自己的任务与SEC加速结合。作业队列与描述符控制器这是SEC的“核心执行引擎”。它从QI或AI接收转换后的作业描述符专注于调度和执行具体的加密、哈希等操作而无需关心FD、队列、多分区等上层抽象。这种架构使得SEC核心逻辑保持简洁和高性能。6. 开发实战配置与排错指南理解了原理最终要落地到驱动或应用开发中。以下是一些关键的配置步骤和常见的“坑”。6.1 多分区访问配置清单要为SEC配置一个支持多分区访问的帧队列你需要协同管理软件如Hypervisor或特权驱动和应用层完成以下步骤规划分区与ICID为输入、控制、输出分区分配唯一的ICID。确保系统MMU已为这些ICID配置好对应的内存访问权限表。创建与配置缓冲区池通过BMan为需要分配缓冲区的分区创建缓冲区池并记录其BPID。创建帧队列通过QMan配置帧队列描述符。这是最关键的一步设置正确的AUC码0,1,2,3以选择访问模式。填入对应的ICID,ICID_2,ICID_3字段。设置PL等AMQ属性。配置源队列ID和响应队列ID。准备流上下文与共享描述符在控制分区的内存中确保该内存地址可被控制ICID访问创建FLC和SD数据结构。根据访问模式设置FLC.ICR,IICID,OICID。仔细配置SP组字段特别是BS、FF、DL/DLC、缓冲区池ID等。一个错误的DL计算会导致缓冲区分配失败。在SD中编写正确的SEC操作序列如AES-CBC加密指令。如果使用CRJD设置FLC.CRJD位并将CRJD指令紧跟在SD之后。应用程序端获取分配给自己的帧队列ID。准备FD设置数据指针、长度并将FLC指针指向步骤4中创建的结构。通过QMan软件门户将FD入队。从指定的响应队列中取出响应FD检查状态。6.2 常见问题与调试技巧即使理解了所有概念实际开发中依然会遇到各种问题。以下是一些常见陷阱和排查思路问题1SEC返回“隔离违规”错误。排查检查帧队列的AUC配置与你的预期访问模式是否一致。检查FLC中的ICR、IICID、OICID字段。如果ICR0确保它们与队列出队响应中的ICID完全匹配。确认你使用的帧队列是否确实配置了你在FLC中预期的ICID。可能队列配置错误。检查FLC和SD所在的内存是否确实可以被队列配置中的“控制ICID”所访问。使用错误的指针或内存权限问题都会导致访问失败可能被报告为隔离违规。问题2作业执行成功但输出缓冲区为空或数据错误。排查首要检查SP配置这是最常见的问题根源。确认BS模式分配vs复用。如果是分配模式检查BPID是否正确对应的缓冲区池是否有可用缓冲区。检查DL和DLC。如果DLC1固定长度DL是否设为了0这会导致SEC请求分配长度为0的缓冲区。如果DLC0修正模式DL的修正值计算是否正确例如解密后去掉填充DL应为负值。检查PTAR、ASAR、DHR等偏移字段。这些值会共同影响输出数据在缓冲区中的起始位置。一个过大的偏移可能导致数据被“推”到了缓冲区之外或者看起来像是空的。使用调试工具直接查看输出缓冲区的原始内存内容对比FD中的偏移量字段。在复用缓冲区模式下务必设置EWS1。否则可能会发生输出数据覆盖未读输入数据的情况。问题3性能不达预期尤其在高并发下。排查检查FLC中的CRID字段。如果作业使用了某种稀缺的CHA资源例如只有一个硬件模块支持某种特定算法而未设置CRID可能导致多个DECO争用该资源引发串行化降低吞吐量。查阅芯片手册确认所用算法涉及的CHA类型及其实例数量合理设置CRID。检查缓冲区池的缓冲区大小。如果PBS设置过小导致单个帧需要多个缓冲区会增加管理开销。如果设置过大会造成内存浪费。需要根据典型数据包大小进行优化。考虑使用帧列表格式处理散列数据避免不必要的内存拷贝。问题4如何调试复杂的多分区流分层调试法先单分区调通将所有ICID设置为同一分区使用AUC0模式。确保基本的加解密功能、FD入队出队、数据输入输出全部正常。逐步引入多分区先配置AUC1模式让控制分区和输入分区相同输出分区不同。验证输出数据能否正确写入另一个分区的队列。最后测试全三分区配置AUC3分别验证输入、控制、输出的权限隔离是否生效。可以故意配置错误的ICID匹配确认SEC是否会报错。善用仿真器和调试寄存器NXP通常提供周期精确的仿真模型和丰富的调试寄存器。可以在仿真中单步跟踪FD的处理流程查看QI解析出的权限信息、SEC核心的执行状态等这是理解复杂交互最有效的手段。最后的建议DPAA2 SEC的配置尤其是多分区部分本质上是一个“声明式”的编程。开发者通过配置数据结构FQD, FLC, SD来声明“谁在什么权限下对什么数据做什么操作结果放到哪里”。务必在编码前用纸笔或图表清晰地画出数据流、控制流以及每个环节使用的ICID。这张图将是你开发和调试过程中最可靠的路线图。