本通信协议依据ISO14230、ISO14229-1和ISO15765来实现Bootloader通信,适用于ECU通过CAN总线实现程序的在线更新。
本文件描述了工程系统配置,Bootloader具体流程和Bootloader协议,是ECU的控制器实现Bootloader程序的依据。
ISO 11898-1: Road Vehicles - Controller Area Networks (CAN) - Part 1: Data link layer
and physical signalling
ISO 11898-2: Road Vehicles - Controller Area Networks (CAN) - Part 2: High-speed
medium access unit
ISO 15765-1: Road Vehicles - Diagnostics on Controller Area Networks (CAN) -
Part 1: General information
ISO 15765-2: Road Vehicles - Diagnostics on Controller Area Networks (CAN) -
Part 2: Network layer services
ISO 15765-3: Road Vehicles - Diagnostics on Controller Area Networks (CAN) -
Part 3: Implementation of unified diagnostic services (UDS on CAN)
ISO 14229-1: Road Vehicles - Unified diagnostic services (UDS) -
Specification and requirements
ISO 15031-6: Road Vehicles - Communication between vehicle and external equipment for
emission-related diagnostic - Part 6: Diagnostic trouble code definitions
1.按照XXX刷写规范开发;(有些主机厂(Car OEM)为了知识产权保护,有自己的bootloader协议,这种情况下,bootloader开发者就必须按照主机厂的要求来开发)
2.刷写方式UDS ( UDS协议栈 ) ,SOS烧录 ( 使用最简单的 UDS协议栈 的服务来烧写程序);
3.初始化时将所有IO置为安全状态;
4.刷写过程中需要存储及和APP通信的数据存入外部EEPROM中;
5.bootloader程序地址范围C00000-C04000;
6.主频80MHz;
7.跳转APP前清除配置的硬件资源;
8.单片机内部看门狗喂狗超时导致复位的标志位置位时在cstart初始化内存前直接跳转APP;
9.在进入编程模式后将变量DWORD ECU_Reprogramming_Mode_Ended __at(0x00CFF8)置为0x55AA55AAU,编程完成后清0;
10.APP有三部分程序需要刷写:1.主单片机内的APP程序,正常方式刷写;2.辅单片机内的Boot或APP,通过Spi通信传输命令及数据,由bootloder通过通信完成刷写;3.外部EEPROM数据,通过I2C刷写,由bootloder通过通信完成刷写;
11.辅单片机程序及EEPROM数据在合成HEX文件时需要叠加偏移地址,如辅单片机程序起始地址C08000在合成HEX后的地址为0x1C08000;EEPROM地址起始位0x2000000;bootloadr在接收到这种地址时采用相应的刷写方式并还原地址;
12.HEX合成软件及bootloader要能够实现三部分的任意组合的刷写;
13.HEX合成软件需要将全地址范围内未使用的字节置为无效操作码0xF9;
14.HEX合成软件需要计算设定的地址范围的校验和并将结果写入目标HEX文件的指定地址;
15.在cstart中变量初始化之前判断单片机是否是软件复位,如果是则将变量WDT_Fault_At_Power_Up_Set_By_Boot__at(0x00CFF2)置为1并立即跳转到APP中,否则置为0正常运行。
注:烧写程序的Hex文件,对地址偏移修改如下图:
这里有HEX 文件的说明(维基百科)链接: link.
还有这个博主的链接 链接: link.
每个XXX主机厂的刷写规范都大同小异,区别不大。弄明白一个,往往能举一反三。
Bootloader的诊断服务流程如下:
预编译阶段
1.开始编程后,0x22服务通过标识符0xF193读取ECU硬件版本号,0xF180读取bootloader软件版本号。
2.0x10服务进入扩展会话模式。
3.0x85服务关闭DTC。
4.0x28服务通信控制,关闭其它通信。
5.0x10服务进入编程会话模式。
6.0x27服务进行安全访问。
7.0x2E服务通过标识符写入指纹数据和编程日期。
编程阶段
编程结束阶段
诊断仪和 ECU 应(shall) 遵从以下关键规则:
诊断仪与 ECU 应通过高速 CAN 总线进行通信、
诊断仪和 ECU 应遵从以下关键规则:
本章节所描述的网络层要求是基于 ISO 15765-2 制定的,用于诊断仪和 ECU 之间的诊断通信。
除了以下章节定义的要求外,更多针对诊断仪与 ECU 应(shall) 遵从的网络层的详细要求请参照 ISO15765-2。
网络层协议具有以下功能:
a)一次可发送或接收最多4095个数据字节;
b)报告发送或接收完成(或失败)。
发送消息多达7个数据字节时(正常编址),可通过发送一个网络层协议数据单元,称之为单帧(SF)。
Figure 7-1 为单帧传输示意图。
通过报文分割并发送多个网络层协议数据单元(N_PDU),来完成超过7个字节的消息的发送;通过接收
多个N_PDU并对接收的一系列数据字节进行重组,来完成超过7个字节的消息的接收。多个N_PDU分为
首帧(FF N_PDU)(报文的第一个协议数据单元)与后续帧(FC N_PDU,也称为流控帧).(接下来的所有协议数据单元)。
多N_PDU报文接收器能够调整传输吞吐量以适应自身接收能力,这种调整是依靠流控机制采用流控协议
超过7个数据字节的消息被分为首帧与后续帧,其中首帧包含前6个数据字节的网络层协议数据单元(FF
N_PDU),后续帧包含剩余数据字节的网络层协议数据单元(CF N_PDU)。每一个CF N_PDU最多包含
7个数据字节,由于CF N_PDU包含了FF N_PDU以外的其余字节,所以数据长度有可能小于7。
消息长度信息包含在FF N_PDU。发送器对所有的CF N_PDU进行编号,这有助于接收器按照相应的编号顺序对消息进行重组。
流控机制(Figure 7-2)允许接收器把自身的接收能力通知给发送器。由于不同节点的接收能力可能不同,所以需要接收器把自身的接收能力通知给发送器,发送器应调整自身的发送策略以适应接收器的接收能力。
接收器的接收能力定义如下。
数据块大小Block-Size (BS):在允许发送器继续传输后续帧 之前,接收器允许发送器发送数据帧的最大数量。
最小间隔时间Separation-Time-Min (STmin)::发送器传输的两个连续后续帧 之间最小时间间隔。
除最后一个数据块以外,其余数据块包含协议数据单元的数量为BS。最后一个数据块包含剩余的协议数
据单元数量为1到BS。
在发送器(接收器)等待接收接收器(发送器)发送的协议数据单元时,允许采用一种超时机制来检测
传输的成败。
通过流控帧,接收器具有控制发送器发送后续帧的能力,它可以控制延时传输,并且当发送器所发送的
字节数超出了接收器缓存的存储能力时拒绝接收。
不同节点网络层对等实体之间的通信是通过网络层协议数据单元的交互完成的。
本部分定义了四种不同类型的网络层协议数据单元:单帧(SF N_PDU)、首帧(FF N_PDU)、后续帧(CF N_PDU)及流控帧(FC N_PDU)。这些网络层协议数据单元用来在网络层对等实体之间建立通信路径、交换通信参数、传输用户数据与释放通信资源。
单帧网络层协议数据单元通过单帧协议控制信息(SF N_PCI)来识别。单帧网络层协议数据单元应(shall)被发送端网络实体发送出去,可以由一个或多个接收端网络实体接收。单帧网络层协议数据单元应(shall)被发送出去用来传输服务数据单元,该服务数据单元可以通过对数据链路层的单一服务请求发送出去。
首帧协议控制信息(FF N_PCI)是首帧网络层协议数据单元(FF N_PDU)的标识。在分段信息传输过程中,发送端网络实体应(shall) 发送FF N_PDU,对应地,接收端网络实体应(shall) 接收FF N_PDU。上述发送接收机制可用来识别分段消息的FF N_PDU。当接收到一个FF N_PDU时,接收端网络层实体开始重组分段信息。
后续帧 协议控制信息(CF N_PCI)是后续帧 网络层协议数据单元(CF N_PDU)的标识。 CF N_PDU用来传输分段的服务数据单元消息数据。在FF N_PDU之后被发送实体发送的所有N_PDU应(shall) 与CF N_PDU的编码方式一致。在接收到最后一个CF N_PDU之后,接收端网络实体应(shall) 把已重组的消息传递给接收端网络实体的服务使用者。在分段消息传输过程中,发送端网络实体应(shall) 发送CF N_PDU,对应地,接收端网络实体应(shall) 接收CF N_PDU。
流控协议控制信息(FC N_PCI)是流控网络层协议数据单元(FC N_PDU)的标识。 FC N_PDU控制发送端网络实体开始、停止或者恢复CF N_PDU的传输。当接收端网络实体正确接收到:
a).FF N_PDU,或
b).前一个后续帧 数据块中的最后一个CF N_PDU(如果需要发送更多的后续帧 ),
并且已经准备好接收后续数据时,它应发送一个FC N_PDU给发送端网络实体。
另外,在分段信息传输过程中, FC N_PDU可以要求发送端网络实体暂停CF N_PDU的传输。如果发送端实体发送的FF N_PDU内的数据长度信息(FF_DL)超过接收端实体的缓存空间, FC N_PDU还可以要求发送端网络实体终止整个分段信息的传输。
N_PDU能够使能一个节点的网络层与另一个或多个节点的网络层(对等协议实体)之间传输数据。所有的N_PDU都包含3个场域
Address information (N_AI)/地址信息(N_AI)
N_AI标识了网络层之间进行信息交互的对等实体。N_SDU中接收的N_AI应复制到N_PDU。如果N_SDU中接收的消息数据(<消息数据>与<长度>)太长,以至于需要网络层分段才能传输整个消息,那么N_AI应(shall) 复制(重复) 到传输的每一个N_PDU中。
N_AI的场域中包含了一些地址信息,这些地址信息标识了交互消息的类型以及发生数据交换的接收端与发送端。 N_AI的地址信息由消息地址组成。
Protocol control information (N_PCI)/协议控制信息(N_PCI)
N_PCI标识了相互交换的N_PDU类型。同时,它还可以用于通信网络层实体之间其它控制参数的交换。
Data Field (N_Data)/数据场(N_Data)
N_PDU中的N_Data用来传输服务用户数据,该服务用户数据包含在接收的N_USData.request服务原语的<消息数据>参数中。如果需要的话,在通过网络传输之前, <消息数据>参数被划分成可填充到N_PDU数据场中的多个小块。N_Data的大小取决于N_PDU类型及选定的地址格式。
N_PCI场标识了相互交换的N_PDU类型,它还可以用于通信网络层实体之间其它控制参数的交换。N_PCI标识的N_PDU类型如下图所示
对SF N_PCI字节进行了描述
SF N_PDU中的单帧数据长度(SF_DL)参数表示服务用户数据字节的数量。
注: 只有在正常编址模式下SF_DL的值才可能为7,大于7和等于 0的 SF通信协议中会被摒弃、忽略不处理。
FF N_PCI字节进行了描述
FF N_PDU中的首帧数据长度(FF_DL)参数表示服务用户数据字节的数量。分段消息长度(FF_DL)可解码成一个长度占12个位的值,该值的最低位为N_PCI第2个字节中的第0位,该值的最高位为N_PCI 第1个字节中的第3位。所支持分段消息的最大长度为4095个用户数据字节,服务参数<长度>值应(shall)分配给FF_DL。
注: 在正常编址模式下FF_DL的范围为8-FFF(Hex)
FF N_PDU中的FF_DL参数表示服务用户数据字节的数量。
对CF N_PCI字节进行了描述.
Consecutive-Frame 的 SN参数定义
CF N_PDU中的参数SN表示后续帧的顺序。
对所有分段消息来说, SN应(shall) 从0开始。其中,首帧(FF)中的SN为0。虽然首帧(FF)中的N_PCI场没有包含一个明确的序列号,但是首帧(FF)的SN仍被当作0.
紧跟在首帧(FF)之后的第一个后续帧(CF)的SN为1. 在分段消息传输过程中,每发送一个新的CF, SN的值应(shall) 加1。任何FC帧 不应(shall not) 影响SN的值。当达到15时, SN的值应(shall) 在发送下一个后续帧时重新设为0.
对FC N_PCI字节进行了描述。
参数FS表示接收端告知发送端网络实体能否继续执行消息的传输
FS 参数定义
BS 参数定义
STmin参数定义
网络层定时参数
注:
对诊断仪与ECU应(shall)遵从的网络层定时参数的其它更详细要求见ISO 15765-2。
诊断服务表 可分为应用程序(App)和引导加载程序(BOOT) 两种。这里以BOOT的诊断服务表说明。
注:
以上图表说明:BOOT中的支持应用层服务,实现BOOT功能,需要哪些必要服务,同时,BOOT更新程序的流程是否符合开发规范。
注:
这些时间参数是与10服务的积极响应是息息相关的,每个项目需求不一样,那么这个10服务的积极应答就要修改成相应的参数。同时也引出下面的会话层时间参数
话层时间参数定义
注:
此说明,一个诊断会话保持的时间在ECU和 诊断仪中的极限值是多少。例如:10 02编程会话在没有任何操作的情况下保持了5000ms,就自动调为10 01默认会话。
在代码中,这是诊断服务表数组,存放每一项服务的ID 、对应的函数、会话是否支持、是否支持功能寻址和物理寻址、服务安全访问级别。
注:代码中相应结构体申明如下
诊断会话控制服务用来使能ECU的不同诊断会话,某一特定的诊断会话能够使能ECU内的一组特定的诊断服务和/或功能。 此外,它还可以使能用于启动会话的数据链路层相关的时间参数设置。
不同诊断会话模式之间相互转换的大概流程如下:
注:
1、ECU 内部应(shall) 始终且仅有一个激活的诊断会话。 当上电时,ECU 应(shall) 总是首先启动默认会话。 如果没有启动其它的诊断会话, 那么 ECU 上电后应(shall) 一直处于默认会话模式。
2、非默认会话的保持时间为S3定时器5000ms,超时改定时会自动回到默认会话。
例如:进入编程会话代码段如下:
请求报文格式
报文肯定响应格式
否定响应消息格式
注:
每个服务的否定响应格式是一样的。NRC(否定响应码 如下汇总)
例如:发送报文
肯定响应:06 50 01 00 32 01 F4 AA
否定响应:03 7F 10 Nrc AA AA AA AA
其中:0xAA 是填充数据
Nrc 是对应的否定响应码。
关键参数代码:
以上为整个系统运行时的参数,包括了定时器、会话模式、27服务的种子秘钥、34服务下载地址、等。
同时注意:每个会话之间的切换,根据不同的需求来设计、如有的会将安全等级重新置位。置安全访问状态为请求种子状态、进入10 02 编程会话是否需要预编程、是否经过安全访问等。
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
简介:
该服务提供了一种保护机制,该机制用来保护 因保密、 排放或安全等原因而受到访问限制的诊断服务。
加密策略采用种子和密钥相关联的方法。种子与密钥长度均应为32位(4个字节)。 ECU供应商负责实现产生随机数产生函数,即每次诊断仪请求种子时ECU软件内部就会产生一个随机的种子。 主机厂负责提供一个安全算法给ECU供应商,用来执行诊断仪与ECU之间的安全访问。 该算法描述了如何用某个种子计算得出唯一的密钥。在供应商开发ECU时,安全算法应(shall) 存储在非易失性存储器内。
流程:
肯定响应:
Tester 27 01 请求种子,ECU 67 01 AA BB CC DD 回应种子、
Tester 27 02 发送秘钥,ECU 67 02 回应肯定响应,安全访问解锁。置位安全等级
否定响应:
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
注:
开发时: 每一个项目的安全算法的求 秘钥 是不一样的,安全访问等级也可能不一样,同时要区分在应用程序(App)/引导加载程序(Boot)的安全等级是否一样,求秘钥算法是否一样、同时是否存在种子掩码、安全访问失败延时机制、种子是随机生成的、NRC如何响应13、22、35 、36、37、以及优先级顺序、等等。
关键代码段:
1、请求种子:27 01(对报文长度、是否延时、是否处于相应的安全级别要进行判断等,才会随机生成种子发送给Tester,否则回应NRC码)
ECU生成随机种子,并计算该种子相应的秘钥,等待接下来Tester发送的秘钥进行对比。
2、发送秘钥: Tester发送67 02 aa bb cc dd(秘钥),ECU收到将会进行判断,如果相等则解锁,置相应的安全等级、同时安全访问尝试次数清零。(对报文长度、是否延时、是否请求过种子要进行判断等,才会将Tester发送过来的秘钥进行对比,否则回应NRC码)
ECU对比秘钥: 秘钥正确则解锁,错误则回NRC,并计失败访问次数
NRC的回应机制参考规范。特别是NRC35/36/37在什么情况下回应。
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
简介:
诊断仪使用例程控制服务来完成以下操作:
#2字节:
01 启动一个程序,
02 停止一个程序,
03 请求程序运行结果。
对于子功能参数为启动程序(startRoutine)与停止程序(stopRoutine)的请求消息来说,参数C是否存在是用户可选的。
#3#4字节:该程序由一个2个字节的程序标识符来标识一般为(FF00 擦除内存、FF01 程序一致性校验、0202 程序CRC校验、0203预编程检查)
1、0203预编程检查:
程序更新前要进行车速、电压的检查不满足则禁止更新程序。
报文: 04 31 01 02 03 00 00 00 00
05 71 01 02 03 00 AA AA AA (00 代表通过)
2、0202 CRC校验:
对下载到芯片数据进行检验,将Tester发送过来的CRC32值和ECU自己计算的CRC32值进行对比。并以第五个字节返回校验结果。通过地址和数据长度来进行CRC32校验,校验算法不同厂商给的算法也不同。
报文:
3、FF00 内存擦除:
写Flash之前,要将芯片中的内容擦除,同时将芯片置为可写Flash状态。Flash 擦除中,可以对擦除的地址和长度进行判断,不正确的地址和长度应返回NRC 31。
报文:
3、FF01 一致性校验 (兼容性检查):
简介:经过预编程检查、34/36/37服务之后,CRC校验之后,再执行的一致性校验,这是编程阶段的最后一步,如果这一步不过,之前的努力下载都白费了。简单的来说就是,该项目只能下载该项目对应的应用程序(App),不能下载其他项目的(App),否则一致性检查会失败,同时下载的之前下载的程序作废。
报文:
简介:
在更新应用程序App之前,预编程通过之后,都会先以34服务进行下载请求开始;将要下载的数据块的存储地址(memory-Address)和数据量大小(memory-Size)发送给到ECU端。关于该服务的请求格式如下:
#2 : dataFormatIdentifier/数据格式标识符:
该参数占据1个字节,每个半字节都是单独编码的。该字节的第7 - 4位定义了压缩方法(compressionMethod),第3 - 0位定义了加密方法(encryptingMethod)。该字节数值为00 hex时标明既没有使用压缩方法(compressionMethod)也没有使用加密方法(encryptingMethod)。
#3: addressAndLengthFormatIdentifier/地址与长度格式标识符:
bit 7 - 4: Length (number of bytes) of the memorySize parameter;该字节的第7 - 4位表示内存大小(memorySize)参数的长度(字节数);
bit 3 - 0: Length (number of bytes) of the memoryAddress parameter.
该字节的第3 - 0位表示内存地址(memoryAddress)参数的长度(字节数)。
#4~#7 : memoryAddress/内存地址 要写数据的ECU内存起始地址
#8~#11 : memorySize/内存大小 要写数据的ECU内存大小
响应格式:
代码:
首先进行数据长度、格式、标识的判断,然后保存Tester发送过来的下载地址和下载数据长度进行保存。
接着是设置积极响应格式,下载流程转态变为DL_TRANING36(执行完34,应该执行36服务。)
报文:
诊断仪通过传输数据服务(36 hex)把数据从诊断仪传输到ECU。
请求报文格式:
blockSequenceCounter/数据块序列计数器 :
跟在请求下载(34 hex)或请求上传(35 hex)服务之后的第一次传输数据(36 hex)时,数据块序列计数器(blockSequenceCounter)参数值为01(hex),并且每次传输数据请求之后该数值加1。如果该参数数值已加到FF(hex),那么在下一次传输数据请求时该参数值会重新从0(hex)开始。
代码:
下载之前,对一些异常进行判断,出现异常则直接退出36服务,并返回相应的NRC值。块编号、报文长度、是否是重复块号,电压是否正常等
电压判断:电压大于16.5V 或者小于8.5V,将退出36下载服务。
BlockSize增加量:最先是从01开始,达到0xFF之后,重新以00开始。
下载地址:每一次36,都将会有不同的数据,写入Flash中,得将地址进行偏移。否则将一直在同一块flash中擦写擦写。
将从Tester发送过来的数据写入Flash中去。
报文:
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
建议:参考(10hex)/诊断会话控制、和开发协议。此处略。
说明:
EEPROM地址起始位0x0200 0000;bootloadr在接收到这种地址时采用相应的刷写方式并还原地址;EEPROM用于存放标定数据、和一些指纹数据。Boot需要对这些地址进行处理,当Boot接收到0x0200 0000地址时知道是将其写入EEPROM中去的,故此写入时,必须将地址还原为0x0000 0000。
标定数据存放位置在EEPROM的0x0000到0x0800;共2048Byte。
Boot信息存储位置为EEPROM的0x1000到0x1080;共 128 Byte,(实际使用6Byte)
如下:
#define BOOT_FLAG_MSG 0x1000
#define BOOT_NVM_DADA 0x0000
#define ECU_SUPPLIER_MESSAGE 0x1100
I2C总线是Philips公司开发的二线式串行总线,由SDA、SCL两根线构成,其中SDA是数据线,SCL是时钟线。
SDA、SCL这两根线都是开漏或者集电极开路输出结构,因此在硬件连接时要接上拉电阻。
I2C总线上的器件分为主器件和从器件,二者都既可以作发送器,也可以作接收器。总线状态必须由主器件(通常为单片机)来控制,由主器件产生串行时钟、控制总线方向、产生起始位和停止位信号。
I2C总线在通信过程中共有五种类型信号, 分别是:起始信号、停止信号、应答信号、非应答信号和数据信号。
1、起始信号S:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
2、停止信号P:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
3、应答信号:接收器接收到8bit数据后,向发送器发出特定的低电平脉冲,表示已收到数据;
4、非应答信号:当全部数据接收完毕后,接收器向发送器发出特定的高电平脉冲,随后发停止位,结束接收数据过程。
5、数据:当SCL为高电平时,SDA上信号有效。因此,当SCL为高电平时,数据线必须保持稳定,如有变化,就会被当做起始或停止信号。要更新每一位数据时,必须在SCL为低电平时进行。
例如:发送数据1011时的总线逻辑为:
每传输一位数据,都有一个时钟脉冲相对应。时钟脉冲由主机提供,不必是周期性的,其时钟间隔可以不同。I2C总线上传输的数据和地址字节均为8位,且高位在前,低位在后。
由于总线状态是由单片机控制的,因此I2C上的信号逻辑都需要通过单片机编程实现,方法如下:
发起始信号S:SCL=0 → SDA=1 → SCL=1 → SDA=0 → SCL=0
发停止位P: SCL=0 → SDA=0 → SCL=1→ SDA=1 → SCL=0
发送1位数据:SCL=0 → SDA置1或0 →SCL=1→ SCL=0
接收1位数据:SDA置1(为读线上数据做准备)→ SCL=1并读取SDA线上数据
→ SCL=0
6、单片机从EEPROM读数据流程:
发起始位 → 发器件写地址 → 检查应答位 → 发存储单元地址 → 检查应答位 → 重发起始位 → 发器件读地址 → 检查应答位 → 接收数据 → 发应答位 → …… → 接收完毕,发非应答位 → 发停止位。
7、单片机向EEPROM写数据流程:
发起始位 →发器件写地址 → 检查应答位 → 发存储单元地址 → 检查应答位 → 发数据 → 检查应答位 → …… → 数据发送完毕,发停止位。
几个逻辑信号的软件编程方法函数。
单片机用I/O口模拟I2C总线通信时,需要通过编程先产生I2C总线所需的各种逻辑信号和时钟信号,然后按照I2C总线上数据的读写流程组织程序就可以了。
总线上每一个器件都有一个器件地址(就像电话线网络上,每一个话机都有一个特定的号码),主机通过发地址信息来和需要通信的从机建立联系。
(1)数据传输时
主机先发送启动信号和时钟信号,随后发送地址信息来寻址被控器件,并规定数据传送方向。
(2)从机对地址的响应
当主机发送寻址字节时,总线上所有从机都将其中的高7位地址与自己的地址比较,若相同,再根据读/写位确定自己是作为发送器还是作为接收器。
作为接收器:在寻址字节之后,主机将通过SDA线向从机发送数据,从机每收到一个数据就回一个应答信号。主机数据发送完毕后发送终止信号,结束传送过程。
作为发送器:在寻址字节之后,从机通过SDA线发送数据,主机接收并回应答信号。当主机不愿再接收数据时就回一个非应答信号。并发送终止信号,结束传送过程。
器件类型D7-D4:是I2C总线委员会分配好的,例如:E2PROM是1010;
片选地址D3-D1:由器件的外部引脚A2、A1、A0的接线来确定(总线上同一类型的器件最多只能接8片);
最后一位D0:是数据方向位,1:读;0:写。
注:这里所说的“读”和“写”是站在主机立场上的,读:主机从从机读取数据;写:主机向从机发送数据。
因此,每一个I2C器件实际上有两个地址,一个是写地址,一个是读地址。
器件内部子地址:当器件内部有连续的子地址空间时,对这些空间进行连续读写,子地址会自动加1。
IIC有两种工作模式:快速、慢速。我们使用是慢速。
• 100 kBaud standard mode (PCRH.STIM = 0):
The symbol timing is based on 10 time quanta tq per symbol. A minimum module
clock frequency fSYS = 2 MHz is required.
• 400 kBaud standard mode (PCRH.STIM = 1):
The symbol timing is based on 25 time quanta tq per symbol. A minimum module
clock frequency fSYS = 10 MHz is required.
IIC Master Transmission 逻辑图如下:
开发时,要查芯片手册,查相应的寄存器。配合Dave的使用。
void WriteByteToNVM(unsigned char *i2c_data, unsigned char num_of_bytes, unsigned int base_addr)
通过这个函数将数据写入到NVM中去,参数列表有: 待写入数据的地址,待写入数据的字节数,待写入到NVM中的地址。
void ReadBytesFromNVM(unsigned char *i2c_data, unsigned char num_of_bytes, unsigned int base_addr)
通过这个函数可以将NVM中的数据读取出来,参数列表有:待读取数据出来后存入的地址,待读取数据的字节数,待读取NVM中的地址。
SPI模块用于与辅MCU通讯,波特率为1M,主芯片为主模式,辅芯片为从模式,当擦除地址大于等于0x1C00000时,代表更新辅芯片程序,
如下图:
Spi总体通讯格式,数据总长度设置为16byte:
Spi运行状态:
序号 | 命令类型 | 主MCU ID | 辅MCU ID |
---|---|---|---|
1 | BOOT和APP:通讯同步 | 0x01 | 0x81 |
2 | 请求种子 | 0x07 | 0x87 |
3 | BOOT:请求烧写辅MCU flash数据 | 0x08 | 0x88 |
4 | BOOT:传输烧录辅MCU flash数据 | 0x09 | 0x89 |
5 | 发送秘钥 | 0x0B | 0x8B |
6 | spiJumpToBoot | 0x06 | 0x86 |
7 | subMcuProgramSucceed | 0x0a | 0x8a |
8 | SpiJumpToHW-Test | 0x05 | 0x85 |
注:有其他功能要求再添加。
总体通讯格式,数据总长度设置为16byte:
1byte | 13byte | 1byte | 1byte |
---|---|---|---|
命令ID | 数据区 | 报文计数 | Checksum |
备注:命令ID为主MCU ID或辅MCU ID,出现错误时第二个字节统一是0x00,正确时为0x01。报文计数为0x00~0xFF的循环计数
Checksum = byte1+ byte2+byte3 ……+Byte15
for (u8 i = 0;i < 15;i ++)
{
checkSum = checkSum + spiTransmitMessageMcal[i];
}
1byte | 1byte | 12byte | 1byte | 1byte |
---|---|---|---|---|
命令ID :0x01/ 0x81 | 数据区 | 默认0x00 | 报文计数 | Checksum |
1byte | 1byte | 12byte | 1byte | 1byte |
---|---|---|---|---|
命令ID :0x07 | 0x01:请求种子 | 默认0x00 | 报文计数 | Checksum |
辅:发送种子
1byte | 1byte | 4byte | 8byte | 1byte | 1byte |
---|---|---|---|---|---|
命令ID:0x87 | 0x01:发送种子 | 种子 | 默认0x00 | 报文计数 | Checksum |
主:发送秘钥
1byte | 1byte | 4byte | 8byte | 1byte | 1byte |
---|---|---|---|---|---|
命令ID0x0B | 0x02:发送密钥密钥 | 秘钥 | 默认0x00 | 报文计数 | Checksum |
辅:发送秘钥结果
1byte | 1byte | 12byte | 1byte | 1byte |
---|---|---|---|---|
命令ID 0x8B | 密钥正确 0x00 :密钥错误 0xFF | 默认0x00 | 报文计数 | Checksum |
出现一些如:效数据长度不对,未进行请求烧写,段内帧计数不对,报文计数不对,checksum不对、则回复否定响应。
剩余其他SPI的服务格式大同小异,此处省略。