Bootstrap

FLASH闪存的读取、擦除、编程+stm32f103c8t6

一、stm32寄存器地址介绍

二、FLASH简介

(1)STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口可以对程序存储器和选项字节进行擦除和编程

(2) 读写FLASH的用途:利用程序存储器的剩余空间来保存掉电不丢失的用户数据;通过在程序中编程(IAP),实现程序的自我更新

(3)在线编程(In-Circuit Programming -ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序

(4)在程序中编程(In-Application Programming - IAP)可以使用微控制器支持的任—种通信接口下载程序。(首先在 程序更新后不影响的地方自己写一个bootloader程序,需要更新程序之后,程序跳转到自定义的bootloader程序,然后通过任意一种通信接口接收数据,然后在通过对flash的读写,将接受到的数据放到程序正常运行的地方)

三、闪存模块组织

四、flash解锁和加锁

FPEC共有三个键值:

  • RDPRT键=Ox000000A5
  • KEY1 = Ox45670123
  • KEY2 = OxCDEF89AB

解锁步骤:
        复位后,FPEC被保护,不能写入FLASH_CR

        在FLASH_KEYR先写入KEY1,再写入KEY2,解锁

        错误的操作序列会在下次复位前锁死FPEC和FLASH_CR

加锁步骤:
        设置FLASH_CR中的LOCK位(置1)  锁住FPEC和FLASH_CR

加锁和解锁的目的是防止误操作

五、使用指针访问存储器

#define    _IO   volatile

使用指针指定地址下的存储器:
        uint16_t Data = *((_I0 uint16_t *)(0×08000000)) ;

使用指针指定地址下的存储器:
        *((___IO uint16_t*)(0x0800ee0e)) = ox1234;

六、编程过程

 

针对以上编程过程,库函数已经帮我们写好了,我们只需要调用函数接口即可

七、选项字节

当往RDP里面写入数据之后,需要往nRDP里面写入对应的补码,如果检测到RDP和nRDP的数据不是补码关系, 那么解除读保护错误。但是此操作硬件会自动帮我们完成

八、器件电子签名

        电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名

        闪存容量寄存器:
        基地址:Ox1FFF F7EO   大小: 16位

        产品唯一身份标识寄存器:
        基地址: Ox1FFF F7E8    大小: 96位

九、代码书写

#include "MyFLASH.h"

uint32_t MyFLASH_Readword (uint32_t Address)
{
    return *( (__Io uint32_t *)(Address) );
}

uint16_t MyFLASH_ReadHalfword (uint32_t Address)
{
    return *((__1o uint16_t *)(Address) );
}

uint8_t MyFLASH_ReadByte (uint32_t Address)
{
    return * ( (__Io uint8_t * ) (Address)) ;
}

void MyFLASH_EraseAllPages (void)
{
    FLASH_Unlock () ;
    FLASH_EraseAllPages ( ) ;
    FLASH_Lock () ;
}

void MyFLASH_ErasePage (uint32_t PageAddress)
{
    FLASH_Unlock ( );
    FLASH_ErasePage (PageAddress ) ;
    FLASH_Lock ();
}

void MyFLASH_Programword (uint32_t Address, uint32_t Data)
{
    FLASH_Unlock ( ) ;
    FLASH_Programword (Address,Data) ;
    FLASH_Lock ( ) ;
}

void MyFIASH_ProgramHalfword (uint32_t Address,uint16_t Data)
{
    FLASH_unlock ( ) ;
    FLASH_ProgramHalfword (Address,Data) ;
    FLASH_Lock ();
}

#include "MyFLASH.h"
#include "store.h"

uint16_t store_Data [ 512];

//上电调用初始化函数,然后就可以加载之前存储在flash中的数据
void store_Init (void)
{
    //0x0800Fc00最后一页的首地址;OxA5A5为了判断之前是否存储数据
    if (MyFLASH_ReadHalfword(0x0800Fc00)!= OxA5A5)
    {
        MyFLASH_ErasePage (0x0800FC00);
        MyFLASH_ProgramHalfword (0x0800FC00,0xA5A5);
        // 一页的大小是1K,存储数据数组大小是半字。第一位存储标志位,后面数据位清0
        for (uint16_t i = l; i < 512; i ++)
        {
            MyFLASH_ProgramHalfword (0x0800FC00 + i * 2,0x0000);
        }
    }
    for (uint16_t i = 0; i <512; i ++)
    {
        store_Data [i] = MyFLASH_ReadHalfword (0x0800FCO0 + i * 2);
    }
}

//调用保存函数就会将数据写入flash存储器中
void store_save (void)
{
    MyFLASH_ErasePage (0x080OFC00) ;
    for (uint16_t i = 0; i < 512; i ++)
    {
        MyFLASH_ProgramHalfword (0x0800Fc00 + i * 2,store_Data[i]);
    }
}

void store_clear (void)
{
    for (uint16_t i = 1; i < 512; i ++)
    {
        store_Data[i] = 0x0000;
    }
    store_save () ;
}

;