采用具有成本效益的I2C/SMBus 接口进行引导加载来简化嵌入式系统开发

2012-03-14 15:04:20 来源:益登科技 点击:2649

摘要:  具有引导加载功能的嵌入式应用提供了可随时更新微控制器(MCU)固件的能力。如果最终固件镜像有错误,或者最终产品组装后需要在MCU上编写固件镜像程序,或者需要现场更新应用程序固件时,这种能力就十分有用了。任何通信协议都可以用于实现引导加载功能,只要MCU能够使用选择的协议进行通信,并且有足够的代码空间存储引导加载程序(bootloader)固件。

关键字:  MCU,  嵌入式,  SCL,  bootloader通信协议

具有引导加载功能的嵌入式应用提供了可随时更新微控制器(MCU)固件的能力。如果最终固件镜像有错误,或者最终产品组装后需要在MCU上编写固件镜像程序,或者需要现场更新应用程序固件时,这种能力就十分有用了。任何通信协议都可以用于实现引导加载功能,只要MCU能够使用选择的协议进行通信,并且有足够的代码空间存储引导加载程序(bootloader)固件。

内部集成电路总线(I2C)或系统管理总线(SMBus)协议通常被用于MCU,因为仅需要两条线进行通信,并可通过少量固件代码实现,所以这些协议成为bootloader的理想选择。已更新的bootloader固件镜像可以由专用MCU或连接到PC机的固定通信功能桥接器发送到目标装置。

让我们来看看嵌入式MCU应用中bootloader的设计原则,以及针对I2C/SMBus的实现技术。首先,我们将介绍一些I2C协议的基础知识,包括硬件和固件的设计思路。

I2C协议与系统内其他集成电路进行通信需要两条信号线:串行数据线(SDA)和串行时钟线(SCL)。这两条双向信号线都需要一个上拉电阻,通常在1K-4.7K欧姆之间,且信号线配置为开漏模式。在这种配置中,主机驱动的信号线被拉低或释放(这将导致外部上拉电阻拉高信号线)。I2C装置是“热插拔”的,意味着装置可以从总线中自由加入或断开。I2C总线被bootloader和系统内其他集成电路共享的特性很有用,例如,嵌入式系统中的两个装置在I2C总线上通信时,外部引导加载装置能够同时连接总线并与MCU通信。

图1 :bootloader通信示例

实现总线共享的一个缺点是总线通信(如图1所示)可能增加引导加载装置所需的时间。其他影响引导加载装置的因素包括Flash页擦除时间、Flash字节编程时间和通信协议速度。 Flash页擦除和字节编程时间是不可改变的参数值,所以bootloader通信协议的时钟频率是重点,他将直接影响发送新固件镜像到目标MCU所需的时间。虽然有些装置可支持高达2 MHz的时钟频率(高速模式),但主流I2C器件一般仅支持最大400 kHz时钟频率(快速模式)。

I2C协议的另一个好处是,假设I2C总线上所有引脚都满足上拉电压容限,那么具有不同I/O电压的装置则可以互相通信,意味着各种装置都可以在同一总线上进行通信。总线上每个装置被预先配置了一个唯一的从机地址,支持与“主”机进行通信。主机发起总线上的所有数据传输,并且可以在同一总线上存在多个主机。该协议采用仲裁机制来解决两个或两个以上主机同时传输的问题,并使用较慢系统时钟频率的装置与较快系统时钟频率的装置进行通信的流量控制方法。从硬件的角度看,只需要装置的两个引脚和两个外部无源器件,使得I2C总线成本降低。

从固件的角度来看,添加I2C引导加载功能到MCU将增加整个应用程序的代码量。固件需要完成以下任务:

· Flash擦除例程

· Flash写入例程

· 轮询模式通信接口的实现

· 中断向量重定向

· 引导加载通信协议

· 引导加载使能引脚

· CRC计算并验证更新的代码镜像

Flash擦除例程需要在引导加载过程中擦除应用程序代码,Flash写例程则写入从目标MCU接受到的字节。为了减少对bootloader应用空间中Flash的损害,两个例程应进行边界检查确保应用程序空间以外的区域不会被擦除或修改。这对于系统非常重要,因为通信接口实现会保存在受保护的引导加载代码区。

装置上的固件用于管理受保护的引导加载区,以免该区域的代码被擦除或修改。虽然也可以选择中断驱动的I2C通信接口,但是轮询模式的I2C通信接口完全可以满足系统的需要,而且设计更简单。如果bootloader代码保存在Flash存储区的最低页面,中断需要重定位到应用代码区。兼容8051 的MCU编译器将生成汇编代码,并在开始的地址0x0003中放置中断向量,或者也可以使用LJMP指令代替。这使得当MCU固件引导加载时,应用固件区域的中断向量能够被更新。

