STM32_HAL_使用FPEC实现闪存的读写

STM32的FLASH结构

  1. 主存储器(Main Memory):这是STM32中最大的存储区域,用于存储用户的程序代码、常量数据以及程序运行时不变的数据。STM32的主存储器通常被组织为多个扇区(sector),每个扇区的大小不同,可以是几个KB到几十KB不等。这些扇区可以被独立擦除,但不能独立编程。

  2. 信息块(Information Block):这个区域通常包含了STM32微控制器的唯一标识码(UID)、产品型号、生产批次等信息。这些信息对于产品的追踪和生产管理是非常有用的,但是在正常编程时不会修改这部分数据。

    1. 系统存储器(System Memory):这部分存储区域通常用于存储ST公司提供的bootloader。系统存储器的内容是在生产时被固化在芯片中的,用户一般不能修改。

    2. 选项字节(Option Bytes):这些字节用于配置微控制器的某些选项,例如读保护、写保护、BOR级别(Brown-out Reset Level)、软件或硬件看门狗等。选项字节的内容可以通过软件编程来修改,但需要遵循特定的编程流程。

  3. OTP区域(One-Time Programmable Area):这是一些只能编程一次的区域,用于存储一些关键的安全信息或者配置参数。一旦编程之后,这些信息就无法更改。

型号范例

STM32 F 103 Z E T 6

家族

“STM32 “表示32bit的MCU

产品类型

“F”表示基础型

具体特性

“103”基础型

引脚数目

“Z”表示144个引脚, 其他常用的为: C表示48引脚, R表示64引脚, V表示100引脚, “Z”表示144个引脚, B表示208引脚, N表示216引脚

FLASH大小

E表示512KB, 其他常用的为: 4表示16KB(小容量ld), 6表示32KB(小容量ld), 8表示64KB(中容量md), B表示128KB(中容量md), C表示256 KB(大容量hd), E表示512 KB(大容量hd), F表示768KB(超大容量xl), G表示1024KB(超大容量xl),

封装

“T”表示QFP封装,这个是最常用的封装

温度

“6”表示温度等级为A :-40~85°

STM32 Flash编程的注意事项:

  1. 扇区和页的结构:STM32的Flash扇区和页的大小根据不同的型号会有所不同。例如,一些STM32型号的页大小可能是128字节或256字节,而扇区大小可能是2KB、4KB、8KB等。

  2. 编程(写)操作:编程操作只能在已经擦除的页上进行,且一次只能编程一页。你不能在未擦除的页上直接编程,因为这可能会导致数据损坏。

  3. 擦除操作:在编程之前,目标页所在的扇区必须先被擦除。擦除操作会清除扇区内的所有数据,将所有位设置为1。

  4. 写保护:STM32的Flash通常具有写保护功能,以防止意外写入或擦除。在编程之前,可能需要确保相应的写保护功能被禁用。

  5. 地址对齐:在编程时,写入的数据必须与页的起始地址对齐。如果写入的数据跨越了页的边界,就需要分成多次编程操作。

  6. 固件升级:在进行固件升级时,通常会选择一个特定的扇区来存储新的固件映像,这个扇区通常被称为“引导扇区”或“更新扇区”。

  7. 特殊扇区:有些扇区可能被保留用于存储Bootloader或其他重要的系统代码,因此在编程时应该避免对这些扇区进行操作。

stm32的FPEC与FSMC的区别

在STM32中,FPEC和FSMC是两个不同的功能模块,它们服务于不同的目的。

  1. FPEC (Flash Program and Erase Controller):

    • FPEC是STM32的一个模块,负责控制内置的Flash存储器的编程(烧写)和擦除操作。
    • 它允许微控制器在运行时重新编程自己的Flash,这意味着可以不通过外部编程器而直接在微控制器上更新固件。
    • FPEC还支持扇区擦除和整个Flash的擦除操作,确保了固件更新的灵活性。
  2. FSMC (Flexible Static Memory Controller):

    • FSMC是STM32的一个接口,它允许微控制器与外部静态存储器(如SRAM、ROM、NOR闪存和NAND闪存)进行通信。
    • FSMC支持多种访问模式,包括8位、16位和32位,以及不同的时序控制,以适应各种外部存储设备的操作需求。
    • FSMC的灵活性使其可以用于多种应用,如扩展微控制器的存储空间,或者连接图形液晶显示器(LCD)等设备。

在使用STM32进行嵌入式系统设计时,开发者可以根据需要选择是否使用FPEC和FSMC。例如,当需要频繁更新固件或者使用外部存储器扩展存储空间时,这两个模块就特别有用。

FPEC

STM32微控制器中的FPEC(Flash Program and Erase Controller)是负责管理闪存编程和擦除的硬件模块。FPEC允许微控制器对自己的内置闪存进行读写操作,这是固件更新、数据存储和其他类似应用的基础。

