概述
介绍使用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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复