我们都知道,FLASH 下载次数是有限制的,虽然对一个项目来说,一颗芯片的下载次数完全满足项目的开发要求,但有的开发板会进行很多项目的测试,比如我就有一个开发板,将所有的 I/O 引脚都引了出来,很多功能我都可以通过杜邦线连接来进行测试,相当方便。但也正因为如此,所以几年下来可能会在这个开发板上不知烧写多少次,很可能某一天就把 FLASH 给烧坏了,这样一来芯片就没法用了。你可能会说,不怕,我的焊工好,焊一个芯片分分钟的事情,但是你考虑焊盘的感受吗?焊盘经不起你多少次焊接就可能废了,而且也不是随时随地都有芯片和焊接工具给你焊接啊。所以最好的办法就是使用 RAM 下载功能。
RAM 下载最大的好处就是下载次数无限,所以你可以尽情尝试各种可能,直到成功为止,根本不必考虑烧写次数问题,但是也有一些缺点。
我们知道 STM32 分为 FLASH 和 RAM 两部分空间,本来 RAM 专门用来存放数据的,FLASH 用来放代码和不变的数据,现在好了,所有的代码和数据都挤到了 RAM 中,而 RAM 的空间一般来说不是很大,所以一些大的项目就无法使用 RAM 的方法进行调试的,只能对一些小项目或者功能模块进行测试。而且原来分了两条总线对 FLASH 和 RAM 进行分别访问(哈佛结构),效率高,现在只能通过一条总线(应该是一条总线吧,也可能还是有两条总线同时访问)访问一个目标 RAM,效率可能下降。但这些缺点不是很明显,毕竟下载次数无限的诱惑力还是相当大的。所以有必要新增一个专门用来功能测试的目标,这样你就可以尽情的测试了!
和建立 FLASH 目标一样,不过不同的是现在以 FLASH 作为模板创建新的 RAM 目标,这是因为 FLASH 目标已经具有下载功能了。
现在用图说明比较直观一点:
之前建立的所有的目标都是将代码下载到 FLASH 中(软件仿真时也是如此,只不过它没有将代码下载到真正的单片机中罢了)。现在我们要改变代码存放的位置,即放在 RAM 中,如下图所示:
这样就将 RAM 空间一分为二,既存放代码,亦存放变量。但是我们知道,放在 RAM 中的数据会在掉电之后消失,所以千万保证单片机在调试过程中一直处于供电状态,不过这个条件还是很好满足的。现在说说另外一点,因为代码存放在 RAM 区中,本质上还是变量,所以在使用指针的时候千万要小心,因为一旦指针指向了存放代码的那一块区域,并修改了数据,那么代码运行过程中必然会出现问题(FLASH 还好,因为 FLASH 中的数据改变需要额外的条件支持才能进行数据的修改,但还是要小心指针的使用,虽然不可能改变代码数据,但是可能会改变其他变量的数据)。
那么现在就看如何实现将所有的数据存放在 RAM 中。
同样的,以 STM32F103RET6 为例进行说明。这款单片机有 512 K FLASH 空间,64 K RAM。怎么看对应的芯片的大小呢?
先点击这个图标:
然后就能找到对应的芯片了:
这里的 ROM 就是 FLASH,蓝色字体是一个链接,点击就可以直接进入 ST 官网,里面有这款芯片资源的详细信息。
现在在 FLASH(debug)的基础上建立一个 RAM 目标。
首先设置当前目标为 FLASH(debug):
最后点击 OK 保存该设置,之后再重新打开该界面,新建一个 RAM 目标:
这样目标就新建好了。
现在先确定一下空间的分配问题,一般代码空间要比变量空间大,所以可以设置代码空间为 48 K,即 0x0000 C000,这样变量的空间就是 64 – 48 = 16 K,这样的空间分配作为一般的模块测试是没有问题的,当然如果觉得不够,也可以自己去合理安排空间。
目前空间分配如下:
现在看如何设置这个目标去改变代码的存放位置。
首先通过下面的配置界面进行配置。
这一步就是告诉编译器编译的时候要该如何进行空间分配。
然后再配置这个:
这里注意,Run to main() 不能勾选,否则程序将不能正常运行,不信的话自己去试试看,加深一下印象。
然后需要添加一个文件,文件名可以随意,我这里设置文件名为 RAM.ini,注意后缀为 .ini。文件的内容如下:
这里稍微解释一下,因为所有的数据都存放在 RAM 中了,所以需要重新定位 PC 和 SP 指针(在 FLASH 下载时,默认是从 0x0800 0000 获得 PC 指针和 SP 指针的,所以不需要额外设置这些,但 RAM 不同),在上面的地址分配下,中断向量表定位到了地址 0x2000 0000 开始处,所以要告诉 KEIL,从这里开始获得所需要的数据;同时需要重新定位你的中断向量表(重新定位中断向量也可以通过程序代码去实现,不必在 .ini 中配置),就是通过修改寄存器 0xE000 ED08 实现的。有关中断向量表的内容可以参考《M3 权威手册》
最后关键的一点是要根据你的路径和文件名加载你的 .axf 文件,这个文件名可以通过搜索工程路径下的 .axf 文件进行确定,也可以通过以下方式确定:
如果你的路径有问题的话,那么将在输出框输出如下信息:
但是发现即使如此还是能进行仿真,后面再好好研究一下为什么吧。
然后再进行最后一步:
如果这个勾选了,会出现如下错误:
大功告成!现在你可以试试用这个图标下载代码并进入调试模式:
注意不能用下载图标进行下载:
这个下载图标是用来下载到 FLASH 的。而上面的图标既可以下载,也可以进入调试模式,所以如果你要进入调试模式的话,直接点上面的图标就可以了,不必先下载代码之后再进入调试模式。
还有关于网上的一些参考文章,发现有多余的步骤,所以如果你想实现 RAM 下载的话,这篇教程还是比较简单的。
需要注意一点的就是,因为所有的代码都是下载在 RAM 中的,所以不能使用复位按钮,因为一旦进行复位,那么程序就会跳转到 FLASH 区(地址 0x0800 0000 开始处)进行执行,导致无法再执行到 RAM 中的程序里面,所以暂时不能使用复位按钮,但是这个问题是可以解决的;还有一点,在使用 uCOS II 操作系统时,发现也会出现问题,但是裸机情况下按照如上配置是没有问题的。
这两个问题后期会一并处理。
多目标工程建立的一点补充:
之前建立多目标的时候,并没有为每一个目标设置对应的输出文件,所以为了防止多目标之间出现文件冲突,为它们单独设置了输出文件位置(如果不想折腾,还是别增加文件夹了,可能会出现一些问题,比如文件夹改变后文件的路径也要做相应改变)。
在工程目录新建如下文件夹:
然后为每一个目标设置对应的文件夹,比如设置 RAM 目标的文件输出位置:
注意设置时必须进入文件内部才行,如下:
同理设置 Listting 文件的输出路径:
最后点击 OK 即可保存设置。