FPEC的主要功能包括:

  1. 编程(Programming):将数据写入闪存。STM32的闪存通常以半字(16位)或字(32位)为单位进行编程。

  2. 擦除(Erasing):清除闪存中的数据,通常是以扇区(sector)为单位的。STM32的闪存扇区大小不一,从几个KB到几十KB不等。

  3. 读取(Reading):从闪存中读取数据,这是最简单的操作,不需要特殊的硬件支持。

  4. 选项字节编程(Option Byte Programming):配置微控制器的某些选项,如读保护、写保护、BOR级别等。

步骤

用STM32的标准库或HAL库:

  1. 配置闪存接口

    • 确保时钟已经使能到闪存接口。
    • 如果需要,配置闪存访问时间(LATENCY),这通常在高速时钟下是必需的。
  2. 解锁闪存编程控制寄存器

    • 使用HAL_FLASH_Unlock()FLASH_Unlock()函数来解锁闪存编程和擦除控制。
  3. 擦除扇区

    • 使用HAL_FLASHEx_Erase()FLASH_ErasePage()函数来选择并擦除要写入的扇区。STM32的闪存被分为多个扇区,每个扇区可以独立擦除。
    • 等待擦除完成,可以通过检查闪存状态寄存器来判断。
  4. 编程闪存

    • 使用HAL_FLASH_Program()FLASH_ProgramWord()函数将数据编程到闪存中。这个操作通常是以半字或字为单位的。
    • 确保在编程之前扇区已经被擦除。
    • 等待编程完成,并检查闪存状态寄存器是否有错误发生。
  5. 读取闪存

    • 直接通过指针访问闪存地址来读取数据。闪存的读取操作是最简单的,不需要特殊的硬件支持。
  6. 配置选项字节(如果需要):

    • 使用HAL_FLASH_OB_Program()FLASH_OB_Program()函数来配置选项字节。
    • 选项字节的编程可能需要特定的序列和条件,比如在执行选项字节编程之前可能需要禁用全局中断。
  7. 锁定闪存编程控制寄存器

    • 使用HAL_FLASH_Lock()FLASH_Lock()函数来锁定闪存编程和擦存控制,防止意外的写入。
  8. 错误处理

    • 在编程和擦除过程中,如果发生错误,通常需要通过读取闪存状态寄存器来确定错误类型,并采取相应的措施。

框图

HAL配置

STM32CubeMX可以帮助用户初始化FPEC(Flash Programming and Erase Controller),但这是在生成的代码中自动完成的,而不是通过STM32CubeMX的用户界面直接配置

1打开GPIO中断

2配置时钟

3打开UART以显示数据

 

即可生成代码

代码编写

由于内部FLASH本身存储有程序数据,若不是有意删除某段程序代码,一般不应修改程序空间的内容,所以在使用 内部FLASH存储其它数据前需要了解哪一些空间已经写入了程序代码,存储了程序代码的扇区都不应作任何修改。 通过查询应用程序编译时产生的“*.map”后缀文件,可以了解程序存储到了哪些区域,

找.map文件(可以确定变量的地址)

步骤操作:

  1. 编译项目:首先确保你已经编译了你的STM32项目。在Keil 5中,这通常是通过点击“Build”菜单下的“Rebuild all”来完成的。

  2. 查看项目设置:在Keil 5中,默认情况下.map文件是在编译过程中自动生成的。你可以在项目的选项设置中确认这一点。点击“Project”菜单下的“Options for Target”打开目标选项窗口。

  3. 输出目录:在目标选项窗口中,选择“Output”标签页。在这里,你可以看到“Select folder for object files”和“Select folder for listing files”。这些选项指定了对象文件和列表文件(包括.map文件)的输出目录。

  4. 查找.map文件:在指定的输出目录中,查找与你项目同名的.map文件。例如,如果你的项目名为MyProject.uvprojx,那么.map文件可能被命名为MyProject.map

  5. 打开.map文件:找到.map文件后,你可以使用文本编辑器(如Notepad++或Visual Studio Code)打开它,以便查看和解析其中的内容。

截取重要的一段解释

Execution Region ER_IROM1确实指的是用户编写程序所要的空间大小,即用户编写的程序代码在Flash存储器中实际占用的空间。这个区域的大小取决于用户编写的代码、链接器分配的其他段(如数据段、未初始化数据段等)的大小,以及链接器在编译和链接过程中所做的优化和调整。

==============================================================================

Memory Map of the image
/*程序的入口点,即程序开始执行的地址。在这个特定的例子中,Image Entry point的值为0x08000131。

这意味着在STM32微控制器启动时,它将从这个地址开始执行程序。这个地址是在Flash存储器中的,对于STM32系列微控制器,通常起始地址是0x08000000,但由于Flash存储器是分段的,不同的段可能会有不同的起始地址。*/
  Image Entry point : 0x08000131
 /*程序ROM加载空间*/

  Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000137c, Max: 0x00080000, ABSOLUTE)

