STM32掉电时存数据到FLASH
cathy 在 提交
cathy 在 提交
关于STM32对内部Flash的保护
为了防止对Flash的非法访问,所有STM32的芯片都提供对Flash的保护,具体分为写保护和读保护。
如果对Flash设置了写保护,那就无法对Flash进行编程和擦除。在开发STM32的时候,如果出现这种情况,通常仿真器都支持对Flash进行解锁,像jlink,stlink等仿真器都支持这个功能。
在使用MDK进行调试的时候,可能会遇到如下图所示的报错信息,这时候就要排查Flash是不是被保护起来了。
读保护即大家通常说的“加密”,是作用于整个Flash存储区域。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:
写保护是以四页(1KB/页) Flash存储区为单位提供写保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志,读与写设置的效果见下表:
当Flash读保护生效时,CPU执行程序可以读受保护的Flash区,但存在两个例外情况:
STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。
Flash保护的相关函数
FLASH_Unlock(); //Flash解锁 FLASH_ReadOutProtection(DISABLE); //Flash读保护禁止 FLASH_ReadOutProtection(ENABLE); //Flash读保护允许
STM32如何设置读保护和解除读保护?
读保护设置后将不能读出Flash中的内容。
如何设置读保护
在程序的开头加入“设置读保护”的代码即可,每次运行代码时都检查一下,如果没有开就打开,如果打开了就跳过。其中,设置读保护的代码如下:
int main(void) { ... if (FLASH_GetReadOutProtectionStatus()!=SET)//检查设置读保护与否 { FLASH_Unlock(); //写保护时可以不用这句话,可用可不用 FLASH_ReadOutProtection(ENABLE); //设置读保护 } ... while(1) { ... } }
上面的代码执行后,使用j-link就不能读出程序了,实现了代码读保护。需要注意的是,芯片读保护后无法再次烧写新的程序到Flash中,必须要解除读保护才可以。但是当解除读保护的时候STM32会自动擦除整个Flash,起到保护数据的作用。
通过代码解除Flash保护
解除读保护可以设置在按键里面,方便实现解锁,也可以设置在命令中。如下是解除读保护代码:
void Off_Protect(void) //关闭保护 { if(FLASH_GetReadOutProtectionStatus() != RESET) { FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用 FLASH_ReadOutProtection(DISABLE); FLASH_Lock(); //上锁 } }
程序中设置一个按键或者命令,可以随时解除Flash的读保护,让芯片又可以重新烧录程序。如果没有留,还可以专门写一个程序,下载到RAM中去运行,用来解除读保护。
注意:执行后,Flash会自动全部擦除。
int main(void) { Chip_Init(); FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用 FLASH_ReadOutProtection(DISABLE); }
通过ST-Link Utility来解除Flash保护
在STLink连接目标板的情况下打开程序烧写软件ST-Link Utility,在菜单栏的Target下选择connect,因为这时候Flash已经被锁住了,能看到如下图所示的错误提示。
下面来操作如何解除Flash保护。
请确保当前已经正确连接了STLink和目标板,在菜单栏Target里打开Option Bytes...选项,发现在这里Read Out Protection选项是Enable,这个表示无法通过SWD读取STM32内部Flash的程序。
将Read Out Protection选项设置为Disable,并点击Apply。
这时候Flash已经成功解锁了,跟上文提到的解除Flash保护的结果一样,内部Flash已经被擦除了,如下图红框中所示。
完成以上步骤之后,在菜单栏Target下选择Disconnect断开与目标板连接。
重新进入MDK,可以正常对目标板烧写程序了。
通过ST-Link Utility来设置Flash保护
在菜单栏Target里打开Option Bytes...选项,可以看到下面有Flash sector protection选项。选择Select all之后,发现所有Page的Protection项都已经变成Write Protection了,只要选择Apply选项就可以对Flash进行写保护,如上图所示。
本文转载自:STM32嵌入式开发
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。
1、前言
单片机内部的FLASH除了存储固件以外,经常将其分成多个区域,用来存储一些参数或存储OTA升级的待更新的固件,这时就会涉及到单片机内部FLASH的编程和擦除操作,STM32不同系列的单片机内部FLASH特性和扇区大小都不太一样,如果不注意这些细节,那就等着爬坑吧
1、FLASH的分区以及扇区大小
FLASH擦除是按照扇区擦的,所以这个很重要,在工程中全局搜索 FLASH_PAGE_SIZE 宏就可以查看该芯片的页(扇区)大小,改宏在 stm32xxx_hal_flash.h中有定义
2、FLASH擦拭后的状态
F1和F4系列的芯片FLASH在擦除后会是0xFFFFFFFF,而L1系列的芯片FLASH在擦除后是0x00000000!!!!!
3、FLASH的编程速度
L1芯片内部FLASH编程速度比F1慢50倍!!!所以在使用L1芯片写入数据时相对于F1慢是正常的
2、STM32 F1、F4、L1系列内部FLASH分区及大小
1、STM32F1系列
对于F1系列的芯片大容量产品的FLASH主存储器每页大小为2K,如【下图】,而中容量和小容量的产品每页大小只有1K
2、STM32F4系列
分为2个Bank,每个Bank分为12个扇区,前4个扇区为16KB大小,第五个扇区是64KB大小,剩下的7个扇区都是128K大小
3、STM32L1系列
3、STM32 F1、F4、L1系列内部FLASH编程时间
信息参考对应芯片的数据手册的 Electrical characteristics 章节
1、STM32F1系列
可以看出F1系列内部FLASH页擦除时间最大为40ms,半字写入的时间为52.2us,比如按字写入1024字节数据,需要26.8ms,还是比较快的
2、STM32F4系列
可以看出F4系列内部不同扇区擦除时间也不一样的,字写入的时间为16us,比如按字写入1024字节数据,只需要4ms,非常快
3、STM32L1系列
可以看出L1系列内部FLASH页擦除和编程的时间都是3.28ms,比如按字写入1024字节数据,需要840ms,非常慢;但是擦除是比较快的
版权声明:本文为CSDN博主 hurryddd 的原创文章,
遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_37845735/article/details/108439644
一.将DSP的Flash里面的函数转移到RAM中
对于独立的嵌入式系统,需要把程序存入non-volitale存储单元中,常用的也就是flash。但是程序在flash中运行相对在RAM中行,速度会变慢很多,具体有多慢,拿28335来说吧,假设系统时钟为150MHz,在RAM中运行时频率还是150MHz,而放在flash中,频率会降到90-95MHz,参照Ti手册SPRA958L,这对于有些对实时性要求较高的函数功能,是不可接受的。所以在系统上电时,把对实时性要求高的函数转移到RAM中去。
下面以initflash函数为例,具体步骤如下:
(1)、将函数定位到section:
#pragma CODE_SECTION(InitFlash, "secureRamFuncs")
当遇到InitFlash(),就到段secureRamFuncs去运行。
当有多个函数需要转移时,重复使用#pragma CODE_SECTION(“函数名", "secureRamFuncs")即可。
即使有多个#pragma CODE_SECTION,后面的步骤只需要一次。
(2)、section分配到memory(红色为memory)。
意思是到FLASH去下载InitFlash(),下载到SECURE_RAM,然后要到SECURE_RAM去运行程序,这个过程给出了下载地址和目标地址。注意此时SECURE_RAM中还没有代码。
1. SECTIONS
2. {
3. /*** User Defined Sections ***/
4. secureRamFuncs: LOAD = FLASH,PAGE = 0
5. RUN =SECURE_RAM, PAGE = 0
6. //定义FLASH和SECURE_RAM的首地址secureRamFuncs_loadstart和secureRamFuncs_loadstart以代替绝对地址
7. LOAD_START(_secureRamFuncs_loadstart),
8. LOAD_SIZE(_secureRamFuncs_loadsize),
9. RUN_START(_secureRamFuncs_runstart),
10. }
(3)、用memcpy()将经过#pragmaCODE_SECTION设定的函数从FLASH弄到SECURE_RAM中去。注意不是将FLASH的东西全部弄到SECURE_RAM中。
1. #include <string.h>
2. //实际应用中这一部分声明可有可无
3. extern unsigned intsecureRamFuncs_loadstart;
4. extern unsigned intsecureRamFuncs_loadsize;
5. extern unsigned intsecureRamFuncs_runstart;
6. void main(void)
7. {
8. /* Copy the secureRamFuncs section */
9. memcpy(&secureRamFuncs_runstart,&secureRamFuncs_loadstart,(Uint32)&secureRamFuncs_loadsize);
10. /* Initialize the on-chip flash registers*/
11. InitFlash();
12. }
二.将MCU的内嵌Flash里的部分代码运行在 RAM 中
MCU 异于资源丰富的linux 平台。MCU(如:基于Cortex V6M 的Cortex M0+ 等) Code通常运行在内嵌Flash中。在某些特定应用场合,需要将部分函数运行于RAM 中。为解决次问题,笔者实现了一种解法,具体做法如下:
1. 实现要运行在RAM的 routine, 本routine 使用纯汇编实现, 如:
__asm void program_word2addr(uint32_t addr, uint32_t data)
{
push {r3, r4, r5, lr} ;save some regsiters
/*your code for this routine*/
pop {r3, r4, r5, pc}
}
2. 编译时,采用code 与运行位置无关的编译选项 如 (Keil --apcs /ropi/rwpi), 生成 *.axf;
3. 通过fromelf -c 将生成 *.axf 反汇编,找到对应program_word2addr 实现部分, 并将routine 对应的binary code Copy 到所要应用的 Code 中,以只读数组的形式出现:
如:
const staic uint16_t s_flashProg2AddressCode[16] = {...., ....}
4. 定义 一个全局数组, 如 static uint16_t g_code[16], size正好等于 s_flashProg2AddressCode的长度;
5. 定义一个函数指针, 如 static void (*callFlashPrg2Address)(uint32_t addr, uint32_t data)
6. 定义一个函数实现将Code 运行与 RAM如:
void run_prgcode_onram(uint32_t addr, uint32_t data)
{
memcpy(g_code,s_flashProg2AddressCode,32 );
callFlashPrg2Address = (void (*)(uint32_t addr, uint32_t data))((uin32_t)g_code + 1);
callFlashPrg2Address (address, data);
}
run_prgcode_onram, 便可以将program_word2addr 运行于RAM中。
callFlashPrg2Address = (void (*)(uint32_t addr, uint32_t data))((uin32_t)g_code + 1); +1 的目的,时由于运行平台为 Cortex V6M , 采用的thumb指令集,根据ARM Spec 要求完成。
callFlashPrg2Address (address, data); 则是实现RAM运行program_word2addr 的关键所在。
本文摘自
https://blog.csdn.net/lansedeyuntkn/article/details/54632541
https://blog.csdn.net/wqzwiseman/article/details/76531653
10月18日,Holtek推出A/D NFC Flash MCU HT45F4050,其最大特点为MCU内建NFC Tag接口,终端产品不须采用MCU加NFC Tag IC的方案,可有效降低零件成本。
HT45F4050 NFC接口RF Data Rate为106 kbit符合NFC Forum Type2及ISO1443 Type A标准,并包含有256 Bytes的NFC EEPROM及64 Bytes的NFC SRAM,可符合NFC Tag应用标准。
HT45F4050另外还包含8K×16程序内存、256×8 RAM、64×8 True EEPROM、12-bit A/D Converter、一组SPI/I2C接口、一个UART接口、4个Timer及一个4-SCOM LCD Driver,提供48LQFP封装,可符合多样应用的需求。
来源:HOLTEK
10月17日,Holtek针对LED Gaming Keyboard应用新推出的Flash MCU HT68FB571,其最大特点为不需外加晶体管,以矩阵扫瞄I/O直推方式,达到同时完成128单色LED及键盘扫瞄。在Gaming Keyboard应用上拥有高性价比。
HT68FB571为单层板PCB安排的MCU脚位,能轻松降低跳线的使用量,具备1.5kHz高扫瞄频率,使LED有极佳的显示效果。HT68FB571的资源包含8K×16程序内存、512×8 RAM、64×8 True EEPROM及SPI×1,提供48LQFP及28SSOP二种封装,可满足单色LED Gaming Keyboard应用的需求。
HT68FB571延续HT66FB5x0 & HT68FB5x0系列特色,支持ISP在线韧体更新。
来源:HOLTEK
芯片的加密,保证了芯片内部信息的安全性。有工程师会问:芯片加密后别人还能解密吗?这芯片安全吗?本文将为大家介绍几种不同类型芯片的加密方式。
随着信息技术的发展,信息的载体——芯片的使用也越来越多了,随之而来的是各个芯片厂商对芯片保密性要求越来越高,用芯片加密的方式来确保芯片内部信息的安全性。其实芯片的安全加密问题与芯片的类型有关,不同类型的芯片加密后有不一样的效果。
市面上现有的芯片种类很多,主要包括Flash,MCU,ARM,DSP,CPLD等。
一、Flash类芯片加密
Flash类芯片包含SPI Nor FLASH ,并行Nor FLASH,NAND FLASH,EMMC等,这些Flash类的芯片都没有非常牢固的加密功能,对code区进行加密后,只能进行写保护,如果有人想复制你的代码,只要读取母片即可,所以这类芯片安全性较低。
将上图所示的信息设置好写入芯片后,对应的区域即进入保护状态,不能编程,擦除,只能通过清空加密寄存器中的信息,才能从新对芯片进行擦除,编程操作。
二、MCU,ARM类芯片加密
经常会有人就MCU加密保护后能否二次使用的问题进行咨询。对于加密后的芯片能不能二次使用这个问题,得具体看是哪个类型的芯片,类似于TI 的MSP430系列芯片加密后即不可进行二次使用,这个加密为OTP(One Time Programmable)型,只能进行一次烧录。其原理是通过高压烧断熔丝,使外部设备再也无法访问芯片,这个是物理性,不可恢复,如要加密,请慎用!
但对于大部分ARM芯片来说,加密后芯片还是可以进行二次使用的。类似于NXP ARM类型芯片有3级可选的加密,即Level 1,Level 2,Level 3。其中Level 1 就是不做读保护级别,即可以读出芯片中的数据,但不能对芯片进行编程,擦除操作。如果芯片被设置为Level 2保护,这种状态下,不能读取芯片内的程序代码内容,也不能对芯片再次做存储空间的擦写或芯片调试了。而Level 3级别的保护是不可逆的,保护后即不能进行其他操作。综上,3个级别当中的Level 1和Level 2加密后还是可以通过解密的方式对芯片进行第二次操作,这种加密等级设置是比较人性化的。下图为P800系列编程器加密设置操作界面。
三、DSP类芯片加密
该类型的芯片加密形式是通过在特定的区域写入客户的密码进行加密。这种加密是可逆的,可以通过输入对的密码进行任何操作。但是有一种方式是不可逆的,即密码为全“0”。其P800系列编程器加密设置窗口如下。
四、CPLD、FPGA类芯片加密
这类芯片加密后一般都可以通过擦除方式进行解密,不能对加密的芯片进行读取操作,这种加密对芯片来说还是比较安全的。
以上便是几种常见类型芯片的加密方式以及加密后的效果,用户可以根据芯片类型选择对应的加密方式,最大程度确保芯片内部信息的安全。
转自:ZLG致远电子 研发部
问题描述:
某客户反馈, 当 MCU 频繁的正常通断电的时候。FLASH 被异常改写,出现各种各样的异常(整片别擦除、中断向量表被改写为 0、写保护被清掉、被加上读保护 ……..)
问题调研:
首先跟客户沟通:
• 他们是延续之前的项目,进行的一些软硬件简单修改。之前的项目没有出现过类似的问题。
• 确认通断电的时间是足够,就是说他们断电后所有的 VDD 都回到 0.上电的时序也是正常。
• 原理图确认这是 follow 了我们的参考设计。
• 测量工作时的电压,只是发觉他们上电时会有一些抖动,其它一切正常。尝试让他们改善上电电路,去掉这一抖动,再次实验,仍然出现类似的问题。
到这里似乎跟硬件没有任何的问题了, 接着让客户代码进行删减又做了如下实验:
1, 去掉能 APP 部分代码,仅仅留下 IAP 代码。做相同的实验,问题再现。
2, 进一步删减程序,客户去掉程序中所有跟 flash 以及 OPTION BYTE 相关的部分,做相同的实验,问题再现。
3, 没招,再删,最后仅仅留下下面程序:
4, 改为标准库中的 systick 例程,去掉写保护,加一个 GPIO 定时翻转程序。同时在烧录之后,加上写保护,做相同的实验,问题再现。
5, 到这里我们都怀疑是芯片真的有损伤了,我们再做了一个实验用 cubemx 生成了一个 GPIO 翻转和 systick 的延时,做相同的实验,问题再现。
从上面规格书来看,如果我们关断 mcu 内部的复位电路,需要在外部接一个复位信号保证 VDD 达到正常工作电压之前一直使 MCU 处于复位状态。
解决办法:
问题找到后解决办法就很简单,去掉 R48 这个 1k 欧姆的电阻,重做实验,再没有发现问题。
结论:
其实在之前我们的另外一个西安的客户发生过频繁上电不工作的情况。他们也是使用了就得数据手册,没有把 PDR_ON 脚拉到 VDD 所致。
对于 ST MCU 来说,这个 PDR_ON 引脚有的封装是被引出来了,有的封装没有引出,如果没有引出的是默认使能内部复位功能,如果引出的话,大家也要当心有的型号是拉低使能内部复位;有得是拉高使能内部复位。所以在检查电路时一定要当心。
来源:www.21ic.com