我是靠谱客的博主 小巧长颈鹿,最近开发中收集的这篇文章主要介绍STM32用HAL库写内部FLASH,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

介绍使用HAL库对内部FLASH进行写操作

1、为什么要用FLASH存Code:FLASH有掉电保护功能

在这里插入图片描述

主存储器:存放代码和数据常量,平时说的芯片内部FLASH的大小就是指的主存储器的大小。起始地址0x08000000,Boot0、Boot1都接GND时从0x08000000开始运行代码
启动程序代码:存储ST自带的启动程序,用来通过串口下载代码。Boot0接3.3V,Boot1接GND时运行这里面的代码
用户选项字节区:配置Flash读写保护、复位、看门狗等功能,共16字节,由选项控制寄存器控制
接口寄存器:整个FLASH的控制机构

说起Flash肯定会提到扇区、页,其实页就是扇区。页的大小要在《STM32F10x闪存编程参考手册》里找。STM32F10x有256页,每页2KB。

向Flash写数据前必须先将页擦除,因为Flash只能将1置0不能把0置1。页为最小擦除单位。擦除后为0xFFFF…。

2、对内部Flash的写入流程

在这里插入图片描述

3、写FLASH时要注意不应覆盖原有的数据,所以要看好空间分布

查看工程空间分布:Keil的一般编译后在目录里的Listing文件中的.map文件里,翻到后面出现 “Memory Map of the image”
如下,ROM区域的内容就是Flash内的代码,Base是基地址

某工程的 ROM 存储器分布映像

Memory Map of the image  //存储分布映像

  Image Entry point : 0x08000131
/* 程序 ROM 加载空间 */
  Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000124c, Max: 0x00010000, ABSOLUTE)
/* 程序 ROM 执行空间 */
    Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x0000123c, Max: 0x00010000, ABSOLUTE)
/* 地址分布列表 */
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x08000000   0x08000000   0x00000130   Data   RO            3    RESET               startup_stm32f103xe.o
    0x08000130   0x08000130   0x00000000   Code   RO         1758  * .ARM.Collect$$$$00000000  mc_w.l(entry.o)
    0x08000130   0x08000130   0x00000004   Code   RO         1765    .ARM.Collect$$$$00000001  mc_w.l(entry2.o)
    0x08000134   0x08000134   0x00000004   Code   RO         1768    .ARM.Collect$$$$00000004  mc_w.l(entry5.o)
    0x08000138   0x08000138   0x00000000   Code   RO         1770    .ARM.Collect$$$$00000008  mc_w.l(entry7b.o)
    0x08000138   0x08000138   0x00000000   Code   RO         1772    .ARM.Collect$$$$0000000A  mc_w.l(entry8b.o)
    0x08000138   0x08000138   0x00000008   Code   RO         1773    .ARM.Collect$$$$0000000B  mc_w.l(entry9a.o)
    0x08000140   0x08000140   0x00000004   Code   RO         1780    .ARM.Collect$$$$0000000E  mc_w.l(entry12b.o)
    0x08000144   0x08000144   0x00000000   Code   RO         1775    .ARM.Collect$$$$0000000F  mc_w.l(entry10a.o)
    0x08000144   0x08000144   0x00000000   Code   RO         1777    .ARM.Collect$$$$00000011  mc_w.l(entry11a.o)
    0x08000144   0x08000144   0x00000004   Code   RO         1766    .ARM.Collect$$$$00002712  mc_w.l(entry2.o)
    0x08000148   0x08000148   0x00000024   Code   RO            4    .text               startup_stm32f103xe.o
    0x0800016c   0x0800016c   0x00000024   Code   RO         1763    .text               mc_w.l(memseta.o)
    0x08000190   0x08000190   0x00000024   Code   RO         1781    .text               mc_w.l(init.o)
......

执行空间Size: 0x0000123c
加载空间Size: 0x0000124c

执行空间比加载空间小的原因:部分RW_data的变量被放到RAM空间执行

4、写Flash你必须知道的几个HAL库函数

对FLASH解锁、上锁

//定义解锁参数
#define FLASH_KEY1                          0x45670123UL 
#define FLASH_KEY2                          0xCDEF89ABUL 
/**解锁
  * @brief  Unlock the FLASH control register access
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_Unlock(void)
{
  HAL_StatusTypeDef status = HAL_OK;

  if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
  {
    /* Authorize the FLASH Registers access */
    WRITE_REG(FLASH->KEYR, FLASH_KEY1);
    WRITE_REG(FLASH->KEYR, FLASH_KEY2);

    /* Verify Flash is unlocked */
    if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
    {
      status = HAL_ERROR;
    }
  }
  return status;
}
/**上锁
  * @brief  Locks the FLASH control register access
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_Lock(void)
{
  /* Set the LOCK Bit to lock the FLASH Registers access */
  SET_BIT(FLASH->CR, FLASH_CR_LOCK);
  return HAL_OK;  
}

解锁就是向FLASH->KEYR寄存器里写入两个解锁参数,
上锁就是将FLASH->CR寄存器FLASH_CR_LOCK位置1

擦除函数