//Load Region LR_IROM1:
Base: 基地址,即Flash存储器中这个区域的起始地址,这里是0x08000000。
Size: 区域的大小,这里是0x0000137c字节。
Max: 区域的最大值,即Flash存储器中这个区域可以使用的最大地址,这里是0x00080000。
ABSOLUTE: 表示这个区域的地址是绝对的,即在整个Flash存储器中是固定不变的。

/*程序ROM执行空间*/
    Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x0000136c, Max: 0x00080000, ABSOLUTE)

//Execution Region ER_IROM1:
Exec base: 执行基地址,与加载基地址相同,这里是0x08000000。
Load base: 加载基地址,与加载基地址相同,这里是0x08000000。
Size: 执行区域的大小,这里是0x0000136c字节。
Max: 执行区域的最大值,与加载区域的最大值相同,这里是0x00080000。
ABSOLUTE: 表示这个区域的地址是绝对的。

//总结来说,Load Region LR_IROM1和Execution Region ER_IROM1描述的是同一个Flash区域,这个区域用于存储程序代码。Load Region是指程序被加载到Flash中的地址,而Execution Region是指程序实际执行时的地址。由于STM32微控制器在启动时会从Flash中加载程序代码并执行,所以这两个地址是相同的。

    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x08000000   0x08000000   0x00000130   Data   RO            3    RESET               startup_stm32f103xe.o
    0x08000130   0x08000130   0x00000008   Code   RO         2341  * !!!main             c_w.l(__main.o)
    0x08000138   0x08000138   0x00000034   Code   RO         2500    !!!scatter          c_w.l(__scatter.o)
    0x0800016c   0x0800016c   0x0000001a   Code   RO         2502    !!handler_copy      c_w.l(__scatter_copy.o)
    0x08000186   0x08000186   0x00000002   PAD
    0x08000188   0x08000188   0x0000001c   Code   RO         2504    !!handler_zi        c_w.l(__scatter_zi.o)
    0x080001a4   0x080001a4   0x00000002   Code   RO         2368    .ARM.Collect$$libinit$$00000000  c_w.l(libinit.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2375    .ARM.Collect$$libinit$$00000002  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2377    .ARM.Collect$$libinit$$00000004  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2380    .ARM.Collect$$libinit$$0000000A  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2382    .ARM.Collect$$libinit$$0000000C  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2384    .ARM.Collect$$libinit$$0000000E  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2387    .ARM.Collect$$libinit$$00000011  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2389    .ARM.Collect$$libinit$$00000013  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2391    .ARM.Collect$$libinit$$00000015  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2393    .ARM.Collect$$libinit$$00000017  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2395    .ARM.Collect$$libinit$$00000019  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2397    .ARM.Collect$$libinit$$0000001B  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2399    .ARM.Collect$$libinit$$0000001D  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2401    .ARM.Collect$$libinit$$0000001F  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2403    .ARM.Collect$$libinit$$00000021  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2405    .ARM.Collect$$libinit$$00000023  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2407    .ARM.Collect$$libinit$$00000025  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2411    .ARM.Collect$$libinit$$0000002C  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2413    .ARM.Collect$$libinit$$0000002E  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2415    .ARM.Collect$$libinit$$00000030  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000000   Code   RO         2417    .ARM.Collect$$libinit$$00000032  c_w.l(libinit2.o)
    0x080001a6   0x080001a6   0x00000002   Code   RO         2418    .ARM.Collect$$libinit$$00000033  c_w.l(libinit2.o)
    0x080001a8   0x080001a8   0x00000002   Code   RO         2438    .ARM.Collect$$libshutdown$$00000000  c_w.l(libshutdown.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2451    .ARM.Collect$$libshutdown$$00000002  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2453    .ARM.Collect$$libshutdown$$00000004  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2455    .ARM.Collect$$libshutdown$$00000006  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2458    .ARM.Collect$$libshutdown$$00000009  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2461    .ARM.Collect$$libshutdown$$0000000C  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2463    .ARM.Collect$$libshutdown$$0000000E  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000000   Code   RO         2466    .ARM.Collect$$libshutdown$$00000011  c_w.l(libshutdown2.o)
    0x080001aa   0x080001aa   0x00000002   Code   RO         2467    .ARM.Collect$$libshutdown$$00000012  c_w.l(libshutdown2.o)
    0x080001ac   0x080001ac   0x00000000   Code   RO         2343    .ARM.Collect$$rtentry$$00000000  c_w.l(__rtentry.o)
    0x080001ac   0x080001ac   0x00000000   Code   RO         2345    .ARM.Collect$$rtentry$$00000002  c_w.l(__rtentry2.o)
    0x080001ac   0x080001ac   0x00000006   Code   RO         2357    .ARM.Collect$$rtentry$$00000004  c_w.l(__rtentry4.o)
    0x080001b2   0x080001b2   0x00000000   Code   RO         2347    .ARM.Collect$$rtentry$$00000009  c_w.l(__rtentry2.o)
    0x080001b2   0x080001b2   0x00000004   Code   RO         2348    .ARM.Collect$$rtentry$$0000000A  c_w.l(__rtentry2.o)
    0x080001b6   0x080001b6   0x00000000   Code   RO         2350    .ARM.Collect$$rtentry$$0000000C  c_w.l(__rtentry2.o)
    0x080001b6   0x080001b6   0x00000008   Code   RO         2351    .ARM.Collect$$rtentry$$0000000D  c_w.l(__rtentry2.o)
    0x080001be   0x080001be   0x00000002   Code   RO         2372    .ARM.Collect$$rtexit$$00000000  c_w.l(rtexit.o)
    0x080001c0   0x080001c0   0x00000000   Code   RO         2420    .ARM.Collect$$rtexit$$00000002  c_w.l(rtexit2.o)
    0x080001c0   0x080001c0   0x00000004   Code   RO         2421    .ARM.Collect$$rtexit$$00000003  c_w.l(rtexit2.o)
    0x080001c4   0x080001c4   0x00000006   Code   RO         2422    .ARM.Collect$$rtexit$$00000004  c_w.l(rtexit2.o)
    0x080001ca   0x080001ca   0x00000002   PAD
    0x080001cc   0x080001cc   0x00000040   Code   RO            4    .text               startup_stm32f103xe.o
    0x0800020c   0x0800020c   0x0000004e   Code   RO         2337    .text               c_w.l(rt_memclr_w.o)
    0x0800025a   0x0800025a   0x00000006   Code   RO         2339    .text               c_w.l(heapauxi.o)
    0x08000260   0x08000260   0x0000004a   Code   RO         2359    .text               c_w.l(sys_stackheap_outer.o)
    0x080002aa   0x080002aa   0x00000012   Code   RO         2361    .text               c_w.l(exit.o)
    0x080002bc   0x080002bc   0x00000008   Code   RO         2369    .text               c_w.l(libspace.o)
    0x080002c4   0x080002c4   0x0000000c   Code   RO         2430    .text               c_w.l(sys_exit.o)
    0x080002d0   0x080002d0   0x00000002   Code   RO         2441    .text               c_w.l(use_no_semi.o)
    0x080002d2   0x080002d2   0x00000000   Code   RO         2443    .text               c_w.l(indicate_semi.o)
    0x080002d2   0x080002d2   0x00000002   Code   RO          213    i.BusFault_Handler  stm32f1xx_it.o
    0x080002d4   0x080002d4   0x00000002   Code   RO          214    i.DebugMon_Handler  stm32f1xx_it.o
    0x080002d6   0x080002d6   0x00000004   Code   RO           13    i.Error_Handler     main.o
    0x080002da   0x080002da   0x00000002   PAD
    0x080002dc   0x080002dc   0x00000024   Code   RO         1328    i.HAL_Delay         stm32f1xx_hal.o
    0x08000300   0x08000300   0x000001f8   Code   RO         1638    i.HAL_GPIO_Init     stm32f1xx_hal_gpio.o
    0x080004f8   0x080004f8   0x0000000c   Code   RO         1332    i.HAL_GetTick       stm32f1xx_hal.o
    0x08000504   0x08000504   0x00000010   Code   RO         1338    i.HAL_IncTick       stm32f1xx_hal.o
    0x08000514   0x08000514   0x00000024   Code   RO         1339    i.HAL_Init          stm32f1xx_hal.o
    0x08000538   0x08000538   0x00000040   Code   RO         1340    i.HAL_InitTick      stm32f1xx_hal.o
    0x08000578   0x08000578   0x0000003c   Code   RO          288    i.HAL_MspInit       stm32f1xx_hal_msp.o
    0x080005b4   0x080005b4   0x00000040   Code   RO         1804    i.HAL_NVIC_SetPriority  stm32f1xx_hal_cortex.o
    0x080005f4   0x080005f4   0x00000024   Code   RO         1805    i.HAL_NVIC_SetPriorityGrouping  stm32f1xx_hal_cortex.o
    0x08000618   0x08000618   0x0000012c   Code   RO         1496    i.HAL_RCC_ClockConfig  stm32f1xx_hal_rcc.o
    0x08000744   0x08000744   0x0000004c   Code   RO         1505    i.HAL_RCC_GetSysClockFreq  stm32f1xx_hal_rcc.o
    0x08000790   0x08000790   0x00000320   Code   RO         1508    i.HAL_RCC_OscConfig  stm32f1xx_hal_rcc.o
    0x08000ab0   0x08000ab0   0x00000028   Code   RO         1809    i.HAL_SYSTICK_Config  stm32f1xx_hal_cortex.o
    0x08000ad8   0x08000ad8   0x0000007c   Code   RO         1073    i.HAL_TIMEx_MasterConfigSynchronization  stm32f1xx_hal_tim_ex.o
    0x08000b54   0x08000b54   0x0000005a   Code   RO          350    i.HAL_TIM_Base_Init  stm32f1xx_hal_tim.o
    0x08000bae   0x08000bae   0x00000002   PAD
    0x08000bb0   0x08000bb0   0x00000024   Code   RO          166    i.HAL_TIM_Base_MspInit  tim.o
    0x08000bd4   0x08000bd4   0x000000dc   Code   RO          359    i.HAL_TIM_ConfigClockSource  stm32f1xx_hal_tim.o
    0x08000cb0   0x08000cb0   0x00000048   Code   RO          167    i.HAL_TIM_MspPostInit  tim.o
    0x08000cf8   0x08000cf8   0x000000cc   Code   RO          422    i.HAL_TIM_PWM_ConfigChannel  stm32f1xx_hal_tim.o
    0x08000dc4   0x08000dc4   0x0000005a   Code   RO          425    i.HAL_TIM_PWM_Init  stm32f1xx_hal_tim.o
    0x08000e1e   0x08000e1e   0x00000002   Code   RO          427    i.HAL_TIM_PWM_MspInit  stm32f1xx_hal_tim.o
    0x08000e20   0x08000e20   0x000000b4   Code   RO          430    i.HAL_TIM_PWM_Start  stm32f1xx_hal_tim.o
    0x08000ed4   0x08000ed4   0x00000002   Code   RO          215    i.HardFault_Handler  stm32f1xx_it.o
    0x08000ed6   0x08000ed6   0x00000002   PAD
    0x08000ed8   0x08000ed8   0x00000058   Code   RO          141    i.MX_GPIO_Init      gpio.o
    0x08000f30   0x08000f30   0x0000009c   Code   RO          168    i.MX_TIM2_Init      tim.o
    0x08000fcc   0x08000fcc   0x00000002   Code   RO          216    i.MemManage_Handler  stm32f1xx_it.o
    0x08000fce   0x08000fce   0x00000002   Code   RO          217    i.NMI_Handler       stm32f1xx_it.o
    0x08000fd0   0x08000fd0   0x00000002   Code   RO          218    i.PendSV_Handler    stm32f1xx_it.o
    0x08000fd2   0x08000fd2   0x00000002   Code   RO          219    i.SVC_Handler       stm32f1xx_it.o
    0x08000fd4   0x08000fd4   0x00000004   Code   RO          220    i.SysTick_Handler   stm32f1xx_it.o
    0x08000fd8   0x08000fd8   0x0000005e   Code   RO           14    i.SystemClock_Config  main.o
    0x08001036   0x08001036   0x00000002   Code   RO         2299    i.SystemInit        system_stm32f1xx.o
    0x08001038   0x08001038   0x0000008c   Code   RO          443    i.TIM_Base_SetConfig  stm32f1xx_hal_tim.o
    0x080010c4   0x080010c4   0x0000001a   Code   RO          444    i.TIM_CCxChannelCmd  stm32f1xx_hal_tim.o
    0x080010de   0x080010de   0x00000014   Code   RO          454    i.TIM_ETR_SetConfig  stm32f1xx_hal_tim.o
    0x080010f2   0x080010f2   0x00000010   Code   RO          455    i.TIM_ITRx_SetConfig  stm32f1xx_hal_tim.o
    0x08001102   0x08001102   0x00000002   PAD
    0x08001104   0x08001104   0x00000060   Code   RO          456    i.TIM_OC1_SetConfig  stm32f1xx_hal_tim.o
    0x08001164   0x08001164   0x0000006c   Code   RO          457    i.TIM_OC2_SetConfig  stm32f1xx_hal_tim.o
    0x080011d0   0x080011d0   0x00000068   Code   RO          458    i.TIM_OC3_SetConfig  stm32f1xx_hal_tim.o
    0x08001238   0x08001238   0x00000050   Code   RO          459    i.TIM_OC4_SetConfig  stm32f1xx_hal_tim.o
    0x08001288   0x08001288   0x00000022   Code   RO          461    i.TIM_TI1_ConfigInputStage  stm32f1xx_hal_tim.o
    0x080012aa   0x080012aa   0x00000024   Code   RO          463    i.TIM_TI2_ConfigInputStage  stm32f1xx_hal_tim.o
    0x080012ce   0x080012ce   0x00000002   Code   RO          221    i.UsageFault_Handler  stm32f1xx_it.o
    0x080012d0   0x080012d0   0x00000020   Code   RO         1811    i.__NVIC_SetPriority  stm32f1xx_hal_cortex.o
    0x080012f0   0x080012f0   0x00000038   Code   RO           15    i.main              main.o
    0x08001328   0x08001328   0x00000012   Data   RO         1509    .constdata          stm32f1xx_hal_rcc.o
    0x0800133a   0x0800133a   0x00000010   Data   RO         2300    .constdata          system_stm32f1xx.o
    0x0800134a   0x0800134a   0x00000002   PAD
    0x0800134c   0x0800134c   0x00000020   Data   RO         2498    Region$$Table       anon$$obj.o


    Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x0800136c, Size: 0x000006b8, Max: 0x00010000, ABSOLUTE)

    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x20000000   0x0800136c   0x0000000c   Data   RW         1346    .data               stm32f1xx_hal.o
    0x2000000c   0x08001378   0x00000004   Data   RW         2302    .data               system_stm32f1xx.o
    0x20000010        -       0x00000048   Zero   RW          169    .bss                tim.o
    0x20000058        -       0x00000060   Zero   RW         2370    .bss                c_w.l(libspace.o)
    0x200000b8        -       0x00000200   Zero   RW            2    HEAP                startup_stm32f103xe.o
    0x200002b8        -       0x00000400   Zero   RW            1    STACK               startup_stm32f103xe.o


==============================================================================

有哪些函数

1解锁与上锁

解锁
HAL_StatusTypeDef HAL_FLASH_Unlock(void);
HAL_OK: 操作成功。
HAL_ERROR: 操作失败。
HAL_BUSY: FLASH控制器忙,操作不能执行。
HAL_TIMEOUT: 操作超时。


上锁
HAL_StatusTypeDef HAL_FLASH_Unlock(void);
HAL_OK: 操作成功。
HAL_ERROR: 操作失败。
HAL_BUSY: FLASH控制器忙,操作不能执行。
HAL_TIMEOUT: 操作超时。

2写操作

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);



