主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制

2025-04-18

在痞子衡旧文《RT四位数Boot模式》里的1.2.1 Serial Downloader模式;《RT三位数Boot模式》里的p1.2.2 Serial Boot模式里都介绍到了i.MXRT芯片内置ROM程序里支持与主机进行数据交互,而交互的通信协议均是blhost协议(这最早来自于飞思卡尔Kinetis系列ROM), 有了这个功能,我们便可以直接将应用程序灌进i.MXRT内部SRAM去加载执行,这个功能在多处理器系统里(尤其是i.MXRT作为协处理器)大有用处。

最近有个客户设计了高通AR1+恩智浦i.MXRT600 的主从系统,RT600作为协处理器直接通过SPI接口从主处理器AR1接收应用程序App并加载到自身内部SRAM执行,这样硬件上便可省去RT600的专属非易失性存储器。客户已经将blhost协议代码集成进了AR1程序里,但在实际测试过程中发现有一定概率导致RT600程序加载失败,RT600 ROM会返回kStatus_AbortDataPhase (0x5A,0xA3), 这是怎么回事?今天痞子衡就来聊聊这个话题:

一、i.MXRT与主机交互方法

我们首先简单回顾下i.MXRT内置ROM程序配套的与主机交互方法,有如下三种。其中方法一是比较常用的,把PC当作主机,因为UART/USB接口可以直接从PC引出,这种方式一般集成在上位机GUI工具里(比如恩智浦官方的SPT以及痞子衡的NXP-MCUBootUtility)。方法二本质上和方式一差不多,主机仍然是PC, 只不过通信接口是SPI/I2C,因为无法直接从PC引出,需要有一个桥接板,恩智浦一共做了三种不同的桥接实现。方式三就是本文提及的客户所用到的方法,把主处理器当作主机,因为处理器接口丰富,所以不管哪种通信方式均可以直连。

因为方式一和方式二均可以直接使用恩智浦提供的配套工具链,因此blhost协议实现细节以及注意事项都被包在了工具链里面,客户使用起来基本不会遇到问题。而方式三需要客户自己移植实现blhost协议到主处理器代码里,这可能会遇到一些协议细节上的设计问题。

主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制 (https://ic.work/) 技术资料 第1张

这里需要特别提一下方式二里的Embedded Host桥接实现,在恩智浦官网MCUBoot主页我们可以下载到NXP_Kinetis_Bootloader_2_0_0.zip包,NXP_Kinetis_Bootloader_2_0_0validationembedded_host 路径下我们可以找到基于Kinetis K65的实现,如果你想移植blhost协议到处理器上运行,不妨参考这个代码。

主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制 (https://ic.work/) 技术资料 第2张

二、i.MXRT从主机接收数据包超时机制

现在我们谈回到blhost协议本身,这是一套数据包传输格式与支持命令的定义集合。打开RT600参考手册的Non-Secure Boot ROM章节,可以找到具体的协议细节,这里就不再赘述。我们只取其中关于write-memory命令的介绍,主机给i.MXRT下载数据(App)主要就是借助这个命令。

主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制 (https://ic.work/) 技术资料 第3张

write-memory命令的过程其实很简单,主机(Host)先要发送含write-memory信息的命令包(0x5A, 0xA4 ...) 给i.MXRT(图中叫target),收到确认的回复(0x5A, 0xA1)后,主机继续发送含App程序数据的数据包(0x5A, 0xA5...),等待i.MXRT处理完成返回确认信息,然后主机不断发送数据包,直到App数据全部发送完成,最后还有一个结束命令包。

Note: 注意这里的App数据不是一个数据包就全部发送完的,而是被拆分成了很多个小数据包,每个小数据包最大长度是512字节。拆分成小包的目的是防止通信过程中有干扰导致数据错误,出现错误就只需要重新发送该包数据。如果不拆分数据包,出现错误就得全部App数据重发,效率太低。

主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制 (https://ic.work/) 技术资料 第4张

关于每个数据小包的接收与发送, i.MX RT均设计了超时机制保护。如果主机已经开始发送当前小包数据(发完包固定起始字节0x5A后为超时起点),那么需要在规定时间内(包剩余长度(Bytes)*10ms/Bytes) 完成该包数据发送,如果超时时间内未完成,i.MX RT则返回 kStatus_AbortDataPhase。至于read-memory时主机接收小包数据时超时机制相同,只不过时间单元是20ms/Bytes。

Note1:RT500/600/700 ROM程序里数据包处理超时机制是一样的,发送和接收均有超时。

Note2:RT1160/1170/1180 ROM程序里数据包处理仅有接收超时,没有发送超时。

当然文档里还有未详尽的地方,主机每发完一小包数据后都需要读确认信息(0x5A, 0xA1),确认信息这里是否有超时限制?如果有,是怎样的机制?

痞子衡就不卖关子了,这里是需要特别注意的,当主机发完一包数据后,i.MXRT需要及时处理数据的,由于这里是加载程序进内部SRAM,所以就是将该数据包从缓冲区搬到 SRAM指定位置,这个时间t2很短,文档里并未给出。t3是比较关键的时间,这里的计时起点并不是主机收到ACK包的第一个字节,而是i.MXRT处理完数据搬移后就开始了,因此主机每次发完数据包之后, 都需要在t2+t3的时间内将确认信息数据包及时读走,否则i.MXRT则返回kStatus_AbortDataPhase。

主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制 (https://ic.work/) 技术资料 第5张

那么问题来了,如果一小包数据是200 bytes(包含 0x5A包头等信息),请问主机发送数据和接收确认的超时时间分别是多少?答案是1990ms和t2+40ms (这里主机接收确认消息只拿了2 bytes数据)。

三、客户主机发送数据包设计

最后回到客户的问题,经过和客户的沟通,主处理器AR1运行得是一个非实时操作系统。在给RT600加载App程序过程中会出现任务调度情况,发送完一个小数据包后,因为任务调度的关系,导致主机读取确认消息(0x5A, 0xA1)的时间间隔不确定,有时候小于40ms, 有时候会超出40ms, 显然这是不符合blhost协议超时机制规定的。

此外即使能满足超时要求,但是主机如何读取确认消息也是有讲究的,尝试读取首字节0x5A要满足至少100us延时(如果存在多次尝试的话,两次尝试之间也要延时), 而拿到首字节后,再去读取第二个字节 0xA1, 也需要至少延时50us。

主从系统中i.MXRT系列MCU从主处理器接收App数据包超时机制 (https://ic.work/) 技术资料 第6张

最后还有一点需要提醒,因为RT500/600/700中存在多个核(CM33、DSP、NPU等), 所以主机有时候给i.MXRT灌的程序数据是糅合了多个核代码,write-memory命令里提供的App长度信息要和实际要写入的数据量匹配,否则i.MXRT也会返回异常状态码。

NXP

恩智浦致力于打造安全的连接和基础设施解决方案,为智慧生活保驾护航。

文章推荐

相关推荐