想做个STM32F407 flash写入数据程序,从CDNS(博主Ch_champion)找了个案例,原来是STM32F103CBT6芯片的案例,现改成STM32F407,写入不成功,贴出代码:
bsp_flash.c
#include "bsp_flash.h"
#include "stdio.h"
#include "string.h"
#include "usart.h"
/*判断使能读保护*/
HAL_StatusTypeDef FLASH_If_EnableReadProtection(void)
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct = { 0 };
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
HAL_StatusTypeDef result = HAL_OK;
if (OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_0)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_1;
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
{
/* Launch the option byte loading */
HAL_FLASH_OB_Launch();
/* Lock the FLASH Option Control Registers access */
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
return result;
}
/* Launch the option byte loading */
HAL_FLASH_OB_Launch();
/* Lock the FLASH Option Control Registers access */
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
result = HAL_ERROR;
}
return result;
}
/*判断读保护等级*/
HAL_StatusTypeDef Flash_If_DisableReadProtection(void)
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct = { 0 };
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
HAL_StatusTypeDef result = HAL_OK;
if (OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_1)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_0;
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
if (HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
{
/* Launch the option byte loading */
HAL_FLASH_OB_Launch();
/* Lock the FLASH Option Control Registers access */
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
return result;
}
/* Launch the option byte loading */
HAL_FLASH_OB_Launch();
/* Lock the FLASH Option Control Registers access */
HAL_FLASH_OB_Lock();
HAL_FLASH_Lock();
result = HAL_ERROR;
}
return result;
}
/*设置flash读保护*/
HAL_StatusTypeDef Set_FlashReadProtection(uint8_t mode)
{
HAL_StatusTypeDef result = HAL_ERROR;
if (mode == 1)
{
FLASH_If_EnableReadProtection();
printf("EnableReadProtection!!!\r\n");
result = HAL_OK;
}
else
{
Flash_If_DisableReadProtection();
printf("DisableReadProtection!!!\r\n");
result = HAL_OK;
}
return result;
}
/*flash初始化*/
void FLASH_If_Init(void)
{
/* Unlock the Program memory */
HAL_FLASH_Unlock();
/* Clear all FLASH flags */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGSERR | FLASH_FLAG_WRPERR);
// /* Unlock the Program memory */
HAL_FLASH_Lock();
}
/*flash写入*/
uint8_t FLASH_If_Write(uint32_t WriteAddr, uint32_t * pBuffer, uint32_t length)
{
static FLASH_EraseInitTypeDef pEraseInit;
uint32_t pageerror = 0; //定义擦除出错时,返回的Flash地址
/*以下原是STM32F103CBT6,用在STM32F407VET6编译出错*/
// HAL_FLASH_Unlock();
// pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
// pEraseInit.PageAddress = WriteAddr; //定义数据地址
// pEraseInit.NbPages = 1; //定义擦除页面数 - 页 = 1024byte
/*以下改成STM32F407VET6*/
pEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS;//
pEraseInit.Sector = WriteAddr; //定义数据地址
pEraseInit.NbSectors = 1; //定义擦除页面数 - 页 = 1024byte
HAL_FLASHEx_Erase(&pEraseInit, &pageerror); //擦除Flash
for (uint32_t i = 0; i < length; i++)
{
//HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, WriteAddr + i * 2, *(pDATA + i)); //半字节:FLASH_TYPEPROGRAM_HALFWORD
#if 0
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr + i * 4, *(pBuffer + i)); //字节:LASH_TYPEPROGRAM_WORD
#else
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr, *(uint32_t*)(pBuffer+i)) == HAL_OK)
{
/* Check the written value */
if (*(uint32_t*)WriteAddr != *(uint32_t*)(pBuffer+i))
{
HAL_FLASH_Lock();
/* Flash content doesn't match SRAM content */
return(FLASHIF_WRITINGCTRL_ERROR);
}
/* Increment FLASH destination address */
WriteAddr += 4;
}
else
{
HAL_FLASH_Lock();
/* Error occurred while writing data in Flash memory */
return (FLASHIF_WRITING_ERROR);
}
#endif
}
HAL_FLASH_Lock();
return (FLASHIF_OK);
}
uint8_t FLASH_If_Read(uint32_t ReadAddr, uint32_t *pBuffer, uint32_t DataLength)
{
uint32_t i;
for(i = 0; i < DataLength; i++)
{
pBuffer[i] = *(__IO uint32_t*)(ReadAddr);////读取4个字节.
ReadAddr += 4;//偏移4个字节.
}
return (FLASHIF_OK);
}
void Flash_Test(void)
{
SystemParamTypeDef SystemParam_default = {
.Device_id = 0x00000111,
.Hardware_Version = 0x10000111,
.Application_Version = 0x00000111,
.Application_Status = APPLICATION_NORMAL
};
SystemParamTypeDef SystemParam_update = {
.Device_id = 0x00000222,
.Hardware_Version = 0x10000222,
.Application_Version = 0x10000222,
.Application_Status = APPLICATION_UPDATED
};
SystemParamTypeDef SystemParam_read;
uint32_t page = sizeof(SystemParam_default) / sizeof(uint32_t);
printf("Flash_Test!!!\r\n");
Set_FlashReadProtection(0); //1解除读保护,0设置读保护。
FLASH_If_Init();
//memset(SystemParam_default, 0, sizeof(SystemParam_default));
memset(&SystemParam_read, 0, sizeof(SystemParam_read)); //清空结构体内容
FLASH_If_Write(DATASTOREADDR, (uint32_t*)&SystemParam_default, page);//SystemParam_default, page
FLASH_If_Read(DATASTOREADDR, (uint32_t*)&SystemParam_read, page);
printf("Device_id:0x%08lX, Hardware_Version:0x%08lX, Application_Version:0x%08lX, Application_Status:0x%08lX \r\n",
SystemParam_read.Device_id, SystemParam_read.Hardware_Version,
SystemParam_read.Application_Version, SystemParam_read.Application_Status);
HAL_Delay(100);
printf("UPDATA!!! \r\n");
//memset(&SystemParam_default, 0, sizeof(SystemParam_default)); //清空结构体内容
memset(&SystemParam_read, 0, sizeof(SystemParam_read)); //清空结构体内容
FLASH_If_Write(DATASTOREADDR, (uint32_t*)&SystemParam_update, page);
FLASH_If_Read(DATASTOREADDR, (uint32_t*)&SystemParam_read, page);
printf("Device_id:0x%08lX, Hardware_Version:0x%08lX, Application_Version:0x%08lX, Application_Status:0x%08lX \r\n",
SystemParam_read.Device_id, SystemParam_read.Hardware_Version,
SystemParam_read.Application_Version, SystemParam_read.Application_Status);
}
bsp_flash.h
#ifndef __BSP_FLASH_H
#define __BSP_FLASH_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#define DATASTOREADDR 0x0807F800 //数据存放地址 0x0800F800 0x080C0000
/* Error code */
typedef enum
{
FLASHIF_OK = 0,
FLASHIF_ERASEKO,
FLASHIF_WRITINGCTRL_ERROR,
FLASHIF_WRITING_ERROR,
FLASHIF_PROTECTION_ERRROR
}Flash_Status_t;
typedef enum {
APPLICATION_NORMAL = 0, // APP能正常稳定运行
APPLICATION_UPDATED, // APP刚更新完成,等待测试启动
APPLICATION_ERROR, // APP错误,不能正常工作
}Application_Status_t;
typedef __PACKED_STRUCT{
uint32_t Device_id; // 设备号
uint32_t Hardware_Version; // 硬件版本信息
uint32_t Application_Version; // APP软件版本
uint32_t Application_Status; // APP的状态. @Application_Status_t
uint32_t SystemParamCRC;
}SystemParamTypeDef;
void Flash_Test(void);
#ifdef __cplusplus
}
#endif
#endif
打印测试,只显示:
Flash_Test!!!
DisableReadProtection!!!
写入数据没有打印出来,应该是写入不成功。
建议你基于STM32F4系列的相关例程来编写代码吧。
STM32F4系列的Cube库里有相关例程参考,有写、有擦操作。
比方:
\STM32Cube\Repository\STM32Cube_FW_F4_V1.27.1\Projects\STM324xG_EVAL\Examples\FLASH\FLASH_EraseProgram
103和407的擦写不一样,注意擦除时的输入参数。在线仿真可以看到指定FLASH地址内容。写不进去可能是擦的区域和写的区域不一致导致的。
你不说我都不知道有官方案例,谢谢建议
写入数据不正常
写入数据不正常
串口打印结果: Flash_Test!!! DisableReadProtection!!! Device_id:0xFFFFFFFF, Hardware_Version:0xFFFFFFFF, Application_Version:0xFFFFFFFF, Application_Status:0xFFFFFFFF UPDATA!!!