TypeProgram:指定要执行的编程操作类型。这可以是FLASH_TYPEPROGRAM_WORD(写入一个字),FLASH_TYPEPROGRAM_HALFWORD(写入一个半字),或者FLASH_TYPEPROGRAM_DOUBLEWORD(写入一个双字)。
Address:要写入数据的FLASH地址。
Data:要写入的数据。即使你只写入一个字,这个参数也是一个64位的,因为HAL库支持写入双字操作。



HAL_OK: 操作成功。
HAL_ERROR: 操作失败。
HAL_BUSY: FLASH控制器忙,操作不能执行。
HAL_TIMEOUT: 操作超时。

3闪存擦除函数

HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError);

pEraseInit:指向一个FLASH_EraseInitTypeDef结构的指针,该结构包含了擦除操作的参数,如擦除类型、起始页、页数等。
PageError:指向一个uint32_t变量的指针,该变量用于存储擦除过程中出现错误的页码(如果有的话)。


  1. TypeErase:这个成员定义了擦除操作的类型。它可以是以下值之一,这些值通常在@ref FLASH_TYPE_ERASE中定义:

    • FLASH_TYPEERASE_MASSERASE:执行整个Flash存储器的擦除。
    • FLASH_TYPEERASE_PAGEERASE:仅擦除指定的一个或多个页面。
  2. Banks:这个成员用于在大规模擦除时选择要擦除的银行。STM32微控制器可能有多个Flash存储器银行。这个参数的值通常在@ref FLASH_BANK_ERASE中定义。对于页面擦除,这个参数不被使用。

  3. Page:这个成员指定了页面擦除操作的起始页面。页面是从0开始编号的,并且这个值必须位于0和MAX_PAGE_NUMBER - 1之间。MAX_PAGE_NUMBER是微控制器Flash的最大页面数。对于大规模擦除,这个参数不被使用。

  4. NbPages:这个成员指定了要擦除的页面数量。这个值必须在1和(MAX_PAGE_NUMBER - 起始页的值)之间。对于大规模擦除,这个参数不被使用。

