0 前言
任何和电子相关的专业的同学,相信在大学期间都会接触到一个非常常用的设备——单片机,但是由于课程时间有限,很多人的学习主要还是为了完成课设任务,而不会去思考或研究其中的一些细节,其中就包括学习单片机的第一步——如何将程序烧录到单片机中?
这个问题说复杂也没有那么复杂,毕竟这只是学习单片机的第一步,主要时间还是花在了对单片机引脚和相关寄存器或库函数上面,对于程序烧录,很多人的看法就是只要会用就行,确实,但是如果程序烧录出现问题呢?或者因为某种原因要换一种烧录方式呢? 这个时候就需要懂一些理论知识了,而且个人认为这个能够帮助使用者对单片机更加了解。于是我找了十多篇教程和文献,汇总到这篇博客中。
个人觉得网上这部分的很多资料都是抄来抄去的,而且很多叫法也不统一,虽然内容很多,但大都是一些重复且价值不大的东西,本文的一个重点在于讲清各种名词和叫法,试图得到一个统一且不冲突的名词概念。
文章目录
1 单片机程序下载方式
由于单片机发展到今天已经非常成熟了,如果我们想要了解程序下载这个一直都有讨论的命题,我觉得可以从其历史发展来看。
1.1 编程器编程
首先需要明确的是,单片机程序下载的本质就是将由0和1组成的二进制文件(hex格式或bin格式)写入到掉电数据不会消失的EEPROM(Electrically Erasable Programmable Read Only Memory,电可擦除可编程只读存储器)中。 最早使用的烧录程序的方式是使用单独的编程器,据说价格比较昂贵,而且每次编程时都需要把可编程芯片取下来放在编程器上,然后再写入程序。【似乎知道为什么现在普遍使用的51单片机最小系统板是用一个夹紧的绿色底座而不是接触更好的双列直插的芯片插座,估计就是历史遗留问题】
这里的编程器是电擦除的,据说更早还有紫外线擦除的,应该是匹配EPROM。
显然,这种烧录程序的方式一个是价格昂贵,意味着你每开发一款芯片,都需要先买一个可能比单片机还贵的编程器;另一方面就是这种编程方式意味着你每改动一次程序都需要拆装一次,不仅麻烦还会对电路板造成损伤,而且如果是成型的产品需要升级程序,还需要返厂或者让技术人员到现场解决,非常不便。于是后来就有了ISP。
1.2 ISP (In System Programming, 系统在线编程)
所谓ISP,即In System Programming,有些人翻译成“在系统中编程”,确实也有道理,因为原来的编程方式需要将芯片取下,即离开系统,而ISP不需要编程器即可完成程序烧录,此时单片机芯片可以焊在电路板上,调试完即是成品。但我比较喜欢另一种解释,那就是用编程器编程属于离线编程,而ISP属于在线编程,这个“线”大概就是指系统,到底有没有离开系统。因此个人觉得这个翻译成系统在线编程最为合适。
ISP基本是目前单片机烧录程序的主要方式。它的实现方式就是通过电脑端的上位机软件,通过某种数据传输协议,将程序编译产生的二进制文件烧录到单片机的EEPROM中。一般电路板上还需要添加少量的外围电路辅助程序的烧录。因此调试单片机程序时,只需要将相关的接口留出即可,而不需要来回取下芯片。
其中,因为对烧录速度和质量的要求,人们在 “某种数据传输协议” 上不断更新,因此也就有了各种不同的烧录方式。如STC的51单片机基于的就是串口协议,即程序通过串口写入到FLASH(EEPROM的一种)中;Atmel的AT89S51,AT89S52等系列单片机基于SPI协议将程序写入到FLASH中;STM32系列的芯片采用ST-Link和J-Link等设备来下载程序,其基于的协议为SWD和JTAG,当然,STM32也可以基于串口协议下载程序;Arduino单片机可以通过串口协议下载程序,也可以通过SPI协议下载(算是AVR单片机一个独有的特点吧)。
但是虽然大家都是ISP,但各自还是有区别的。
其中最为特殊的莫过于串口协议,因为其他的各种协议都是借助外界设备(如ST-Link、USBasp)来直接操作单片机的FLASH,而通过串口下载程序时,虽然也需要使用外部设备(一般是一个USB转TTL模块),但是其本质还是靠芯片内部已固化的一段程序来更新FLASH。
这也就是为什么网上很多资料都把串口下载称之为ISP,而基于其他协议下载的都不叫ISP。
另外,对于某些单片机,支持ISP模式烧写程序的协议可能不止串口协议,或者说不止一个通讯接口。如STM32F4支持多个串口写入和CAN协议【参考链接第二个】
用来写入FLASH的这部分程序是芯片出厂就已经固化到芯片当中的,称为引导程序,也叫自举程序(自己能给自己编程,那不就是自己举起自己嘛),英文名叫BootLoader。这部分程序是对用户保密的,也就是说用户无法知道这段程序到底是怎么写入FLASH的,只知道它能这么做。
因此,为实现这种功能,芯片内部ROM就可以分为两部分,一部分是系统存储区 (System Flash)
,一般在低地址,用来存放引导程序;另一部分是用户存储区(User Flash)
,有些也称为应用程序区(Application Flash)
,一般在高地址,用来存放用户编写的程序(主要执行的部分)。其示意图如下所示。
更正:STM32内部的存储结构实际并不是这样,详细请参考这篇文章
以STM32为例,由于它既支持SWD,JTAG这种直接操作FLASH的协议,也支持基于串口协议利用引导程序写入FLASH,因此它需要支持多种启动模式。如下图所示。
这里的“主闪存存储器”即上面提到的用户存储区,用来存放用户编写的程序。
所以,显而易见,如果手边有ST-Link或J-Link,就可以考虑从用户存储区开始运行,这样上位机就直接将数据写入到用户存储区的FLASH中;如果要采用串口下载,就需要从系统存储区开始启动,当芯片在这个部分开始执行程序时,会不断检测串口是否有写入FLASH的指令,如果有,则开始写入用户存储区的FLASH,如果没有,也无法跳转到用户存储区运行,只能调整BOOT模式再复位。
但是,一般串口下载要更慢,而且ST-Link或J-Link除了下载程序外,还支持硬件仿真,这也就是为什么用串口下载的比较少。
和STM32串口下载类似的还有STC单片机,官方手册对于程序下载的流程介绍如下图所示:
可以看出,和STM32最大的差别在于STC51单片机不存在一个系统存储区的死循环,内置的bootloader和用户程序是先后执行的关系。这样好处很明显,那就是不用选择启动模式;坏处也很明显,那就是每次上电都必须运行这个bootloader,对于上电之后启动速度有较高要求的场景来说就可能会有点问题。
另外,值得注意的是,STC单片机对于从系统存储区启动有一个特别的要求,那就是冷启动,即单片机彻底没电(给2-3V供电也不行)。这个时候上电单片机才会执行ISP程序(一般按下RST单片机不会执行ISP程序,只是从头开始执行用户程序),检测是否有烧入程序的需求。【大概可以理解为上电复位是一种特殊的复位,和按下复位键不同】
如果不想每次下载程序时都要断电,可以买一个免冷启的串口下载模块,其大致原理就是利用串口芯片的流控信号(RTS,DTR)来控制芯片的供电端,比如用MOS管的通断来决定芯片是否通电。
1.3 IAP (In Application Programming,应用在线编程)
说了这么多ISP,感觉基本够用了,为什么还会有IAP呢?这个主要是用于一些特殊的情况,比如一个产品内程序的远程升级。
和上面的ISP一样,IAP也有翻译成“在应用中编程”,这个也有其合理性,但是个人感觉“应用在线编程”会更形象点,这个“线”就不是指系统了,而是指芯片正在执行应用程序,在这个过程中实现程序的自我更新,此即IAP的原理。也正是这种特殊操作,能够实现对一个已开发的产品进行远程的程序升级。
乍一看似乎感觉IAP和ISP(特指串口这种自举方式,后文不再强调)差不多? 确实如此,其原理和上面提到是一样的,那就是内部有一段程序可以实现FLASH中代码的更新。之所以不能直接使用ISP是因为芯片出厂的时候,这部分程序是已固化到芯片当中的,不能修改,而且大概率是不公布细节的。
那IAP到底是怎么实现的呢?虽然说可以自举,但绝对不能更新当前程序所在的Flash,只能是更新其他部分的,逻辑如下所示:
此图和上面那张图一样,都犯了地址大小不分的错误,谨记谨记!
从上图可知,ISP程序引导加载IAP程序,IAP程序引导加载应用程序。在开发者开发产品时,IAP程序必须通过SWD、JTAG或者ISP(串口or其他协议)烧录,第二部分应用程序可以在第一部分烧录时一起烧录,也可以通过IAP程序烧录。
如果IAP程序被破坏,产品必须返厂才能重新烧写程序,这是很麻烦并且非常耗费时间和金钱的。针对这样的需求,可以考虑把IAP程序所在的Flash加上写保护,这样能在一定程度上防止意外破坏(但也没办法避免外部的强行刷机)。
2 其他名词的解释
2.1 ICP
ICP全称是In Circuit Programming
,即在电路中编程,这个我感觉应该是和ISP是一个意思,因为芯片所在的系统不就是电路系统吗?不需要离开电路就能对芯片进行编程,感觉和ISP是一个意思,有些型号的芯片之所以区分这两者估计是使用的协议不同。
2.2 ICSP
ICSP全称是In Circuit Serial Programming
,这个一般的翻译是在线串行编程,这个主要是出现在Arduino中,上面有六个引脚,也可能用来下载程序。其实这个算是AVR单片机的一个特性,其本质是通过SPI协议来写入程序,和AT89S52的烧录方式差不多(虽然一个是10引脚,一个是6引脚)。
但是值得一提的是,Arduino如果采用ICSP的方式烧录程序,那么它还是会从FLASH的起始地址开始烧录,也就是说会覆盖掉低地址段的引导程序!!! 这一点个人感觉很不合理。因此,如果要转为使用串口下载,需要在IDE中再次烧录引导程序。如下图所示。
详细内容可以参考这篇博客 : 【单片机】Arduino进阶应用
2.3 EEPROM和FLASH // 2024.04.29
最近评论区有人纠结EEPROM和FLASH之间的关系,搞得我都不太确定了,遂询问Chat-GPT,所幸我没记错,把截图放上来,供其他人参考。
画重点:FLASH存储器可以看作是EEPROM的一种。
其实我觉得很容易理解,因为最早肯定对单字节擦除有需求,毕竟以前的存储资源是非常紧张的。而且肯定是先有存储芯片,才有上层的操作系统等应用,软件的发展促使了存储芯片读写速度的提升,FLASH,顾名思义,闪存肯定主打就是快。先有慢设备,再有快设备,这才应该是历史发展的规律。
3 参考资料
-
stm32F4 IAP实现原理讲解以及中断向量表的偏移 - CSDN——实践案例,可以多看
有一说一,上面的一些博客提到的一些理论其实就有冲突的地方。。。