实现MCU本地OTA升级的LIN诊断方法详解

一、目标

通过PC端上位机实现MCU本地的OTA升级,本篇文章对实现的目的、需要用到的第三方工具、LIN诊断帧、升级协议、MCU端升级过程以及PC端升级过程做详细说明。

二、目的

最近在做MCU项目时需要将样机寄给客户进行验证,在客户的验证过程中要求参数可调试,如果需要修改软件升级MCU就很麻烦。于是就想做个上位机实现MCU升级功能,项目中MCU只有LIN接口可以用来作为调试接口,于是就想通过LIN诊断协议进行参数调试和实现本地OTA升级功能。

三、第三方工具

 一般LIN开发用的调试工具是CANOE,但是CANOE太贵了,客户端也不一定有CANOE工具,于是选用了在淘宝就可以买到的一款USB转LIN的调试工具-图莫斯UTA0503,如下图:

用这款工具的好处是厂家提供了二次开发的接口库,用户可以使用这个库进行二次开发,实现自己的PC上位机,支持QT等实现。

四、LIN诊断帧

从发送格式上,诊断帧的PDU 单元U (Packet Data Unit,分组数据单元)可分为单帧(Single Frame,SF)、首帧(First Frame,FF)和续帧(Consecutive Frames, CF)三种。从发送源上,主机发送请求 PDU,从机发送应答 PDU。 如下图所示,为 PDU 格式,包括节点地址(NAD),协议控制信息(PCI),LEN,服务 ID(SID),应答服务 ID(RSID), 消息字节段(D1~D6)。首字节 NAD 首先发送,末字节 D4,D5,D6 最后发送。

第一个字节是 NAD(node address),用于区分不同从机节点的地址。 0x00 用于休眠命令; 0x01~0x7D 从机节点地址,即 NAD 0x7E 功能节点地址(功能 NAD); 0x7F 广播节点地址(广播 NAD); 0x80~0xFF 用户自定义。

第二个字节是 PCI(Protocol Control Information)信息,包含了 PDU 单元类型和消息字节长度 的信息。如下表:

 单帧中,附加信息 Length 表示消息字节数加 1。首帧中,附加信息只表示 Length 的高 4 位,低 8 位在 LEN 中表示。因此在消息长度为 12 位数据,最大长度为 4095(0xFFF)。 续帧中的附加信息表示首帧后,跟随的续帧的编号,第一个续帧编号为 1,之后累加 1。如果续帧数多于 15 个,那么帧计数器在第 16 个续帧时从 0 重新计数。

SID(Service Identifier)表示了从机节点应完成的服务请求。节点配置服务的 SID 区间为 0xB0~0xB7,诊断 服务的 SID 区间为 0x00~0xAF,0xB8~0xFE。

RSID(Response Service Identifier)表示从机节点应答的内容,它的值是 SID+0x40。

五、升级协议

5.1 升级时序如下图所示:

5.2 升级协议定义: 

1)节点探测指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(SID) byte4 byte5 byte6 byte7 byte8
 单帧 需要探测的节点地址 0x06 0xB2 0x20 产商ID低8位 产商ID高8位 功能ID低8位 功能ID高8位
说明:使用0xB2诊断服务进行节点探测,byte4的0x20为自定义的节点探测服务识别ID,产商ID和功能ID根据MCU定义修改
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0xF2 0x21 0x22 0x23 0x24 0x25
说明:如果节点存在,MCU应答byte4~byte8的内容可以自行定义。
2)开始升级指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(SID) byte4 byte5 byte6 byte7 byte8
 单帧 需要升级的节点地址 0x06 0x22 0xFA 0x30 0x00 0x00 0x00
说明:使用0x22诊断服务发送节点升级指令,byte4的0xFA为自定义的节点升级服务识别ID,byte5的0x30为开始升级指令。
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0x62 0xFA 0x30 错误码 0x00 0x00
说明:byte6字节为错误码定义,参照升级错误码定义。
3)升级包总数指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(SID) byte4 byte5 byte6 byte7 byte8
单帧  需要升级的节点地址 0x06 0x22 0xFA 0x31 包总数高8位 包总数低8位 0x00
说明:byte5的0x31为升级包总数指令,byte6和byte7为2字节大小的升级包总数的高8位和低8位。
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0x62 0xFA 0x31 错误码 0x00 0x00
说明:byte6字节为错误码定义,参照升级错误码定义。
4)升级包ID请求指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(SID) byte4 byte5 byte6 byte7 byte8
 单帧 需要升级的节点地址 0x06 0x22 0xFA 0x32 0x00 0x00 0x00