4获取闪存状态函数

HAL_FLASH_StateTypeDef HAL_FLASH_GetState(void);

这个函数可以用来检查FLASH是否处于忙碌状态

返回值
HAL_FLASH_STATE_BUSY: FLASH忙,一个编程或擦除操作正在进行中。
HAL_FLASH_STATE_ERROR: FLASH发生错误,可能是因为编程或擦除操作失败。
HAL_FLASH_STATE_READY: FLASH准备就绪,没有进行中的操作,并且没有错误。

5等待操作完成函数

HAL_StatusTypeDef HAL_FLASH_WaitForLastOperation(uint32_t Timeout);

当你需要对FLASH进行操作时,通常需要等待上一个操作完成。这可以通过检查FLASH的状态或者使用特定的等待函数来实现


Timeout:等待操作完成的超时时间(以毫秒为单位)。
这个函数返回一个HAL_StatusTypeDef类型的值,用于指示操作是否成功。可能的返回值包括:

HAL_OK: 操作成功完成。
HAL_ERROR: 操作失败。
HAL_TIMEOUT: 等待操作完成时发生超时。

6读取闪存特定地址的函数      //库中没有

main.h源码

使用了UART   GPIO   

不用初始换写入的闪存   库已经初始化了

思路

uart输出地址内的数据1秒一次

