STM32单片机学习小Tips之数据的保存和毁灭(2)
和以前学到的有关数据保存不同,这里的数据保存还有“保密”之意,即一旦受到意外的侵入,STM32将毁灭数据。这是通过Tamper机制来实现的。
以下是数据手册中的有关说明:
5.3.1 侵入检测
当TAMPER引脚上的信号从0变成1或者从1变成0(取决于备份控制寄存器 BKP_CR的TPAL位),会产生一个侵入检测事件。侵入检测事件将所有数据备份寄存器内容清除。 然而为了避免丢失侵入事件,侵入检测信号是边沿检测的信号与侵入检测允许位的逻辑与,从而在侵入检测引脚被允许前发生的侵入事件也可以被检测到。
● 当 TPAL=0 时:如果在启动侵入检测TAMPER引脚前(通过设置TPE位)该引脚已经为高电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现上升沿)。
● 当 TPAL=1 时:如果在启动侵入检测引脚TAMPER前(通过设置TPE位)该引脚已经为低电平,一旦启动侵入检测功能,则会产生一个额外的侵入事件(尽管在TPE位置’1’后并没有出现下降沿)。
设置BKP_CSR寄存器的TPIE位为’1’,当检测到侵入事件时就会产生一个中断。
在一个侵入事件被检测到并被清除后,侵入检测引脚TAMPER应该被禁止。然后,在再次写入备份数据寄存器前重新用TPE位启动侵入检测功能。这样,可以阻止软件在侵入检测引脚上仍然有侵入事件时对备份数据寄存器进行写操作。这相当于对侵入引脚TAMPER进行电平检测。
注:当V DD电源断开时,侵入检测功能仍然有效。为了避免不必要的复位数据备份寄存器,TAMPER引脚应该在片外连接到正确的电平。
显然,Tamper需要硬件与之配合。以上数据手册描述了硬件配置时的一些注意事项。
(1) 可以是把引脚由低电平到高电平认为是一次侵入,也可以把引脚从高电平变到低电平认为是一次侵入,这通过TPAL来设置。
(2) Tamper机制需要被启动才能起作用。但在启动之前,如果引脚已处于设定的状态,那么一旦启动,就会产生一次Tamper事件,这需要注意,否则会引起数据的意外丢失而不自觉。
(3) 即便芯片上的VDD电源断开,(只要仍有VBAT),那么Tamper检测仍是有效的,因此,设计硬件时必须要小心,如果某设计是将Tamper引脚通过上拉电阻接VDD,并在这个引脚上接入机械开关到地。如果开关导通,那么就是一次Tamper事件,这个没有问题。但是,如果电源断开(VDD变低),也会引发一次Tamper事件,而这往往并不是设计都的本意。因此,这个引脚的上拉电阻必须接到VBAT而不是接到VDD。
(4) 总的来说,TAMPER并不复杂,下面来看一看代码。
这次是用的STM32库中的这个例子。
有关LED的设置,这里就不再重复了,和上一篇文章(数据的保存与毁灭(1)相同)。
/* Enable write access to Backup domain */
PWR_BackupAccessCmd(ENABLE);
这是打开BKP功能。
/* Clear Tamper pin Event(TE) pending flag */
BKP_ClearFlag();
清除Tamper事件
/* Tamper pin active on low level */
BKP_TamperPinLevelConfig(BKP_TamperPinLevel_Low);
配置Tamper引脚究竟是高电平有效还是低电平有效,这个再研究一下,继续跟踪:
/**
* @brief Configures the Tamper Pin active level.
* @param BKP_TamperPinLevel: specifies the Tamper Pin active level.
* This parameter can be one of the following values:
* @arg BKP_TamperPinLevel_High: Tamper pin active on high level
* @arg BKP_TamperPinLevel_Low: Tamper pin active on low level
* @retval None
*/
void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel)
{
/* Check the parameters */
assert_param(IS_BKP_TAMPER_PIN_LEVEL(BKP_TamperPinLevel));
*(__IO uint32_t *) CR_TPAL_BB = BKP_TamperPinLevel;
}
CR_TPAL_BB又是什么呢?
/* Alias word address of TPAL bit */
#define CR_OFFSET (BKP_OFFSET + 0x30)
#define TPAL_BitNumber 0x01
#define CR_TPAL_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (TPAL_BitNumber * 4))
要看懂上面有关CR_TPAL_BB的相关定义及理解为何这样写,恐怕又要涉及到Contex的另一个重要内容,即bit-band,这个暂不深究,留待下次学习(说句闲话:bit-bank我早就看到,就是没有兴趣深入了解,因为没觉得什么地方有用到,今天既已知其用途,改日必去改看,,,所以只有动起来,才能学更多的东西)。这里只管当它是能够直接设定该平是0或都是1就行了。
即根据实参决定BKP_CR中的TPAL究竟是0还是1。可选参数为:
#define BKP_TamperPinLevel_High ((uint16_t)0x0000)
#define BKP_TamperPinLevel_Low ((uint16_t)0x0001)
BKP的其他用途:
BKP的寄存器可以用来存储RTC校验值的校验寄存器。
在PC13管脚(当该管脚不用于侵入检测时)上输出RTC校准时钟,RTC闹钟脉冲或者秒脉冲
为方便测量,RTC时钟可以经64分频输出到侵入检测引脚TAMPER上。通过设置RTC校验寄存器(BKP_RTCCR)的CCO位来开启这一功能。 通过配置CAL[6:0]位,此时钟可以最多减慢121ppm。
下面以RTC的那个例子为例,来看一看如何用Tamper(PC13)引脚来送出信号。
/* 打开PWR和KBP模块的时钟信号 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/*允许对BKP进行存取*/
PWR_BackupAccessCmd(ENABLE);
/* 禁止引脚的TAMPER功能*/
BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper functionality must be disabled */
/* 允许时钟信号在TAMPER引脚输出*/
BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
这样就可以了,也不复杂。
需要说明的一点是,PC13这个引脚不需要被配置成输出引脚,但在这一时刻它是起到输出作用的。
BKP_RTCOutputConfig()这个函数中所用到的参数可以有这样的一些:
BKP_RTCOutputSource_None
不允许在Tamper引脚输出信号
BKP_RTCOutputSource_CalibClock
在Tamper引脚上输出RTC时钟经64分频后的频率信号
BKP_RTCOutputSource_Alarm
在Tamper引脚上输出RTC报警信号
RTCOutputSource_Second
在Tamper引脚上输出秒信号
经测试,
(1)在Tamper引脚上输出的信号,不受复位的影响!当然,这是有条件的,条件是复位时不会执行到操作RTC的相关代码。
(2) 在用J-LINK写入代码时,Tamper引脚输出的信号,不受影响,照样输出!
(3)断电之后再上电,Tamper引脚送出的信号,不受影响,照样输出!
(4) 去掉VBAT供电端的电力供应,断电,再上电,Tamper引脚送出的信号消失!
判断:前面的程序写的有关标志被保存在BKP区域,不断电不会消失。这是否对电池的寿命有影响呢?毕竟送出波形也会有消耗的。
最后用两个图来结束,分别是运行时的BKP内容和POWER,RESET,CLOCK的内容。
STM32单片机小Tips之玩转IAR,开发STM32
记得本笔记开始时曾说过,我选用keil,理由是keil我熟,而当时我什么都不懂,总要找个熟悉点的东西,并且说过,如果需要用到IAR时,肯定上手也很快。这回要用IAR了,看一看上手究竟快不快啦!
资源列表:
芯片:STM32103VC
库:3.3
JLINK:V8
IAR:5.3
工作目标:编译库中的例子。
工作过程:
(1)文件夹结构
基本上没有变化。
为什么要强调这个呢,这可和设置有很大的关系。
接下来看例子文件
其中上面的那个文件夹中包含了大量的例子,而下面的这个文件夹则包含了几种编译器的工程例子,里面有一些东西是我们需要用到的。
再继续
这次偷了点懒,没有专门为源程序建立一个文件夹,直接把工程文件和源程序文件放在一起了,当然,也有一个因素,是因为使用IAR默认设置就做得相当的“干净”,编译完了后基本上没有多出几个文件出来。要是keil,那可不得了,,,
在iar中用File-》New-》WorkSpace新建一个工作区,然后用Project-》Creat New Project新建一个工程。
起名保存等等吧,这一类的问题就不在这里一一列出了。
总之我们做好了一个名为IOToggle的工程,然后就要将文件加入到工程中去了。
为了便于区分,同样在IOToggle中建立3个组,如下图所示。
将IOToggle文件夹中的所有C文件全部加入到APP组,同时再将
中的stm32_eval.c文件加入这个组中。
在CMSIS组中加入的文件是:
其中core_cm3.c在\Libraries\CMSIS\CM3\CoreSupport文件夹中,system_stm32f10x.c在\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x文件夹中,而startup_stm32f10x_hd.s在\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\iar中。
在LIB文件夹中加入的文件是:
这些文件当然都是3.3库所提供的,在\Libraries\STM32F10x_StdPeriph_Driver\src文件夹中。
至此,文件加入完毕。
从下面开始有两个选择
1.直接使用J-LINK
接下是重要的设置工作。
接下来这里很重要
设定头文件所在位置,这个如果设置不对,编译不能通过。
$PROJ_DIR$\
设定项目所在位置,如果这个没有的话,会找不到stm32f10x_it.h等头文件。
$PROJ_DIR$\。.\。.\。.\。.\Libraries\CMSIS\CM3\CoreSupport
这里的。.\表示的是上级目录的意思(DOS下的东西,曾经是那么的熟悉)
$PROJ_DIR$\。.\。.\。.\。.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
$PROJ_DIR$\。.\。.\。.\。.\Libraries\STM32F10x_StdPeriph_Driver\inc
$PROJ_DIR$\。.\。.\。.\。.\Utilities\STM32_EVAL
其他的都不多说了,如果做其他工程时,目录结构与上面的不相同,那么基于这些知识就能自行修改这些参数了。
在Defined sybols中预设了一个符号,这也是必须的,否则会有大量的编译错误出现。
接下来,在Link中还有一个重要的设置:
需要更改override default的设置,不能使用其默认的设置。
这个EWARMv5在这里:\Project\STM32F10x_StdPeriph_Template\EWARMv5
要选择这个stm32f10x_flash.icf替换掉原来的默认设置,这个其实就是准备向flash中写代码的。
接下来要设置的是Debugger。我们选择
接着切换到Download
这里只要选中Use flash loader即可,不需要做修改。
接着可以到J-Link/J-Trace中去修改,不过,我用的都是默认的参数,没有什么需要修改的。
2.使用RDI
如果不用J-Link,也可使用RDI设置
然后,单击RDI,进入RDI设置
这个红色框中的是需要自己找的,要找到SEGGER的安装目录,并找到这个DLL文件。
接着就会在右下角出现这个
单击RDI,出来对话框
单击Configuration进入设置界面
勾选Enable flash programming,然后选择指定的芯片即可。
至此,IAR基本算是玩起来了。