说明:byte5的0x32为升级ID请求指令,由MCU告知当前需要发送的下一个升级包ID。
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0x62 0xFA 0x32 错误码 包ID高8位 包ID低8位
说明:byte6字节为错误码定义,参照升级错误码定义。Byte7和8为MCU下一个升级包ID。
5)升级包数据指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(LEN) byte4(SID) byte5 byte6 byte7 byte8
首帧  需要升级的节点地址 0x10 0x45 0x22 0xFA 0x33 包ID高8位 包ID低8位
续帧1  需要升级的节点地址 0x21 D1 D2 D3 D4 D5 D6
续帧2  需要升级的节点地址 0x22 D7 D8 D9 D10 D11 D12
续帧3  需要升级的节点地址 0x23 D13 D14 D15 D16 D17 D18
续帧4  需要升级的节点地址 0x24 D19 D20 D21 D22 D23 D24
续帧5   需要升级的节点地址 0x25 D25 D26 D27 D28 D29 D30
续帧6  需要升级的节点地址 0x26 D31 D32 D33 D34 D35 D36
续帧7  需要升级的节点地址 0x27 D37 D38 D39 D40 D41 D42
续帧8  需要升级的节点地址 0x28 D43 D44 D45 D46 D47 D48
续帧9  需要升级的节点地址 0x29 D49 D50 D51 D52 D53 D54
续帧10  需要升级的节点地址 0x2A D55 D56 D57 D58 D59 D60
续帧11  需要升级的节点地址 0x2B D61 D62 D63 D64 0xFF 0xFF
说明:byte5的0x33为升级包数据发送指令,包数据长度为64字节(D1~D64),最后一包的数据不满64字节则填充0xFF。
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0x62 0xFA 0x33 错误码 包ID高8位 包ID低8位
说明:byte6字节为错误码定义,参照升级错误码定义。Byte7和8为MCU下一个升级包ID。
6)CRC校验码发送指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(SID) byte4 byte5 byte6 byte7 byte8
 单帧 需要升级的节点地址 0x06 0x22 0xFA 0x34 校验码高8位 校验码低8位 0x00
说明:byte5的0x34为升级包校验码发送指令,由PC计算(累加升级包数据每个字节包括填充的0xFF)并发送计算的CRC校验码值(16字节)。
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0x62 0xFA 0x34 错误码 校验码高8位 校验码低8位
说明:byte6字节为错误码定义,参照升级错误码定义。Byte7和8为MCU计算的CRC校验码数值,算法同PC端。
7)重启MCU指令:
PC端请求 byte1(NAD) byte2(PCI) byte3(SID) byte4 byte5 byte6 byte7 byte8
 单帧 需要升级的节点地址 0x06 0x22 0xFA 0x35 0x00 0x00 0x00
说明:byte5的0x35为升级包接收完整重启MCU指令。
MCU端应答 byte1(NAD) byte2(PCI) byte3(RSID) byte4 byte5 byte6 byte7 byte8
 单帧 MCU节点地址 0x06 0x62 0xFA 0x35 错误码 0x00 0x00
说明:byte6字节为错误码定义,参照升级错误码定义。

六、MCU端升级过程:

 MCU端flash分区如上图所示,boot为启动分区,app1为A分区,也是app启动运行的分区,app2为B分区,用于升级过程接收保存升级包数据的备份分区,data flash分区为用户数据保存区域和升级标志等信息保存区域。

MCU端接收升级数据包并写入B分区并累加CRC校验码,当升级包接收完成后计算的CRC校验码和PC端发送过来的校验码一致的话说明接收的数据包是完整的,写入升级标志置位、包总数和CRC等信息,并重启MCU。Boot启动时读取升级标志,包总数和CRC校验值,判断升级标志是否置位,如果置位则读取B分区内容并计算CRC校验值,如果计算的CRC校验值和保存的CRC校验值一致说明B分区数据完整无误。擦除A分区数据内容,将B分区数据拷贝到A分区。跳转到A分区运行。

七、PC端升级过程:

 上位机提供了本地OTA升级功能。用户可以在没有烧写工具的情况下通过LIN升级APP软件,升级界面如下图1所示,界面中有“升级节点探测”功能和“升级”功能两块。

其中“升级节点探测”功能是为了探测可升级的节点地址,为后续升级使用。如果探测到可升级的MCU节点,将在“探测节点地址列表”中显示。

探测节点完成后可以在列表中选中要升级的节点,后续对同一个MCU升级已经知道了节点地址就可以直接在“2”所在的位置直接填写节点地址不需要再去走探测流程。然后点击“加载升级文件”按钮选则需要升级的bin文件,Bin文件信息将在旁边的矩形框中显示。点击“开始升级”按钮开始进行升级。如果升级过程中出现错误,比如CRC校验错误等,可以再次点击“开始升级”按钮进行升级,升级过程比较慢,大概需要两三分钟。当所有的升级包都发送成功后会弹出如下图2所示的对话框提示用户是否需要写入升级标志并重启MCU,如果用户点击取“取消”按钮,升级包数据仅仅保存在B分区,并不会更新到A分区,升级过程实际并没有完成。用户点击“确定”按钮才真正重启MCU将B分区数据拷贝到A分区,并从A分区启动运行程序。

图1

 

 图2

  八、总结

通过实现LIN诊断协议OTA升级功能,让我对LIN诊断协议有了更加深刻的理解。本文定义的协议也适用于OTA远程升级,对升级流程中有考虑不足的请指出,谢谢。

物联沃分享整理
物联沃-IOTWORD物联网 » 实现MCU本地OTA升级的LIN诊断方法详解

发表评论