按键点击一下触发中断中断内部是写了,先将地址的值先擦除,在写入数据数据会将原来的值加一

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t address =0x0807F800;//地址data_32的地址(在MOP文件中看一下哪些位置没有写入数据)

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
	
		uint32_t data_values=*(uint32_t*)address;//要写入的数据
	
	
		//解锁  FLASH(闪存)
		HAL_FLASH_Unlock();
		
		//擦除页          										//必须擦除要写入的页在写入不然数据不能保存或写入失败
		FLASH_EraseInitTypeDef eraseInit;
											
		//eraseInit.Banks=FLASH_BANK_1;//只有一块闪存时可以不写  //指的是那一块
		eraseInit.NbPages=1;//擦除几页
		eraseInit.PageAddress=address;//开始地址
		eraseInit.TypeErase=FLASH_TYPEERASE_PAGES;//按页擦除
	
		//变量存放错误  值为0xffffff  为成功
		uint32_t pag=0xFFFFFFFF;
		//开始擦写
		HAL_FLASHEx_Erase(&eraseInit,&pag);
	
		//写入数据
		//1代表地址是多大16 32 64 2:地址3:数据
		if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,address,(data_values+1))==HAL_OK){
			
				uint8_t a[]={"写入成功"};
				HAL_UART_Transmit(&huart1,a,8,20);
		}else{
			
				uint8_t a[]={"写入失败"};
				HAL_UART_Transmit(&huart1,a,8,20);
		}
	
		//上锁
		HAL_FLASH_Lock();
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		char data_char[19];
		//闪存地址的值
		long data_=*(uint32_t*)address;
		//将值转换为字符
		sprintf(data_char,"数据是:%ld",data_);
		HAL_UART_Transmit(&huart1,(uint8_t*)data_char,18,20);
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

