支持矩阵:诊断开发与刷写实战深度解析)
干诊断开发这几年我最怕的不是ECU收到请求后回一个否定响应而是回了一个语义不对的NRC或者明明该回NRC的时候它沉默不语。UDS里的否定响应码NRC看着就是0x7F后面跟一个字节真要把它做对牵扯到服务设计、状态机处理、会话管理、安全等级、时序约束一大堆东西。OEM的规范里往往只写“支持标准NRC”但“标准NRC”到底怎么映射到每个服务很少有文档讲透。这篇文章就把我平时梳理的UDS服务NRC支持矩阵拿出来结合刷写、故障诊断这些实际场景说说每个服务该支持哪些否定响应码以及为什么是这些。先说清楚一个前提NRC不是随便选的它本质上是ECU对请求条件进行检查后按优先级返回的“拒绝原因”。一个健壮的诊断实现应当能对同一条请求按条件命中唯一的NRC而不是碰运气。下面先讲清楚基础帧格式和NRC分类再按服务逐个拆解最后用刷写流程串一遍实战。如果你是刚接触UDS的测试工程师、底层软件开发或者诊断功能开发这篇文章可以直接当参考手册用。1. 否定响应码基础0x7F帧结构与会话逻辑1.1 0x7F响应帧的构成UDS协议里ECU对诊断请求的响应分两种正响应和负响应。正响应的首字节是SID0x40负响应的首字节固定是0x7F后面跟两个字节一个是请求的SID另一个就是NRC。比如请求0x22 01 02 03如果数据标识符不支持ECU返回的就是0x7F 22 31其中0x31就是requestOutOfRange。很多初学者会把0x7F和“请求的SID0x40”搞混这里强调一下正响应的SID是原请求SID加上0x40负响应的SID原样返回且前面固定是0x7F。也就是说负响应里能看到“是哪个服务拒绝了”而NRC则是“为什么拒绝”。所以诊断仪拿到0x7F 31 36这种帧第一反应就是0x31服务例程控制拒绝了原因是0x36超过尝试次数——这个在安全解锁类例程里很典型。NRC的取值范围在ISO 14229-1里有定义从0x00到0x7F。0x00不用表示正响应。0x10到0x37这段是通用NRC0x70到0x7F这段是特定于数据传输、编程和响应挂起场景的NRC。还有一部分OEM会定义供应商特定的NRC区间但主机厂为了兼容性通常要求ECU优先使用标准NRC。1.2 NRC的三类常见用途我习惯把NRC按用途分成三类这样梳理服务支持矩阵时思路会清楚很多。第一类是“请求本身就不合法”。比如服务不存在0x11、子功能不支持0x12、报文长度不对0x13、请求参数越界0x31、数据标识符或DTC不支持0x31。这类NRC的触发条件跟ECU当前状态无关只要请求报文有错直接拒绝。第二类是“受当前状态限制”。比如当前不在正确的诊断会话下那么可能返回0x7FserviceNotSupportedInActiveSession或0x7EsubFunctionNotSupportedInActiveSession安全访问没解锁就执行需要解锁的操作返回0x33条件不满足返回0x22时序不对返回0x24ECU忙返回0x21。这类NRC的判定顺序非常关键后面在优先级部分细说。第三类是“执行过程中出错”。典型的就是刷写相关的0x70到0x73还有0x26failurePreventsExecutionOfRequestedAction。这类NRC不仅表示“拒绝请求”还表示“操作已经尝试但失败了”。理解这三类你就能明白为什么每个服务支持的NRC是不一样的——因为每个服务的请求格式、前置条件都不一样。2. 核心服务与NRC支持矩阵2.1 会话控制、复位与保持活跃服务0x10、0x11、0x3E这三个服务属于最基础的通用服务几乎所有ECU都会支持但它们的NRC支持策略差异挺大。0x10服务DiagnosticSessionControl最常见的问题是子功能不支持。Default Session0x01、Programming Session0x02、Extended Diagnostic Session0x03这三个是标准里要求必须有的如果收到不支持的会话类型返回0x12。另外如果你在请求里设置了suppressPosRspMsgIndicationBitbit 7为1ECU如果支持抑制正响应那么成功时可以不回正响应但失败时依然要回负响应。这个细节很容易被测试用例漏掉。还有一个0x22conditionsNotCorrect很多团队不知道0x10也会用这个NRC。典型场景是整车处于行驶状态禁止切换到编程会话或者当前车速不为0禁止进入扩展会话。这种“请求本身合法但当前条件不允许”的情况就要用0x22而不是0x12或0x31。0x11服务ECUReset要注意的是复位类型。0x01硬复位、0x03软复位、0x04快速下电上电这些都是标准子功能。如果请求了一个不支持的复位类型返回0x12。还有一点某些ECU在复位前会做条件检查比如需要安全解锁或者只能在特定会话下复位否则返回0x33或0x22。0x3E服务TesterPresent在实现上最简单但也很容易犯一个错误只支持0x00子功能却对其他的子功能不返回0x12。比如有些诊断仪会发0x3E 0x80抑制正响应如果ECU没实现这个bit的处理就应该回0x12而不是继续按0x00处理。服务常见NRC触发场景0x100x12、0x22、0x13子功能不支持、条件不满足、报文长度错误0x110x12、0x33、0x22、0x13复位类型不支持、未解锁、条件不满足0x3E0x12、0x13子功能不支持、报文长度错误2.2 数据读取与写入服务0x22、0x2E、0x23、0x2F0x22ReadDataByIdentifier和0x2EWriteDataByIdentifier是“DID存取”类服务也是NRC出错最集中的地方。先说0x22。它的报文格式是SIDDID...一个请求可以带多个DID。如果所有的DID都支持就返回正响应把每个DID的值带出来。只要有一个DID不支持就要返回0x31。这里有个主机厂规范里的常见分歧是“只要有一个DID不支持就整体拒绝”还是“跳过不支持的DID返回剩余DID的值”ISO 14229标准倾向于前者但国内很多OEM的规范允许“部分成功”这个必须看SWSSoftware Specification定义。如果规范没写清楚建议实现成“整体拒绝”因为诊断仪那边处理起来更简单。0x22还会出现0x13报文长度不对和0x31DID越界。如果请求里DID字节数不是偶数DID固定两个字节就是0x13。如果DID编码合法但ECU没这个DID就是0x31。注意0x22在扩展会话和默认会话下支持的范围可能不一样如果某个DID只在扩展会话下可读默认会话下请求它应该返回0x7FserviceNotSupportedInActiveSession而不是0x31。这一点很多实现会搞混因为DID在“代码层面”是存在的只是当前会话不让读NRC要区分“不存在”和“不可用”。0x2EWriteDataByIdentifier比0x22多了一堆前置检查。首先是会话很多DID只在扩展会话下才能写否则返回0x31或0x7F0x31更常见表示这个写操作在当前不可用。其次是安全等级写入类操作基本都要解锁否则返回0x33。再次是数据校验比如写入的值超出DID允许范围返回0x31写入的值格式不对、长度不对返回0x13。如果写入的值在业务逻辑层面被拒绝也可以返回0x22conditionsNotCorrect。我见过不少ECU把“范围错误”和“条件不满足”混用测试用例会按规范里的DID表逐条校验建议开发时就把DID的读写权限、范围、会话、安全等级整理成一张配置表运行时直接查表返回对应的NRC。0x23ReadMemoryByAddress和0x2FInputOutputControlByIdentifier属于“高级数据操作”服务用的场景少但NRC要求更高。0x23的地址和长度需要对齐到ECU的内存访问粒度不对齐返回0x13或0x31地址越界返回0x31。0x2F的关键NRC除了0x31、0x33、0x22之外还有0x13——IO控制里的controlOption控制模式字段必须合法比如0x00控制关、0x01控制开如果请求了不支持的controlOption返回0x13。还有不少实现要求0x2F必须在扩展会话下使用并且参数值不能与当前物理值冲突这种冲突往往用0x22更合适。服务常见NRC触发场景0x220x31、0x13、0x7FDID不存在、长度错误、会话不支持0x2E0x33、0x31、0x22、0x13未解锁、范围错误、条件不满足、格式错误0x230x31、0x13地址越界、地址或长度不对齐0x2F0x13、0x31、0x33、0x22controlOption错误、参数越界、未解锁、条件冲突2.3 安全访问与通信控制服务0x27、0x28、0x850x27SecurityAccess是整车厂最容易自定义NRC细节的服务因为这里涉及种子seed、密钥key、尝试次数、时间延迟等一堆状态。0x27服务有两个子功能请求种子奇数子功能和发送密钥偶数子功能。常见的NRC映射如下请求种子时如果安全等级不支持返回0x12。请求种子时如果ECU正处于时间延迟状态比如上次失败后需要等10秒返回0x37requiredTimeDelayNotExpired。发送密钥时如果当前没有请求过种子、或者种子已过期返回0x22或0x24requestSequenceError。标准推荐用0x24因为请求种子的时序是0x27服务内部状态机的一部分。但很多OEM规范里也允许0x22这个看SWS。发送密钥时如果密钥错误返回0x35invalidKey。如果错误次数超过限制返回0x36exceedNumberOfAttempts。如果要执行的安全等级未解锁但请求访问的是另一个等级通常不会立刻拒绝而是要求先对该等级请求种子。这里要注意0x36和0x37的关系0x36是“你连错太多次了解锁功能被锁死只能通过断电重启或等更长时间恢复”0x37是“你得再等一段时间才能重新发”。有些ECU在0x36之后紧接着用0x37报告需要等待的剩余时间这种组合在测试时非常容易踩坑。0x28CommunicationControl这个服务也很典型。它控制通信子网Application、Diagnostic、NM等的开启和关闭。如果请求了不支持的通信类型比如0x02关闭NM消息返回0x12或0x31。如果ECU当前状态不允许关闭通信比如安全相关的通信被强制开启返回0x22。0x28还有一个容易被忽略的NRC是0x24——有些OEM禁止在刷写过程中使用0x28切换通信模式如果时序不对就返回0x24。0x85ControlDTCSetting和0x28一样是“控制类”服务。它的子功能0x02关闭DTC记录和0x01开启DTC记录必须区分清楚。如果请求关闭时ECU已经处于关闭状态有些规范允许返回0x22有些规范要求直接回正响应幂等处理。这个细节在ISO标准里没有明确要求但在OEM测试用例里经常作为“特殊检查点”。0x85最常用的NRC是0x12子功能不支持、0x33未解锁、0x22条件不满足以及0x7F会话不支持。注意0x85的关闭DTC记录功能通常要求在扩展会话下使用默认会话下请求会返回0x7F。2.4 故障诊断服务0x19、0x140x19ReadDTCInformation绝对是UDS服务里最复杂的之一因为它有十几个子功能而且每个子功能对NRC的要求都不一样。先说最常用的几个子功能0x01报告DTC数量、0x02报告DTC状态、0x04报告DTC快照记录、0x0A报告DTC支持的DTC状态掩码。这些子功能如果收到不支持的DTC状态掩码比如请求了0x19 0x02 0xFF 0x01状态掩码0x01而ECU只支持0x09、0x0A、0x1A等掩码就要返回0x31。注意这里的0x31表示“DTC状态掩码不支持”或“DTC组不支持”具体要看是哪个参数出了问题。测试时诊断仪经常会通过改变掩码来探测ECU的能力所以0x19服务里0x31的使用率极高。0x19还有个特殊情况是0x12和0x7F的选择。如果一个子功能本身是标准里定义的但ECU没有实现比如0x19 0x19那么返回0x12subFunctionNotSupported还是0x7FserviceNotSupportedInActiveSession我倾向于0x12因为0x19服务整体是支持的只是这个子功能在当前不支持。但如果ECU完全不支持0x19那就是0x11serviceNotSupported而不是0x12。0x14ClearDiagnosticInformation服务比较简单但它有一个重要的时序问题清除DTC需要在特定的条件下进行否则ECU会拒绝。条件不满足返回0x22比如车辆正在行驶DTC组不支持返回0x31报文长度错误返回0x13。0x14服务通常还和安全等级、会话绑定未解锁返回0x33。注意0x14服务的DTC参数是三个字节的DTC组可以填0xFFFFFF表示清除所有DTC。如果填了不支持的DTC组比如0x000000ISO标准里要求返回0x31。2.5 例程控制与数据传输服务0x31、0x34、0x36、0x37刷写和例程控制是NRC使用的重灾区因为这里的状态机最复杂。0x31RoutineControl有三个子功能0x01启动例程、0x02停止例程、0x03请求例程结果。它最常见的NRC是0x12子功能不支持和0x31例程ID不支持。一个很容易踩的坑是例程ID存在但当前状态不允许启动这个例程。比如某些ECU的“擦除Flash例程”只能在编程会话下启动如果在扩展会话下请求应该返回0x22或0x7F而不是0x31。例程执行失败比如擦除Flash失败应该返回0x31参数越界还是0x22条件不满足规范没有统一规定但很多OEM规范把“例程执行结果”放在正响应里如果执行失败就返回0x31并用例程结果字段说明失败原因。这种设计下0x31表示“例程执行返回失败”而不是“参数越界”。这一语义差异必须读清楚OEM规范再实现。0x34RequestDownload是刷写流程的入口。它最常见的NRC是0x31内存地址或大小越界、0x13格式错误、0x22条件不满足、0x24请求序列错误、0x70uploadDownloadNotAccepted。0x70这个NRC很特殊它不是表示“参数错误”而是表示“刷写请求被拒收”——比如Flash驱动未就绪、下载功能未使能。如果ECU的刷写程序还没进入编程会话收到0x34直接返回0x7F或0x33更合理而不是0x70。0x36TransferData在刷写时依赖块序列计数器blockSequenceCounter。如果计数器不连续比如上一帧是1这一帧是3返回0x73wrongBlockSequenceCounter。如果内存写入失败返回0x71transferDataSuspended。如果ECU当前不在“传输数据状态”收到0x36返回0x24requestSequenceError更合适。还有0x13如果数据长度与0x34请求下载时约定的大小不匹配比如实际数据长度大于申请的长度返回0x13。0x37RequestTransferExit收尾服务。如果ECU的Flash编程还没有完成或者校验失败返回0x72generalProgrammingFailure。如果0x37请求时ECU内部的数据写入还没结束可以先回0x78requestCorrectlyReceived-ResponsePending保持连接完成后再回正响应。3. NRC返回优先级规则从模糊到精准3.1 NRC检查的顺序很多ECU同时存在多个“拒绝原因”最终返回哪个NRC取决于检查顺序。ISO 14229没有强行规定完整的NRC优先级但行业里有一套默认的检查顺序我强烈建议按这个顺序实现报文格式检查长度、字节数、格式。不合法就返回0x13。这一步最先做因为后续解析参数都依赖格式。服务是否支持不支持返回0x11。这一步通常在协议栈的dispatch层完成。会话是否支持服务不支持当前会话返回0x7F子功能不支持当前会话返回0x7E0x75/0x76在部分标准版本里也有以OEM规范为准。子功能是否支持不支持返回0x12。安全等级检查需要解锁但没解锁返回0x33。注意0x33的优先级在参数越界之前还是之后行业里有分歧。我习惯先查安全因为“没权限”比“参数错误”更根本但有些OEM规范要求先查参数。这个必须跟着规范走。前置条件检查比如当前状态、时序、时序状态机返回0x22、0x24等。参数范围检查DID、DTC、地址、长度等返回0x31。运行时错误检查比如Flash写入失败、例程执行失败返回0x72、0x71、0x26等。这个顺序不是绝对的但它能保证在同样一个请求里如果格式错了不会被误判成“参数越界”如果会话不对不会被误判成“参数错误”。诊断仪做故障排查时也常常按这个顺序去解析NRC。3.2 优先级错误带来的实际故障我见过一个典型的错误案例某ECU接收到0x2E请求时先检查DID是否存在再检查安全等级。于是诊断仪在默认会话下发给一个需要安全解锁的DID写请求ECU因为“DID在当前会话不存在”直接返回0x31。可诊断仪的逻辑是“DID存在但你没权限”它会先去解锁再重试结果还是0x31然后陷入死循环。后来改成先检查安全等级返回0x33诊断仪立刻就知道要解锁了。另一个常见错误是0x12和0x7F的混用。0x7F是“服务在当前会话不支持”0x12是“子功能在当前会话不支持”或“子功能不支持”。比如0x19服务的0x04子功能在默认会话下不可用但0x19服务本身可用。如果返回0x7F诊断仪以为整个0x19服务不可用实际上只是这个子功能受限。正确做法是返回0x7EsubFunctionNotSupportedInActiveSession如果协议版本支持或0x12。如果OEM规范里没有0x7E就用0x12。还有一个优先级细节是0x13长度错误和0x31参数范围错误的选择。0x13针对的是“报文的格式或长度与约定不一致”0x31针对的是“字段值超出约定范围”。举例0x22服务请求8个字节的DID列表4个DID如果只发了3个字节一个半DID就是0x13如果发了4个字节但其中有一个DID不存在就是0x31。测试用例通常会专门构造这种“半截DID”报文来验证0x13的实现。4. 刷写流程中的NRC实战4.1 从进入到退出的NRC走读刷写流程是UDS服务最典型的综合应用正好把NRC串一遍。整个过程通常是默认会话 - 0x10 0x02切换到编程会话 - 0x27安全解锁 - 0x85关闭DTC记录 - 0x28关闭通信 - 0x34请求下载 - 0x36传输数据 - 0x37请求传输退出 - 0x11复位。这一串流程里每个环节都可能返回NRC测试时最容易出问题的是以下几步。第一步0x10 0x02进入编程会话。如果ECU正在刷写过程中被重复要求进入编程会话不同OEM有不同策略。有的直接返回正响应幂等有的返回0x22因为已经处于编程会话。我建议实现成“如果当前会话已经是编程会话再次请求0x10 0x02就回正响应”这样诊断仪重试逻辑更简单。如果整车条件不满足比如车速不为0或发动机运行中返回0x22。第二步0x27解锁。编程会话下的安全等级通常是0x01或0x03。解锁失败的NRC路径很典型连续输错密钥会先返回0x35超过次数限制返回0x36然后ECU进入延迟锁定状态下一次请求种子返回0x37。这时候诊断仪必须等延迟时间结束才能继续否则刷写流程会卡死。第三步0x34请求下载。请求下载时诊断仪会申请一段内存地址和大小。如果这个地址落在Flash保护区或超出App地址范围返回0x31。如果ECU的Bootloader还没完成初始化返回0x70uploadDownloadNotAccepted。很多刷写失败案例都发生在这里不是0x31也不是0x70而是ECU压根没返回0x50正响应而是回了0x7F 10 22——这说明诊断仪压根没成功进入编程会话到了0x34这一步才发现状态不对。所以排查刷写问题第一步永远是从会话状态开始查。第四步0x36传输数据。这是NRC出现频率最高的一步。块序列计数器回0x73、Flash写入失败回0x71、长度不匹配回0x13、内存地址越界回0x31、ECU忙回0x21或0x78。0x78的用法是ECU收到0x36后需要比正常情况下更长的时间来擦写Flash先回一个0x7F 36 78表示“请求收到正在处理稍后再来问”。诊断仪收到0x78后不会重发这一帧而是等待一段时间后重新发送下一帧。注意0x78不是最终响应后续ECU必须再回一个真正的0x76正响应或0x7F错误响应否则诊断仪会超时。第五步0x37退出传输。0x37之后ECU通常要做完整性校验。如果校验失败返回0x72generalProgrammingFailure。如果校验通过才回0x77正响应。0x37失败后有的ECU允许诊断仪重新发0x34开启新一轮下载有的则要求重新进入编程会话。这个行为很影响刷写工具的恢复策略建议在诊断规范里明确写清楚。4.2 刷写中0x78的处理和“时序惩罚”0x78requestCorrectlyReceived-ResponsePending是实现刷写功能时绕不开的一个NRC。它本质上告诉诊断仪“我没拒绝你但我要花时间处理你别急。”ECU可以在处理0x36或0x31这种耗时操作时发0x78然后继续内部处理处理完再发真正的正响应或负响应。这里有一个很关键的“P2/P2时间”约束。诊断仪发出请求后等待ECU在P2时间内返回第一帧响应默认是50ms。如果ECU判断自己处理不完就必须在P2时间内先发0x78然后可以在P2时间默认5000ms内完成。如果P2*还不够ECU可以继续发0x78但每发一次都会重置计时器。测试时一定要验证ECU在极端情况比如Flash写入变慢下的0x78发送频率不能只按正常耗时写死。踩过一个坑某ECU的0x36处理在正常条件下只需要30ms测试工程师就没做0x78分支。结果在高温老化测试中Flash写入变慢ECU在50ms内没回任何响应诊断仪直接判定超时刷写中断ECU卡在半刷状态。后来不得不在0x36处理入口加了一个“超过40ms就发0x78”的保护逻辑。这种边界场景只有沉浸式跑过刷写流程的人才会重视。5. 常见问题与排查技巧实录5.1 NRC问题速查表我把平时排查NRC问题时遇到的高频故障整理成了一个速查表方便你对照排查。这张表覆盖了绝大多数实际开发中的NRC异常。现象可能原因处理建议诊断仪收到0x7F 10 31但0x10服务明明存在报文里的subFunction或suppressPosRspMsgIndicationBit组合不对检查0x10报文字节长度和subFunction取值范围0x22请求不存在的DID返回0x7F而不是0x31代码把DID支持列表和会话支持列表耦合在一起把DID配置表里的“是否存在”和“会话是否可读”拆开0x27发送密钥返回0x24但没有请求过种子安全访问状态机在收到其他服务后被重置了检查安全状态机是否被0x10、0x3E等干扰0x2E写入时返回0x22但规范要求0x31范围校验被放在条件校验后面了按OEM规范调整NRC优先级0x36刷写中途返回0x73块序列计数器不连续通常是诊断仪重发导致的检查诊断仪重发策略和ECU计数器重置逻辑ECU刷写时返回0x78后一直没有最终响应0x78发送了但内部处理线程卡死或超时检查处理线程和P2*超时逻辑0x19请求DTC数量返回0x31DTC状态掩码或DTC组定义不支持核对支持的状态掩码表0x11复位请求返回0x7F复位服务当前会话不支持或suppressPosRsp位没处理检查复位服务会话绑定5.2 排查NRC的实用方法排查NRC问题光看报文不够我一般按三步走。第一步复现和抓包。用一个能记录完整报文的诊断仪抓下完整交互过程重点看请求帧和响应帧的时间戳。很多NRC问题不是“返回了错误的NRC”而是“应该返回NRC的时候没返回、导致诊断仪超时”。这种情况下时间戳比NRC本身更有价值。比如ECU在100ms后才回0x7F 22 22虽然NRC正确但已经违反了P2约束诊断仪照样报错。第二步查配置表和状态机。NRC异常十有八九出在配置上。DID支持列表、DID会话矩阵、DID安全等级、DTC掩码表、例程ID表、安全等级定义这些配置表和状态机必须一一核对。我建议把配置表做成独立模块不要硬编码在业务逻辑里。这样排查时只需要核对配置表不必翻代码。第三步对照OEM规范做“NRC优先级用例”验证。规范里的每个服务都有对应的测试用例比如“在默认会话下请求一个需要扩展会话的DID应返回0x7F”。我建议把这些用例整理成自动化脚本在每次协议栈改动后跑一遍回归。NRC这块改动特别容易出隐性回归比如你改了0x22的会话配置可能会影响0x2E、0x23等所有依赖DID配置表的地方。还有一个小技巧在ECU的调试日志里把“检查NRC的路径”打出来。比如请求0x2E时日志里按顺序打出“检查格式 - 通过检查会话 - 通过检查安全 - 未解锁返回0x33”。这样测试人员或者产线人员不用读代码就能看出NRC是从哪个环节抛出来的定位速度快很多。这个日志在量产阶段可以关掉但开发阶段一定要保留。5.3 协议版本和OEM规范的坑最后提醒一个容易被忽略的问题不同版本的ISO 14229-1对NRC的定义有微调。比如0x75、0x76、0x7E、0x7F这些和“会话支持”相关的NRC在2006版、2013版和2020版里的定义和推荐用法不完全一样。有的OEM规范基于14229-1:2013有的基于2020还有的混合使用。写代码之前一定要确认基于哪个版本并且严格按照那个版本的NRC定义实现。比如0x7E和0x7F在有些规范里被定义为subFunctionNotSupportedInActiveSession和serviceNotSupportedInActiveSession而有些规范里只用0x12来表示两者不做会话区分。这种差异没法靠“猜”解决只能看规范。供应商库比如Vector的CANoe、AUTOSAR协议栈通常会按标准实现默认行为但OEM的SWS常常会覆盖这些默认行为。所以最后一句话NRC实现得好不好不取决于你背了多少个代码而取决于你对协议、规范、状态机三者的理解有多深。每当我在现场排查NRC问题时都会先问三件事这版规范是哪个版本、ECU当前在哪个会话、上一个请求是什么。搞清楚这三件事一半的NRC问题已经解决了。