深入理解嵌入式开发中的Flash、RAM和ROM(第10部分)

目录

  • 一、存储器
  • 二、分类
  • 1. RAM
  • (1)SRAM
  • (2) DRAM
  • 2. ROM
  • (1)EPROM
  • (2)EEPROM
  • 3. Flash
  • 三、内部Flash(嵌入式Flash)
  • 1.主要特性
  • 2.擦除和编程操作
  • 3.编程/擦除位数与电压之间的关系
  • 4.单位
  • 四、编程细节
  • 拓展:栈存储
  • 代码
  • 总结
  • 我们经常看到一个开发板写着FLASH多少kb或者1MB/2MB,但是这个flash又有什么用?

    一、存储器

    存储器系统结构
    程序存储器、数据存储器、寄存器和 I/O 端口排列在同一个顺序的 4 GB 地址空间内。各字节按小端格式在存储器中编码。字中编号最低的字节被视为该字的最低有效字节,而编号最高的字节被视为最高有效字节。

    主要特性:
    1. 4GB线性地址空间。 可寻址的存储空间分为 8 个主要块,每个块为 512 MB。共为 4GB,且以 32位寻址,未分配给片上存储器和外设的所有存储区域均视为“保留区”。

    2. 位段访问( 可选)。SRAM和外设空间中存在两个可位寻址的区域,通过位段别名地址。

    3. 支持 32位、16位和8位数据的高效传输。

    4. 架构定义的存储器映射。
    4GB的存储器空间被划分为多个区域, 用于预定义的存储器和外设,以优化处理器设计的性能。例如,Cortex-M3和CortexM4处理器具有多个总线接口,允许对程序代码用的CODE区域的访问和对SRAM或外设区域的数据操作同时进行。
    ● 程序代码的问(如CODE区域)
    ● 数据访问(如SRAM区域)
    ● 外设(如外设区域)
    ● 处理器的内部控制和调试部件(如私有外设总线)

    5. 支持小端和大端的存储器系统。
    可以使用小端或大端的存储器系统。实际上,微控制器产品一般会被设计成只具有一种端配置。对于小端的存储器系统,字大小数据的第一个字节位于32位存储器位置的最低字节处。类似于大端序、小端序。

    6. 写缓冲。
    写缓冲可能会将本次传输缓存起来,处理器可以继续执行下一条指令,如果可能的话,这样可以提高程序的执行速度。

    7. 存储器保护单元(MPU)。
    MPU为监控总线传输的可编程设备,需要通过软件( 一般是嵌入式OS)配置。若MPU存在,应用程序可以将存储器空间分为多个部分,并为每个部分定义访问权限。当违反访问规则时,错误异常就会产生,错误异常处理则会分析问题,而且如果可能,将错误加以修复。

    8. 非对齐传输支持。
    由于存储器系统为32位的(至少从编程模型的角度来看是这样的),大小为32位(4 字节,或) 或16位(2 字节,或半字)可以是对齐也可以是不对齐的。对齐传输的意思是地址值为大小(以字节为单位)的整数倍。例如,字大小的对齐传输可以执行的地址为0x00000000x00000004、…、0x000010000x00001004等;类似地,半字大小的对齐传输可以执行的地址则为0x00000000000x00000002、…、0x0000l0000x00001002等。

    二、分类

    1. RAM

    随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。

    (1)SRAM

    SRAM 全称 Static Random-Access Memory,中文译为静态随机存取存储器。所谓“静态”,即只要保持通电(计算机处于开启状态),SRAM 就可以保证每个比特位的数值(0 或者 1)不发生变化,从而一直存储这些数据。

    SRAM 主要由晶体管构成,SRAM 中的每 1 个比特位都通常要用 6 个 CMOS 晶体管(再配以其它一些零件,但没有电容器)组合实现。这样的六晶体管配置,使得 SRAM 具备以下的特点:
    和 DRAM 相比,SRAM 存储 1 比特位所需的部件更多,因此它的体积更大。和具备等量存储空间的 DRAM 相比,SRAM 需要占用更大的电路板空间;而同体积的 DRAM 和 SRAM 相比,SRAM 提供的内存空间也就更少。
    同样和 DRAM 比,SRAM 读写效率更高,因为 SRAM 支持立即对每个比特位做读、写操作,而无需等待电容器充满电或者完全释放后再做对应的操作。同时,CPU 访问 SRAM 的时间更快(可以低至 10 纳秒),而且两次访问操作可以连续执行,中间不需要暂停。

    基于这样的特性,SRAM 通常用来做计算机的寄存器、高速缓存以及显卡上的帧缓存区。

    系统 SRAM 可按字节、半字(16 位)或全字(32 位)访问。读写操作以 CPU 速度执行, 且等待周期为 0。系统 SRAM 分为三个块:
    ● 映射在地址 0x2000 0000 的 112 KB 和 16 KB 块,可供所有 AHB 主控总线访问。
    ● 映射在地址 0x2002 0000 的 64 KB 块,可供所有 AHB 主控总线访问。(适用于 STM32F42xxx 和 STM32F43xxx)。AHB 主总线支持并发 SRAM 访问(通过以太网或 USB OTG HS):例如,当 CPU 对 112 KB 或 64 KB SRAM 进行读/写操作时,以太网 MAC 可以同时对 16 KB SRAM 进行读/写操作。
    ● 在地址 0x1000 0000 映射的 64 KB 块,只能供 CPU 通过数据总线访问。

    (2) DRAM

    DRAM,全称 Dynamic Random Access Memory,中文译为动态随机存取存储器。

    该存储器本质是一个集成电路,内部包含数百万个尺寸非常小的晶体管和电容器。在电路板上,每个晶体管都和一个电容器对齐摆放,整体构成 1 个比特位,其中电容器充满电表示存储 1,无电表示存储 0;晶体管则充当开关的角色,它允许电路板读取或者修改当前电容器的状态。

    DRAM 这种组织结构存在的最大问题是,即便晶体管处于关闭状态,它也会存在漏电的现象,从而导致相连电容器中的电量减少,存储的数据也相继丢失。因此,DRAM 必须定时刷新各电容器中的电量,才能保证存储的数据不会丢失,这也是它称为“动态 RAM”的原因。

    2. ROM

    我们正常编译生成的二进制文件,需要下载烧录到单片机里面去,这个文件保存在单片机的ROM中,ROM这个名称指的是「read only memory」的意思,所有可以完成「read only memory」这种特性的存储介质都可以称为ROM。
    一般可以分为四大类:
    (1)PROM (Programmable Read-Only Memory),可编程只读存储器,也叫One-Time Programmable (OTP) ROM“一次可编程只读存储器”,是一种可以用程,只可以擦写一次,是一次性的,软件输入后,无法修改,例如芯片的全球唯一ID码。
    (2)EPROM (Erasable Programmable Read-Only Memory),可擦除可编程只读存储器,一旦编程完成后,EPROM只能用强紫外线照射来擦除。
    (3)EEPROM (Electrically Erasable Programmable read only memory)是指带电可擦可编程只读存储器。是一种掉电后数据不丢失的存储芯片。

    (1)EPROM

    电擦除和紫外线擦除是两种不同的擦除方式,我现在知道用紫外线擦除的ROMEPROM

    EPROM是一种具有可擦除功能,擦除后即可进行再编程的ROM内存,写入前必须先把里面的内容用紫外线照射它的IC卡上的透明视窗的方式来清除掉。这一类芯片比较容易识别,其封装中包含有“石英玻璃窗”,一个编程后的EPROM芯片的“石英玻璃窗”一般使用黑色不干胶纸盖住, 以防止遭到阳光直射。EPROM内资料的写入要用专用的编程器,并且往芯片中写内容时必须要加一定的编程电压(VPP=12~24V,随不同的芯片型号而定)。

    EPROM的型号是以27开头的,如27C020(8*256K)是一片2M Bits容量的EPROM芯片。EPROM芯片在写入资料后,还要以不透光的贴纸或胶布把窗口封住,以免受到周围的紫外线照射而使资料受损。

    (2)EEPROM

    EEPROM拯救了这一切?
    EEPROM的全称是「电可擦除可编程只读存储器」,即Electrically Erasable Programmable Read-Only Memory。EEPROM的出现可以说是跨时代的,因为ROM可以多次编程了,对于程序员来说,终于可以多次烧写单片机了,更让我们兴奋的是,我们可以使用电擦除,而不是紫外线擦除了。
    从擦除次数上,EEPROM可以擦除100W次,而且EEPROM可以针对每一个区块,也就是每一个位置写 「0」或者 写 「1」,如果大家知道FLASH特性的话,就会觉得EEPROM是多么优秀。而且数据的保存时间可以达到100年。
    当然了,特点就是电路复杂,成本高,因为成本高就导致了EEPROM的大小不是非常大,一般在512KB 以下。

    3. Flash

    FLASH,可以擦写多次,按扇区/块擦除
    我们一般使用的单片机里面使用的是EEPROME2PROM),STM32则使用FLASH

    如果从电擦除这个特性上说的话,FLASH也是EEPROM的一种,不同的是,FLASH的擦除区块不是一个字节,而是扇区来擦除,也是因为这样的特性,才导致FLASH价格比EEPROM便宜。

    闪存(Flash Memory)是一种长寿命的非易失性(在断电情况下仍能保持所存储的数据信息)的存储器。用途SD卡、固态硬盘、芯片内存存储单元存储代码。

    三、内部Flash(嵌入式Flash)

    Flash 接口可管理 CPU 通过 AHB I-CodeD-Code 对 Flash 进行的访问。该接口可针对 Flash 执行擦除和编程操作,并实施读写保护机制。Flash 接口通过指令预取和缓存机制加速代码执行。

    1.主要特性

    (1)嵌入式 Flash
    Flash 具有以下主要特性:
    ● 对于 STM32F40x 和 STM32F41x,容量高达 1 MB;对于 STM32F42x 和 STM32F43x, 容量高达 2 MB
    128 位宽数据读取
    ● 字节、半字、字和双字数据写入。

    注意:
    字节写入优点:字符或字符串的访问。缺点:速度慢 。
    字写入优点:32位数据访问,速度快。缺点:不太适合字符或字符串的访问。

    ● 扇区擦除与全部擦除

    注意: 扇区擦除类似计算机的分区格式化,全部擦除类似硬件盘格式化

    名称 块基址 大小
    主存储器 扇区0 0x0800 0000 – 0x0800 3FFF 16 KB
    扇区0 0x0800 0000 – 0x0800 3FFF 16 KB
    扇区1 0x0800 4000 – 0x0800 7FFF 16 KB
    扇区2 00×0800 8000 – 0x0800 BFFF 16 KB
    扇区3 0x0800 C000 – 0x0800 FFFF 16 KB
    扇区4 0x0801 0000 – 0x0801 FFFF 64 KB
    扇区5 0x0802 0000 – 0x0803 FFFF 128KB
    扇区6 0x0804 0000 – 0x0805 FFFF 128KB
    扇区11 0x080E 0000 – 0x080F FFFF 128KB
    系统存储区域 0x1FFF 0000 – 0x1FFF 77FF 30KB
    OPT区域 0x1FFF 7800 – 0x1FFF 7A0F 528KB
    选项字节 0x1FFF C000 – 0x1FFF C00F 16KB

    例如:扇区FLASH写入的位置可以对应——》》》》|扇区0 | 0x0800 0000 - 0x0800 3FFF | 16 KB

    与EEPROM的区别:

    EEPROM能够单独修改某个字节,但是Flash想要修改,只能先擦除,再编程写入


    不同芯片flash大小,会有不同的扇区数量。
    ● 存储器组织结构
    Flash 结构如下:
    — 主存储器块,分为 4 个 16 KB 扇区、1 个 64 KB 扇区和 7 个 128 KB 扇区
    — 系统存储器,器件在系统存储器自举模式下从该存储器启动
    — 512 字节 OTP(一次性可编程),用于存储用户数据OTP 区域还有 16 个额外字节,用于锁定对应的 OTP 数据块。
    — 选项字节,用于配置读写保护、BOR 级别、软件/硬件看门狗以及器件处于待机或 停止模式下的复位。

    ● 低功耗模式(“电源控制 PWR)”部分

    (2)操作技巧

    操作步骤:找到扇区、擦除扇区、根据需要,编程写入数据


    Flash编程 般以数据块为单位。 调试器将Flash编程算法代码和程序映像块下载到RAM中,然后执行Flash编程代码,这样处理器自己就可以进行Flash编程操作。 由于 SRAM每次只能存放一小块程序映像,要将整个程序映像写到Flash中需要多次重复整个步骤。

    2.擦除和编程操作

    执行任何 Flash 编程操作(擦除或编程)时,CPU 时钟频率 (HCLK) 不能低于 1 MHz。如果 在 Flash 操作期间发生器件复位,无法保证 Flash 中的内容。在对 STM32F4xx 的 Flash 执行写入或擦除操作期间,任何读取 Flash 的尝试都会导致总线 阻塞。只有在完成编程操作后,才能正确处理读操作。这意味着,写/擦除操作进行期间不能从 Flash 中执行代码或数据获取操作。

    3.编程/擦除位数与电压之间的关系

    电压范围 2.7 – 3.6 V(使用外部 VPP) 电压范围2.7 – 3.6 V 电压范围2.4 – 2.7 V 电压范围2.1 – 2.4 V 电压范围1.8 V – 2.1 V
    并行位数 x64 x32 x16 x16 x8
    PSIZE(1:0) 11 10 01 01 00

    注意:
    如果在编程并行位数/电压范围设置不一致的情况下启动任何编程或擦除操作,可能会导致出现意外结果。即使后续的读操作指示逻辑值已有效写入存储器中,也无法确定写入操作确实成功。
    要使用 VPP,必须在 VPP 引脚施加一个外部高压电源(8 V 到 9 V 之间)。该外部电源必须在直流电耗超过 10 mA 时也能维持该电压范围。建议仅在工厂生产线上进行初始编程时使用VPP。VPP 电源的供电时间不得超过一小时,否则 Flash 可能会损坏。

    4.单位

     字节:8位
     半字:16位
     字:32位
     双字:64位
    
     uint32_t i;
     uint64_t i;
    
     word i;
    dword i;
    

    四、编程细节

    1.以分区形式进行规划,配置数据最好从最后扇区进行操作,防止覆盖扇区0的代码。

    2.写入数据之前得先擦除数据,类似与读书时的黑板原理。

    思考1:擦除完之后,扇区里面所有的数据是什么?
    答:所有的数据都是为0xFF,所有bit位都是1。

    思考2:假如说现在已经擦除完扇区,先写入了1个字,然后在下一个偏移地址再次写入新的字是否在需要擦除扇区?
    答案:不需要的。

    思考3:假如说现在已经擦除完扇区,先写了1个字,然后在同一个地址再次写入新的字是否需要擦除扇区?
    答案:需要进行擦除!

    例子,已经写入数据为0x12345678,然后再写入新的数据为0x1111111,最后得到的数据居然是0x101010.

    总结:
    判断是否允许写入字,只需要判断当前的地址存储的数据是否为0xFFFFFFFF,若为0xFFFFFFFF,可以写入数据,不需要进行扇区擦除。

    拓展:栈存储

    同几乎所有的处理器架构一样,Cortex M处理器在运行时需要枝存储和措指针(Rl3)。在枝这种存储器使用机制中,存储器的一部分可被用作后进先出的数据存储缓冲。ARM处理器将系统主存储器用于找空间操作。 详细理解原理:栈、堆内存

    ● 当正在执行的函数需要使用寄存器(寄存器组中)进行数据处理时,临时存储数据的初 始值。 这些数据在函数结束时’可以被恢复出来,以免调用函数的程序丢失数据。
    ● 往函数或子程序中的信息传递。
    ● 用于存储局部变量。
    ● 在中断等异常产生时保存处理器状态和寄存器数值。
    Cortex M处理器使用的战模型被称作“满递减”。处理器启动后,SP被设置为战存储空间最后的位置。 对于每次PUSH操作,处理器首先减小 SP的值,然后将数据存储在 SP指向 的存储器位置。 在操作期间,SP指向上一次数据被存储在校中的位置。
    对于POP操作,SP指向的存储器位置的数据被i卖出,然后 SP的数值会自动减小。PUSH和POP指令最常见的用法为,在执行函数或子程序调用时保存寄存器组中的内容。 在函数调用开始时,有些寄存器的内容可以通过PUSH指令保存在楼中,而后在函数调 用结束时通过POP恢复为它们的初始值。

    例如:

    寄存器中的数值稍后还会被主程序用到,因此,它们就被PUSH保存到楼中,且在functionl结束时被POP恢复。 这样,调用函数的程序代码不会丢失任何数据而且可以继续执行。 注意,对于每次PUSH操作 (保存到存储器 ),都会有一个对应的POP(从存储器中读取),而且POP操作的地址应该和PUSH的一致。

    每个PUSH和POP指令都可以往/从横空间传输多个数据,如图4.21所示。由于寄存器组中的寄存器都是32位的,每个由战PUSH和POP生成的存储器传输都会访问至少一个字(4字节)的数据,而且地址总是对齐到4字节边界上,SP的最低两位也总是为0。
    可以将函数返回和POP操作结合起来,首先,把LRCR14)的数值压到枝存储中,在子程序/函数结束时将其恢复到PC(Rl日
    Cortex-M处理器在物理上存在两个枝指针。它们为:
    ● 主战指针(MSP)。 复位后默认使用的枝指针,用于所有的异常处理。
    ● 进程枝指针(PSP)。 只能用于线程模式的技指针,通常用于运行嵌入式 OS 的嵌入式系统中的应用任务。

    在寄存器中当位SPSEL的数值,若该位为0,则线程模式 在校操作时使用MSP,否则线程模式使用PSP。
    在异常事件产生后,处理器在进入中断服务程序CISR)前会首先将多个寄存器压人战中,这种寄存器状态保存操作被称作“ 压战”,而在JSR结束时,这些寄存器又会被恢复到寄存器组中,这种操作则被称作“出拢” 。

    一般来说,在C函数中修改当前选定的SP的方式是不为我们所提倡的,这是因为栈存储中的某部分可能会被用于存储局部变量或其他数据。 要在汇编代码中访问MSP和PSP ,可以使用MSR和MRS指令:

    MRS R0, MSP;//将主战指针读人R0 
    MSR MSP, R0;//将R0写入主战指针
    MRS R0, PSP;//将进程找指针读人R0
    MSR PSP, R0;//将R0写人进程技指针
    

    代码

    proj1_写入读取FLASH

    #include <stm32f4xx.h>
    #include <string.h>
    #include <stdio.h>
    
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    #include "delay.h"
    #include "usart.h"
    #include "rtc.h"
    
    int main()
    {
    	char usart1_buf[50];
    	
    	// 中断优先级2组:4级抢占优先级,支持4级响应优先级
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    	
    	LED_Init();		// 初始化4个LED
    	BEEP_Init();	// 初始化蜂鸣器
    	KEY_EXTI_Init();		// 初始化按键(外部中断)
    	USART1_Config(115200);	// 串口1配置
    	
    	usart1_send_str("This is FLASH test~\r\n");
    
    	
    	
    	
    	
    	/* 1.打开FLASH写访问 */
    	FLASH_Unlock();
    
    	/* 2.清空标志位 */  
    	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
    					FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); 
    
    	/********************** 3.擦除扇区4 ******************/
    	if(FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3) != FLASH_COMPLETE)
    	{
    		usart1_send_str("FLASH_EraseSector failed!\r\n");
    		
    		/* 擦除出错 */
    		while (1);
    	}
    	
    	/********************** 4.写入数据 ******************/
    	if(FLASH_ProgramWord(0x08010000, 0x12345678) != FLASH_COMPLETE)
    	{ 
    		usart1_send_str("FLASH_ProgramWord failed!\r\n");
    		
    		/* 写入出错 */
    		while (1);
    	}
    	/* 5.关闭写访问 */
    	FLASH_Lock(); 
    
    	// 6.读取刚写入的数据
    	volatile uint32_t uwData32 = 0;
    
    	uwData32 = *(volatile uint32_t*)0x08010000;
    	
    	memset(usart1_buf, 0, sizeof(usart1_buf));
    	sprintf(usart1_buf, "Get: 0x%X\r\n", uwData32);
    	usart1_send_str(usart1_buf);
    	
    	
    	
    	
    	while(1)
    	{
    		
    	}
    }
    

    proj2_连续写入64字

    #include <stm32f4xx.h>
    #include <string.h>
    #include <stdio.h>
    
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    #include "delay.h"
    #include "usart.h"
    #include "rtc.h"
    
    int main()
    {
    	uint8_t i;
    	
    	char usart1_buf[50];
    	
    	// 中断优先级2组:4级抢占优先级,支持4级响应优先级
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    	
    	LED_Init();		// 初始化4个LED
    	BEEP_Init();	// 初始化蜂鸣器
    	KEY_EXTI_Init();		// 初始化按键(外部中断)
    	USART1_Config(115200);	// 串口1配置
    	
    	usart1_send_str("This is FLASH test~\r\n");
    
    	
    	
    	
    	
    	/* 1.打开FLASH写访问 */
    	FLASH_Unlock();
    
    	/* 2.清空标志位 */  
    	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
    					FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); 
    
    	/********************** 3.擦除扇区4 ******************/
    	if(FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3) != FLASH_COMPLETE)
    	{
    		usart1_send_str("FLASH_EraseSector failed!\r\n");
    		
    		/* 擦除出错 */
    		while (1);
    	}
    	
    	/********************** 4.写入数据 ******************/
    	for(i=0; i<64; i++)	// 0~63
    	{
    		if(FLASH_ProgramWord(0x08010000+4*i, i) != FLASH_COMPLETE)
    		{
    			usart1_send_str("FLASH_ProgramWord failed!\r\n");
    			
    			/* 写入出错 */
    			while (1);
    		}
    	}
    
    	/* 5.关闭写访问 */
    	FLASH_Lock(); 
    
    	
    	
    	// 6.读取刚写入的数据
    		// 指针指向扇区4的首地址
    	volatile uint32_t *p_data = (volatile uint32_t*)0x08010000;
    	
    	for(i=0; i<64; i++)	// 0~63
    	{
    		memset(usart1_buf, 0, sizeof(usart1_buf));
    		sprintf(usart1_buf, "%d ", *(p_data+i));
    		usart1_send_str(usart1_buf);
    	}
    	usart1_send_str("\r\n");
    	
    	
    	while(1)
    	{
    		
    	}
    }
    

    proj3_扇区操作验证(擦除后为0xFFFFFFFF)

    #include <stm32f4xx.h>
    #include <string.h>
    #include <stdio.h>
    
    #include "led.h"
    #include "beep.h"
    #include "key.h"
    #include "delay.h"
    #include "usart.h"
    #include "rtc.h"
    
    int main()
    {
    	uint8_t i;
    	char usart1_buf[50];
    	
    	// 中断优先级2组:4级抢占优先级,支持4级响应优先级
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    	
    	LED_Init();		// 初始化4个LED
    	BEEP_Init();	// 初始化蜂鸣器
    	KEY_EXTI_Init();		// 初始化按键(外部中断)
    	USART1_Config(115200);	// 串口1配置
    	
    	usart1_send_str("This is FLASH test~\r\n");
    	
    	/* 1.打开FLASH写访问 */
    	FLASH_Unlock();
    
    	/* 2.清空标志位 */  
    	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | 
    					FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR); 
    
    	/********************** 3.擦除扇区4 ******************/
    	if(FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3) != FLASH_COMPLETE)
    	{
    		usart1_send_str("FLASH_EraseSector failed!\r\n");
    		
    		/* 擦除出错 */
    		while (1);
    	}
    	
    	/* 5.关闭写访问 */
    	FLASH_Lock(); 
    
    	// 6.读取刚写入的数据
    		// 指针指向扇区4的首地址
    	volatile uint32_t *p_data = (volatile uint32_t*)0x08010000;
    	
    	for(i=0; i<10; i++)
    	{
    		memset(usart1_buf, 0, sizeof(usart1_buf));
    		sprintf(usart1_buf, "0x%X\r\n", *(p_data+i));
    		usart1_send_str(usart1_buf);
    	}
    	
    	
    	while(1)
    	{
    		
    	}
    }
    

    源码:
    链接:https://pan.baidu.com/s/1VIsBe2ZPrDTpTjfHj1sgkw
    提取码:baba

    总结

    Cortex-M3和Cortex M4处理器本身并不包含存储器(没有程序存储器、SRAM或缓 存),它们具有通用的片上总线接口,因此,微控制器供应商可以将它们自己的存储器系统添加 到系统中。 一般来说,微控制器供应商需要将下面的部件添加到存储器系统中:
    (1)程序存储器, 一 般是Flash。
    (2)数据存储器, 一般是SRAM。
    (3)外设。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入理解嵌入式开发中的Flash、RAM和ROM(第10部分)

    发表评论