重点总结

在STM32微控制器中,Flash存储器的未编程区域通常会被初始化为0xFF(因为Flash擦除后的状态是所有位都是1)。然而,SRAM(静态随机存取存储器)的未初始化区域则可能包含随机数据,这些数据是上电后或者上次执行程序后遗留下来的。

使用前必须先解锁,之后在上所

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/658098.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

项目十三:搜狗——python爬虫实战案例

根据文章项目十二:简单的python基础爬虫训练-CSDN博客的简单应用,这一次来升级我们的技术,那么继续往下看,希望对技术有好运。 还是老样子,按流程走,一条龙服务,嘿嘿。 第一步:导入…

git 学习随笔

git 学习随笔 基本概念 git 对待数据类似快照流的形式而不是类似 cvs 那样的纪录文件随时间逐步积累的差异 git 中所有数据在存储钱都会计算校验和(hash) 三种状态:已提交(committed),已修改(modified),已暂存(staged)。 add…

20240528解决飞凌的OK3588-C的核心板可以刷机不能连接ADB的问题

20240528解决飞凌的OK3588-C的核心板可以刷机不能连接ADB的问题 2024/5/28 16:34 OS:Linux R4/Buildroot 硬件接了3条线出来,一直可以刷机,但是链接ADB异常。 【总是链接不上】 Z:\OK3588_Linux_fs\kernel\arch\arm64\boot\dts\rockchip\OK3…

防火墙如何端口映射?

防火墙端口映射(Firewall Port Mapping)是一种网络技术,通过对防火墙配置进行调整,允许外部网络用户访问内部网络中的指定端口。该技术使得外部用户可以通过公共网络访问内部网络中的特定服务或应用程序,从而实现远程访…

HackTheBox-Machines--Beep

