天天看点

STM32F4内部Flash读写

STM32F4内部Flash读写

 之前的文章中介绍过STM32F0列的内部Flash读写《​​STM32CubeMX之内部Flash读写​​》,F1系列的也是一样的。而F4系列的单片机与F0和F1略有不同,HAL库对应的函数也不同,今天来简单介绍一下。

 以TM32F429IGT6单片机为例,其内部Flash起始地址是:0x08000000,大小是0x00100000。

先看一下其内部Flash的Sector划分:

STM32F4内部Flash读写

我们需要关心的只有Main memory。可以看到,每个Sector的大小不一样,前128K被分为了4个16K和1个64K,后面每个Sector都是128K。而F1系列的每个Sector大小相同都是1K或2K。

我们知道,Flash在写的时候必须先整块Sector擦除才能写入。F0/F1系列的直接调用函数擦除指定地址的Sector就行,比如我们需要擦除0x08000000起始地址的Sector,程序如下:

FLASH_EraseInitTypeDef f;


f.TypeErase = FLASH_TYPEERASE_PAGES;
f.PageAddress = 0x08000000;
f.NbPages = 1;
PageError = 0;


HAL_FLASH_Unlock();  
HAL_FLASHEx_Erase(&f, &PageError);      

而F4系列HAL库的Flash擦除函数,其形参为Sector的编号而非实际地址。比如我们需要擦除0x08000000起始地址的Sector,需要先获取Sector的编号0,作为函数的形参再调用擦除函数,程序如下:

Sect = 0;
FLASH_Erase_Sector(sect,FLASH_VOLTAGE_RANGE_3);      

因此,我们需要编写一个函数用于获取Sector的编号,程序如下:

uint32_t sectStartAddr[13]=
{
    0x08000000,//0
    0x08004000,//1
    0x08008000,//2
    0x0800c000,//3
    0x08010000,//4
    0x08020000,//5
    0x08040000,//6
    0x08060000,//7
    0x08080000,//8
    0x080a0000,//9
    0x080c0000,//10
    0x080e0000,//11
    0x08100000
};
//获取Sector的编号
int GetSectorFromAddress(uint32_t address)
{
    int sect;


    if( address < 0x08000000 || address > 0x080FFFFF )
        return -1;


    for( int i=0; i<12; i++ )
    {
        if( address >= sectStartAddr[i] && address < sectStartAddr[i+1] )
        {
            sect = i;
            break;
        }
    }
    return sect;
}      

则擦除0x08000000地址Sector的程序如下:

sect = GetSectorFromAddress(0x08000000);
FLASH_Erase_Sector(sect,FLASH_VOLTAGE_RANGE_3);      

写入函数与F0/F1系列的一样,直接调用HAL库函数即可,函数形参的地址为绝对地址:

startAddr = 0x08000000;
endAddr = 0x08000020;
for(i = startAddr; i < endAddr; i += 4)
{
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, i, *data++);
}      

    读取函数也是一样的,直接读取指定地址即可:

uint32_t data = *(uint32_t *)(0x08000000);      

      当然,擦除写入之前不要忘了解锁和上锁的操作:

HAL_FLASH_Unlock();//解锁flash
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);


//......擦除写入操作


HAL_FLASH_Lock();      

   内部Flash读写可以用于存储一些参数,也是实现IAP程序升级的关键,下一篇文章将介绍通过U盘实现单片机程序升级。

​​

继续阅读