bootloader通信协议需要定义目标MCU和bootloader装置之间通信的字节结构。例如,协议应当规定bootloader装置发送到目标MCU的写命令去启动固件更新。图2显示了一个bootloader装置发送到目标MCU的字节结构示例。

图2: 引导装置发送到目标MCU的字节结构体

总线上传输的第一个字节是目标MCU的I2C地址。目标MCU应答他的I2C地址后,一个引导加载写命令被发送,以告知目标MCU bootloader装置将传来何种数据。接下来,更新代码的起始位置被发送,紧跟着是Flash密钥(如果MCU需要)和更新代码镜像。目标MCU将需要数据缓冲区或者外部数据(xdata)空间存储接收到的字节。当目标MCU从I2C总线上接收到一个字节后,会发送一个应答,通知bootloader装置去发送另一个字节。只要目标MCU缓冲区有空间,这个过程将持续进行。最后,发送循环冗余校验(CRC)验证更新的固件镜像。目标MCU缓冲区满并使用CRC验证有效后,目标MCU开始把缓冲区中的数据写入Flash,同时bootloader MCU应停止发送数据。

图2中,Flash键值由bootloader装置发送到目标MCU,虽然这种方式增加了通信负载量,但比硬编码在目标MCU固件中的Flash键值更安全。如果Flash键值硬编码到目标MCU,目标MCU上Flash失效的几率将增加。Flash写入完成后,目标MCU应答预定义的包给bootloader MCU,通知他可以发送更多字节。bootloader通信协议和I2C固件也需要处理I2C错误,例如仲裁丢失错误或NAK。如果SCL低超时检查功能有效(SMBus规范的超时条件),他也需要由协议和固件处理。bootloader通信协议和固件将处理所有通信错误,但是不处理手动引导加载模式或非法的固件镜像。

要创建引导加载引脚来提供进入引导加载模式的故障安全方法,可通过通用输入/输出(GPIO)引脚实现。例如,如果目标MCU被复位,首先应该检查引导加载使能引脚的状态。根据该引脚状态,固件将进入引导加载模式或应用模式。这提供了一种进入引导加载模式的故障安全方法,并能够用于固件错误恢复。复位后,也会进行CRC或签名检查,以便在运行应用固件以前验证应用镜像的完整性。进入应用模式以前,验证应用镜像的合法性是重要的。如果应用程序的镜像是无效的,在装置上运行的固件可能损害系统。镜像可以通过运行应用空间的CRC或检查代码区特定位置的签名字节来验证。推荐同时使用这两种方式来减少运行无效固件带来的危害。

启动加载过程的最后一个方面是确定如何发送更新的固件到目标MCU。如果选择I2C现的bootloader,通用的MCU或固定功能通信桥接器可以用于bootloader装置。对于通用的MCU,需要开发实现与目标MCU通信的固件。此外,开发人员也需要想办法从计算机传输更新的固件到MCU,这需要更多的代码开发。虽然这种方式提供最大的灵活性,但也需要最多的开发时间。而固定功能的通信桥接器能够替代MCU,且无需固件开发。例如,如果使用HID-to-I2C或HID-to-SMBus通信桥接器,不需要固件开发和驱动安装,但主机侧的HID应用将需要与桥接器通信,发送更新的固件到目标MCU。图3显示了一个使用固定功能通信桥接器的系统示例。

图3:固定功能通信桥接器示例

小结

在任何嵌入式系统中,更新MCU固件的能力为开发人员提供了极大的灵活性。如果应用程序镜像包含错误,或者固件需要在产品组装后更新到MCU中,或者应用程序固件需要现场更新,bootloader将提供一种便捷的开发工具。

I2C或SMBus bootloader对于开发人员来说是极好的选择, I2C和SMBus协议仅需要两条信号线和两个无源外部器件(电阻器),由少量固件来实现。已更新的bootloader固件镜像可以通过独立MCU或连接到计算机的固定功能通信桥接器发送到目标装置。 I2C和SMBus通信接口很经济,并且是MCU上常见的外设,这使得他们成为bootloader通信接口的理想候选。

本文为哔哥哔特资讯原创文章,未经允许和授权,不得转载,否则将严格追究法律责任;
Big-Bit 商务网

请使用微信扫码登陆

x
凌鸥学园天地 广告