Beep测试过程 1 信息收集 nmap端口扫描 gryphonwsdl ~ % nmap -sC -sV 10.129.137.179 Starting Nmap 7.94 ( https://nmap.org ) at 2024-05-28 14:39 CST Nmap scan report for 10.129.229.183 Host is up (0.28s latency). Not shown: 988 closed tcp ports (conn-refused…

【微服务】部署mysql集群,主从复制,读写分离

两台服务器做如下操作 1.安装mysqldocker pull mysql:5.72.启动以及数据挂载 mkdir /root/mysql/data /root/mysql/log /root/mysql/conf touch my.conf //mysql的配置文件docker run --name mysql \ -e MYSQL_ROOT_PASSWORD123456 \ -v /root/mysql/data:/var/lib/mysql \ -v…

FaceChain-FACT:开源10秒写真生成,复用海量LoRa风格,基模友好型写真应用

github开源地址:https://github.com/modelscope/facechain/tree/main/facechain_adapter 魔搭创空间应用体验:魔搭社区 一、效果演示 FaceChain FACT的代码和模型目前已经在github和modelscope创空间上同步开源。FaceChain FACT具有简单的交互式界面设…

Rohm公司参展欧洲PCI盛会

​德国历史悠久的文化名城纽伦堡,即将迎来一场科技盛宴——欧洲PCI展览会。在这个为期三天的盛会中(6月11日至13日),Rohm公司将以璀璨之姿,特别聚焦宽带隙(WBG)设备的璀璨光芒。 此次&#xff0…

linux安装srs

获取srs cd /opt git clone -b 4.0release https://gitee.com/ossrs/srs.git cd srs/trunk 启动srs ./objs/srs -c conf/srs.conf ./etc/init.d/srs status 访问http://192.168.220.146:8080/出现下方图片说明安装成功 点击进入SRS控制台看到下方图片

AI视频教程下载:使用ChatGPT进行商务写作

你将学到什么? 学习如何将ChatGPT集成到你的写作过程中,并有效地将其用作商务写作的个人写作助手。 学习如何使用ChatGPT生成想法,提高你的书面沟通的结构、清晰度和连贯性。 你将学习使用ChatGPT的最佳实践,包括如何自定义其设…

【Flutter】显式动画

🔥 本文由 程序喵正在路上 原创,CSDN首发! 💖 系列专栏:Flutter学习 🌠 首发时间:2024年5月29日 🦋 欢迎关注🖱点赞👍收藏🌟留言🐾 目…

k8s群集调度之 pod亲和 node亲和 标签指定

目录 一 调度约束 1.1K8S的 List-Watch 机制 ⭐⭐⭐⭐⭐ 1.1.1Pod 启动典型创建过程 二、调度过程 2.1Predicate(预选策略) 常见的算法 2.2priorities(优选策略)常见的算法 三、k8s将pod调度到指定node的方法 3.1指…

FPGA中的乒乓操作

为什么不直接选用一个缓存更大的FIFO而选用乒乓操作为什么乒乓操作可以实现低速处理高速数据乒乓操作适用哪些场景 一、乒乓操作结构 首先先介绍一下乒乓操作的原理,其结构如下: 输入选择单元负责将数据送到数据缓冲模块,然后输出选择单元负…

网络工程师---第四十三天

1、网络地址转换请简述DNS服务器迭代查询与递归的区别? 2、请从技术方面简述RAIDO、RAID1、RAID3、 RAID5的特点? 3、请从层次结构、部署设备和功能配置方面描述层次化的网络结构? 4、请简述IPSECVPN和AH和ESP的区别? 5、请简述ID…

用友U8 Cloud linkntb.jsp SQL注入漏洞复现(CNVD-C-2023-708748)

0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP,主要聚焦成长型、创新型企业,提供企业级云ERP整体解决方案。 0x02 漏洞概述 用友U8 Cloud linkntb.jsp 接口处存在SQL注入漏洞,未授权的攻击者可通过此漏洞获取数据库权限,从而盗取用户数据,造成用户信息泄露。 0x…

vue组件的基本使用方法

组件 【1】组件是什么? 组件就是:扩展 HTML 元素,封装可重用的代码,目的是复用例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html组件把js,cs…

[java基础揉碎]文件IO流

目录 文件 什么是文件 文件流​编辑 常用的文件操作 创建文件方式一 创建文件方式二 创建文件方式三 tip:为什么new file 了还有执行createNewFile?new File的时候其实是在内存中创建了文件对象, 还没有在磁盘中, 当执行createNewFile的时候才是往磁盘中写入​编辑 …

Golang 创建第一个web项目(Gin + Gorm)

1. 写这篇博客的由来: 当你想使用最快的框架创建项目的时候是不是有点束手无策? 当你想配置数据库写 SQL 甚至不知道如何写,文件夹都不知道建在哪里? 😄因为Golang 目前并没有 JAVA 那种硬性规范,但是…

基于JCEF实现网页资源性能分析

文章目录 1、需求2、实现代码3、运行效果 1、需求 在使用chrome浏览器访问页面时,浏览器自带的开发者工具可以查看页面每个资源的资源大小和加载时间。 这个功能可以让我们直接知道接口或资源的耗时情况和大小情况,如果存在性能问题,可以进…

LES物流执行系统,在离散制造行业有那些作用和价值?

离散制造企业往往面临的是多品种、小批量的非标订单生产,传统推动式物流系统已经无法应对计划变化滞后,各车间、工序之间难以衔接等情况,特别是密集劳动力的电子行业,非标产品 SKU 种类繁多,物料配送复杂,对…