/**
  * @brief  Perform a mass erase or erase the specified FLASH memory pages
  * @note   To correctly run this function, the @ref HAL_FLASH_Unlock() function
  *         must be called before.
  *         Call the @ref HAL_FLASH_Lock() to disable the flash memory access 
  *         (recommended to protect the FLASH memory against possible unwanted operation)
  * @param[in]  pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
  *         contains the configuration information for the erasing.
  *         选择擦除方式的结构体
  * @param[out]  PageError pointer to variable  that
  *         contains the configuration information on faulty page in case of error
  *         (0xFFFFFFFF means that all the pages have been correctly erased)
  *         声明一个指针变量,如果擦除成功变量值为0xFFFFFFFF,擦除失败则把失败地址保存到变量中
  * @retval HAL_StatusTypeDef HAL Status
  */
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
{
  HAL_StatusTypeDef status = HAL_ERROR;
  uint32_t address = 0U;

  /* Process Locked */
  __HAL_LOCK(&pFlash);

  /* Check the parameters */
  assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));

  if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
  {
    {
      /* Mass Erase requested for Bank1 */
      /* Wait for last operation to be completed */
      if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
      {
        /*Mass erase to be done*/
        FLASH_MassErase(FLASH_BANK_1);
        
        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
        
        /* If the erase operation is completed, disable the MER Bit */
        CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
      }
    }
  }
  else
  {
    /* Page Erase is requested */
    /* Check the parameters */
    assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress));
    assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages));
   {
      /* Page Erase requested on address located on bank1 */
      /* Wait for last operation to be completed */
      if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
      {
        /*Initialization of PageError variable*/
        *PageError = 0xFFFFFFFFU;
        
        /* Erase page by page to be done*/
        for(address = pEraseInit->PageAddress;
            address < ((pEraseInit->NbPages * FLASH_PAGE_SIZE) + pEraseInit->PageAddress);
            address += FLASH_PAGE_SIZE)
        {
          FLASH_PageErase(address);
          
          /* Wait for last operation to be completed */
          status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
          
          /* If the erase operation is completed, disable the PER Bit */
          CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
          
          if (status != HAL_OK)
          {
            /* In case of error, stop erase procedure and return the faulty address */
            *PageError = address;
            break;
          }
        }
      }
    }
  }

  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);

  return status;
}

TypeErase 选择擦除的方式,HAL库提供两种:PAGES、MASSERASE,定义在stm32f1xx_hal_flash_ex.h中

/** @defgroup FLASHEx_Type_Erase Type Erase
  * @{
  */ 
#define FLASH_TYPEERASE_PAGES     0x00U  /*!<Pages erase only*/
#define FLASH_TYPEERASE_MASSERASE 0x02U  /*!<Flash mass erase activation*/

写入数据

/**
  * @brief  Program halfword, word or double word at a specified address
  * @note   The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
  *         The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
  *
  * @note   If an erase and a program operations are requested simultaneously,    
  *         the erase operation is performed before the program one.
  *  
  * @note   FLASH should be previously erased before new programmation (only exception to this 
  *         is when 0x0000 is programmed)
  *
  * @param  TypeProgram:  Indicate the way to program at a specified address.
  *                       This parameter can be a value of @ref FLASH_Type_Program
  * @param  Address:      Specifies the address to be programmed.
  * @param  Data:         Specifies the data to be programmed
  * 
  * @retval HAL_StatusTypeDef HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
  HAL_StatusTypeDef status = HAL_ERROR;
  uint8_t index = 0;
  uint8_t nbiterations = 0;
  
  /* Process Locked */
  __HAL_LOCK(&pFlash);

  /* Check the parameters */
  assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
  assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
  
  if(status == HAL_OK)
  {
    if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
    {
      /* Program halfword (16-bit) at a specified address. */
      nbiterations = 1U;
    }
    else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
    {
      /* Program word (32-bit = 2*16-bit) at a specified address. */
      nbiterations = 2U;
    }
    else
    {
      /* Program double word (64-bit = 4*16-bit) at a specified address. */
      nbiterations = 4U;
    }

    for (index = 0U; index < nbiterations; index++)
    {
      FLASH_Program_HalfWord((Address + (2U*index)), (uint16_t)(Data >> (16U*index)));
      
      /* In case of error, stop programation procedure */
      if (status != HAL_OK)
      {
        break;
      }
    }
  }

  /* Process Unlocked */
  __HAL_UNLOCK(&pFlash);

  return status;
}

TypeProgram 选择写入数据的方式,HAL库提供三种:HALFWORD,WORD,DOUBLEWORD,定义在stm32f1xx_hal_flash.h中

/** @defgroup FLASH_Type_Program FLASH Type Program
  * @{
  */ 
#define FLASH_TYPEPROGRAM_HALFWORD             0x01U  /*!<Program a half-word (16-bit) at a specified address.*/
#define FLASH_TYPEPROGRAM_WORD                 0x02U  /*!<Program a word (32-bit) at a specified address.*/
#define FLASH_TYPEPROGRAM_DOUBLEWORD           0x03U  /*!<Program a double word (64-bit) at a specified address*/

函数的具体内容详见HAL库,本文做了删减

最后

以上就是小巧长颈鹿为你收集整理的STM32用HAL库写内部FLASH的全部内容,希望文章能够帮你解决STM32用HAL库写内部FLASH所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部