我遇到了许多项目,其中AVR微控制器与引导加载程序(例如Arduino)一起使用,但是我对这个概念不太了解。
如何制作引导加载程序(对于任何微控制器)?
编写引导加载程序后,如何将其编程到微控制器(就像在AVR的Flash ROM中刻录的任何.hex程序一样,或其他方法)?
我遇到了许多项目,其中AVR微控制器与引导加载程序(例如Arduino)一起使用,但是我对这个概念不太了解。
如何制作引导加载程序(对于任何微控制器)?
编写引导加载程序后,如何将其编程到微控制器(就像在AVR的Flash ROM中刻录的任何.hex程序一样,或其他方法)?
Answers:
引导加载程序是在微控制器中运行的程序,需要进行编程。它通过某种通信方式从外部接收新的程序信息,并将该信息写入处理器的程序存储器。
这与将程序放入微控制器的常规方式形成对比,后者是通过为此目的在微控制器中内置的特殊硬件来实现的。在PIC上,这是类似SPI的接口。如果我没记错的话,AVR使用Jtag,或者至少其中一些使用Jtag。无论哪种方式,这都需要一些外部硬件来摆动编程引脚,以将信息正确地写入程序存储器。描述程序存储器内容的HEX文件起源于一台通用计算机,因此该硬件一侧连接到计算机,另一侧则连接到微型计算机的特殊编程引脚。我公司将PIC程序员作为副业,因此,我对PIC的这一过程非常熟悉。
通过专用硬件进行外部编程的要点是,不管程序存储器的现有内容如何,它都可以工作。微控制器以擦除或处于未知状态的程序存储器开始,因此外部编程是将第一个程序放入微控制器的唯一方法。
如果您对要加载到产品中的程序有确定的把握,并且数量足够大,则可以为您准备制造商或分销商的程序芯片。该芯片像其他任何芯片一样被焊接到板上,并且该单元已准备就绪。例如,这可能适合玩具之类的东西。固件完成后,便完成了很多工作,并将大量生产。
如果您的产品数量较少,或更重要的是,您希望正在进行的固件开发和错误修复,则不希望购买预编程的芯片。在这种情况下,将空白芯片安装在板上,并且在生产过程中必须将固件加载到芯片上。在这种情况下,必须以某种方式使硬件编程线可用。如果您愿意创建生产测试夹具,则可以通过显式连接器或pogo引脚垫进行。通常,此类产品通常都必须进行测试或校准,因此将程序写入处理器的额外成本通常很小。有时,当使用小型处理器时,会先将特殊的生产测试固件加载到处理器中。这用于方便测试和校准设备,然后在已知硬件良好之后才加载实际固件。在这种情况下,存在一些电路设计考虑因素,以允许充分访问编程线以使编程过程能够进行,但又不会给电路带来太多不便。有关更多详细信息,请参见在线编程写操作。
到目前为止,一切都很好,不需要引导加载程序。但是,请考虑您要现场升级甚至允许最终客户升级的具有相对复杂固件的产品。您不能指望最终客户拥有一个程序员小工具,或者即使您提供了一个工具也不会知道如何正确使用它。实际上,我的一位客户这样做。如果您购买了他们的特殊领域自定义选项,那么您将获得我的一名程序员使用该产品。
但是,在大多数情况下,您只希望客户在PC上运行程序并神奇地更新固件。这是引导程序进入的地方,特别是如果您的产品已经具有可轻松与PC进行接口的通信端口,例如USB,RS-232或以太网。客户运行一个PC程序,该程序与Micro中已经存在的引导程序进行对话。这会将新的二进制文件发送到引导加载程序,然后将其写入程序存储器,然后使新代码运行。
听起来很简单,但实际上并非如此,至少如果您希望此过程稳定可靠,那就不是。如果发生通信错误,并且新固件在到达引导加载程序时已损坏,该怎么办?如果在启动过程中电源中断怎么办?如果引导加载程序本身有错误并崩溃,该怎么办?
一个简单的情况是,引导加载程序始终从复位运行。它尝试与主机通信。如果主机做出响应,则它要么告诉引导加载程序它没有新内容,要么发送新代码。随着新代码的到来,旧代码将被覆盖。您始终会在上传的代码中包含一个校验和,以便引导加载程序可以判断新应用是否完好无损。如果不是,它将一直停留在引导加载程序中,并不断请求上载,直到将具有有效校验和的内容加载到内存中为止。对于始终连接的设备,以及可能在响应引导加载程序请求的主机上运行后台任务的设备,这可能是可以接受的。该方案对于很大程度上独立且仅偶尔连接到主机的单元不利。
通常,如上所述的简单引导加载程序是不可接受的,因为没有故障保护功能。如果未完整接收到新的应用程序映像,则您希望设备继续运行旧映像,直到执行成功的上载之前不致失效。因此,固件中通常实际上包含两个特殊模块,即一个上传器和一个引导加载器。上传器是主应用程序的一部分。作为与主机定期通信的一部分,可以上传新的应用程序图像。这需要与主应用程序映像分开的内存,例如外部EEPROM或使用更大的处理器,因此可以将程序存储空间的一半分配给存储新的应用程序映像。上传器仅将接收到的新应用程序映像写入某处,但不运行它。重置处理器后(可能是在上传后根据主机的命令发生),引导加载程序运行。现在这是一个完全独立的程序,不需要外部通讯功能。它比较当前和上载的应用程序版本,检查它们的校验和,如果版本不同并且进行新图像校验和检查,则将新图像复制到应用程序区域。如果新映像已损坏,则只需像以前一样运行旧应用程序即可。
我做了很多引导程序,没有两个是一样的。尽管有些微控制器公司希望您相信,但没有通用的引导加载程序。每个设备在与主机打交道时都有其自己的要求和特殊情况。以下是一些我曾经使用过的引导程序和某些上传程序配置:
由于引导加载程序本身就是包含完整TCP网络堆栈的复杂代码段,因此它也必须可以现场升级。他们这样做的方式是让上传服务器向其提供一个特殊的应用程序,该应用程序的唯一目的是在执行后立即覆盖引导加载程序,然后重置计算机,以便新的引导加载程序运行,这将导致上传服务器发送最新的主应用程序图像。从技术上讲,在短短几毫秒内使用特殊应用程序通过引导加载程序复制新映像的电源故障将是无法恢复的故障。实际上,这从未发生过。我们不太可能这样做,因为这些设备是大型安装的一部分,在这些大型安装中,已经有人负责系统维护,这有时意味着出于其他原因替换嵌入式设备。
希望您可以看到还有许多其他可能性,每种可能性都有自己的权衡,包括风险,速度,成本,易用性,停机时间等。
引导加载程序的概念是什么?
想象一下这种情况:您的微控制器上有大量存储空间-足以存储超过2-3个彼此独立的程序或应用程序。假设当您启动设备时,您可能希望能够选择要运行的设备。那么您需要什么来支持呢?您将需要一个启动程序,然后使您可以在启动时在其他程序之间进行选择。
这个怎么运作?
引导程序就是那个程序-它是要运行的第一件事,它可以将其他应用程序加载到内存中的特定位置(像FLASH这样的持久性文件,或者像RAM这样的易失性文件),然后跳转到所需的程序,然后从那里接管执行。
如何制作AVR引导加载程序(或任何微控制器)?
我从来没有做过引导加载程序,但这就是我想做的事情:像平常一样开始编写固件程序-但请确保将其放在一个区域中,以使其始终是当运行时的第一件事设备启动。在我的脑海中,我想从这个小程序中获得一些功能:能够将新程序上传到内存中的可用位置,擦除先前上传的程序,选择要运行的程序(如果有更多一个),并具有某种存储数据结构(可增长的跳转表?),以便能够记住其他程序所在的位置并跳转到它们。可以通过UART进行交互,它可以为您提供一个非常简单的终端菜单,并可以通过同一通道上传固件。
如何对微控制器进行编程(就像在AVR的ROM上刻录的任何.hex程序一样,或其他方法)?
如果它是一块完全空白的芯片,没有现有的引导加载程序可以自我更新,那么您将需要像使用任何必需的技术(如AVR的ICSP)所描述的那样烧成FLASH。
这绝不是 “引导程序”的全面内容。根据您想要的内容或系统的目的,您可以设计一个内容以将内容上载到RAM中的指定位置而不是FLASH中,然后在任意内存位置开始执行。或者,也许您想要一个能够选择在PC启动时加载哪个操作系统的示例(例如,请参见grub)。用于8位微控制器的Bootloader往往非常简单。
关于Arduino的注意事项:该引导程序仅管理一个程序AFAIK,它还接管串行端口以管理固件上载和其他内容。
“启动”装载机的概念类似于“启动”泵的概念。换句话说,您需要“某种东西”将程序加载到给定地址,然后在该给定地址开始执行程序。那就是引导加载程序。在最简单的情况下,引导加载程序“出现”在CPU的指定起始地址(最有可能为零)上,将程序加载到所需的内存段中,将控制权转移到该内存段,然后“消失”。外观和消失由“外部”硬件控制。一种可能的实现方式是使用通过“硬件”重置激活的ROM,并通过“软件”重置停用的ROM。ROM中的加载程序可以根据需要简单或复杂,并且需要以特定CPU可以理解的二进制形式编写。如果不需要ROM使用的地址空间,则不需要取消ROM。显然,可以使用EEPROM,ePROM,闪存PROM等代替ROM。