stm32F407学习之27:APPFLASH模块

直接上代码
appflash.h




#ifndef __APP_FLASH_H__
#define __APP_FLASH_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "bsp_flash.h"
#include "rlog.h"


// 定义获取成员值的宏
#define GET_SYSINFO_ITEM(member) (appflash_handle()->member)
#define GET_SYSINFO_ITEM_SIZEOF(member)  sizeof(appflash_handle()->member)
#define COPY_SYSINFO_ITEM(value, member)  do { \
    memcpy(value, &appflash_handle()->member,  sizeof(appflash_handle()->member)); \
} while(0)  	

// 定义设置成员值的宏
#define SET_SYSINFO_ITEM(member, value) do { \
    memcpy(&appflash_handle()->member, value, sizeof(appflash_handle()->member)); \
} while(0)


// 定义获取任意成员偏移量的宏
#define GET_SYSINFO_ITEM_OFFSET(item) offsetof(SYS_INFO_T, item)
#define GET_SYSINFO_ITEM_ADDR(item) ((uint32_t)appflash_handle() + GET_SYSINFO_ITEM_OFFSET(item))



#define FLASH_MAGIC 0xAA55  //魔幻数

#define SYSINFO_FLASH_ADDR TEST_FLASH_ADDR
//#define SYSINFO_FLASH_ADDR UPG_FLASH_ADDR

#define BOOT_FALSH_ADDR     0x08000000   //FLASH_Sector_0
#define APP_FLASH_ADDR      0x08020000   //FLASH_Sector_5
#define UPG_FLASH_ADDR      0x08040000   //FLASH_Sector_6
#define TEST_FLASH_ADDR     0x08060000   //FLASH_Sector_7


#pragma pack(1)
typedef struct
{
	  uint8_t test_area[32];          //测试数据区
    uint16_t magic;
	  uint16_t reserve0;
    // 升级文件信息
    union {
        uint8_t upg_info[28];
        struct {
            uint8_t file_type;      // 升级文件类型
            uint8_t status;         // 升级状态
            uint16_t crc16_t;       // 文件crc值
            uint16_t reserve[2];    // 保留值
					  uint32_t file_len;      // 升级文件长度
        } upginfo;
    };

    // 基础信息
    union {
        uint8_t sys_info[192];      // 系统信息
        struct {
            uint8_t boot_version[16];   // boot版本
            uint8_t hw_version[16];     // 硬件版本
            uint8_t app_version[16];    // app版本
            uint8_t device_name[24];    // 设备名称, 默认No.1[xxxxxx]
            uint8_t local_ipaddr[4];    // 本地IP, 默认192.168.1.2
            uint8_t remote_ipaddr[4];   // 远程IP, 默认192.168.1.104
					  uint8_t gateway[4];         // 默认网关,默认192.168.1.1
					  uint8_t netmask[4];         //子网掩码,默认255.255.255.0
            uint16_t local_server_port; // 本地服务器IP,默认5001
            uint16_t remote_server_port;// 远程服务器IP,默认5002
            uint8_t mac_addr[6];        // MAC地址
					  uint8_t reserve[2];    // 保留值
					  uint8_t device_id;          //设备编号
					  
        } sysinfo;
    };

    uint8_t reserve1[768*5];
		#define  cali_area reserve1
    uint8_t reserve2[256];
} SYS_INFO_T;




void appflash_init(void);
void appflash_load(void);
void appflash_save(void);
void appflash_factory(void);


SYS_INFO_T *  appflash_handle(void);
void set_mac_addr_default(void);
void set_local_ipaddr(uint8_t *new_ip);
uint8_t* get_local_ipaddr(void);


#ifdef __cplusplus
}
#endif

#endif



appflash.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>



#include "appflash.h"
#include "wwdg_task/wwdg_task.h"



//系统默认参数
static SYS_INFO_T g_sys_info_default =
{
    .magic = FLASH_MAGIC,
    .sysinfo.boot_version = "BT_V1.0.0",
    .sysinfo.hw_version = "HW_V1.0.0",
    .sysinfo.app_version = "APP_V1.0.0",
    .sysinfo.device_name = "No.1[000000]",
    .sysinfo.local_ipaddr = {192, 168, 1, 2},
    .sysinfo.remote_ipaddr = {192, 168, 1, 104},
		.sysinfo.gateway = {192, 168, 1, 1},
		.sysinfo.netmask = {255, 255, 255, 0},
    .sysinfo.local_server_port = 5001,
    .sysinfo.remote_server_port = 5002,
    .sysinfo.mac_addr = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
		.sysinfo.device_id = 0x00,
		.sysinfo.reserve[0] = 0x00,
		.sysinfo.reserve[1] = 0x00,
		
};


//系统参数全局变量
static SYS_INFO_T g_sys_info;



//加载配置
void appflash_init(void)
{
	appflash_load();
}



void appflash_load(void)
{
    // 从闪存加载配置
	  uint32_t len = 0;
    len = Flash_Read(SYSINFO_FLASH_ADDR, (uint8_t*)&g_sys_info, sizeof(SYS_INFO_T));
	  if(len != sizeof(SYS_INFO_T)){
			RLOG_ERROR("appflash_load  Flash_Read error!! datalen = %d\r\n", len);
		}else{
			RLOG_DEBUG("appflash_load Flash_Read ok! datalen = %d\r\n", len);
    }

    // 检查魔数是否正确
    if (g_sys_info.magic != FLASH_MAGIC)
    {
        // 加载默认配置
			  RLOG_DEBUG("appflash_load save default data start.\r\n");                        
			  appflash_factory();
    }
}


void appflash_save(void)
{
	FLASH_Status status;
	//注意关狗,写FLASH需要时间
	RLOG_DEBUG("appflash_save save data  start.\r\n"); 
	status = Flash_Write(SYSINFO_FLASH_ADDR, (uint8_t*)&g_sys_info,  sizeof(SYS_INFO_T));
	RLOG_DEBUG("appflash_save Flash_Write data end.\r\n"); 
	if(status != FLASH_COMPLETE){
		RLOG_DEBUG("appflash_load Flash_Write error. status = %d\r\n", status); 
	}else{
		RLOG_DEBUG("appflash_load Flash_Write ok.\r\n"); 
	}
	return; 
}
	

//恢复出厂设置
void appflash_factory(void)
{
	uint8_t local_ipaddr[4];  //设置默认IP(IP不恢复出厂设置)
	uint8_t bak_flag = 0;
	if(g_sys_info.magic == FLASH_MAGIC){  //记录本地IP
			COPY_SYSINFO_ITEM(local_ipaddr, sysinfo.local_ipaddr);
		  bak_flag = 1;
	}
	
	memcpy(&g_sys_info, (uint8_t*)&g_sys_info_default, GET_SYSINFO_ITEM_OFFSET(reserve1));
	//memset(g_sys_info.reserve1,  0xFF, sizeof(g_sys_info.reserve1));
	set_mac_addr_default();  //设置默认MAC
	
	if(bak_flag == 1){    //还原本地IP
		//set_local_ipaddr(local_ipaddr);
	}
	
	appflash_save();
}



//获得句柄
SYS_INFO_T * appflash_handle(void)
{
	return &g_sys_info;
}


//备份IP地址
void appflash_netinfo_bakup(void){
	RTC_WriteBackupRegister(RTC_BKP_DR0, FLASH_MAGIC);
	RTC_WriteBackupRegister(RTC_BKP_DR1, *(uint32_t*)GET_SYSINFO_ITEM(sysinfo.local_ipaddr));
}


//还原IP地址
void appflash_netinfo_restore(void){
	if(RTC_ReadBackupRegister(RTC_BKP_DR0) == FLASH_MAGIC){
		uint8_t *local_ipaddr = (uint8_t *)RTC_ReadBackupRegister(RTC_BKP_DR1); 
		set_local_ipaddr(local_ipaddr);
	}
	return;
}

///////////////////////////////////////////////////////////////////////////


//设置本地MAC地址
void set_mac_addr_default(void){
	extern uint32_t GetMcuUniqueID();
	uint8_t mac[6] = {0x02, 0x00,0x00,0x00,0x00,0x00};
	uint32_t sn0 = GetMcuUniqueID();
	mac[0]=2;//高三字节(IEEE称之为组织唯一ID,OUI)地址固定为:2.0.0
	mac[1]=0;
	mac[2]=0;
	mac[3]=(sn0>>16)&0XFF;//低三字节用STM32的唯一ID
	mac[4]=(sn0>>8)&0XFFF;;
	mac[5]=sn0&0XFF; 
	
	SET_SYSINFO_ITEM(sysinfo.mac_addr, mac);
	return;
	
}


//设置本地IP
void set_local_ipaddr(uint8_t *new_ip)
{
	//appflash_netinfo_bakup();  //备份
	SET_SYSINFO_ITEM(sysinfo.local_ipaddr, new_ip);
}


//获得本地IP
uint8_t* get_local_ipaddr(void)
{
	uint8_t* local_ip = GET_SYSINFO_ITEM(sysinfo.local_ipaddr);
	
	return local_ip;
}









测试用例


//获得系统信息
static void test_sysinfo(int argc, char *argv[]){
	  //读系统数据
	  if(argc == 1){
			RLOG_INFO("magic = %04X\r\n", GET_SYSINFO_ITEM(magic));
			//RLOG_HEX("local_ipaddr", GET_SYSINFO_ITEM(sysinfo.local_ipaddr), 4);
			//RLOG_HEX("remote_ipaddr", GET_SYSINFO_ITEM(sysinfo.remote_ipaddr), 4);
			RLOG_INFO("app_version = %s\r\n", GET_SYSINFO_ITEM(sysinfo.app_version));
			RLOG_INFO("device_name = %s\r\n", GET_SYSINFO_ITEM(sysinfo.device_name));
			uint8_t *mac = appflash_handle()->sysinfo.mac_addr;
			RLOG_INFO("macaddr = %02x %02x %02x %02x %02x %02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
		
			uint8_t *ip = appflash_handle()->sysinfo.local_ipaddr;
			RLOG_INFO("local_ipaddr = %d.%d.%d.%d \r\n", ip[0], ip[1], ip[2], ip[3]);
			ip = appflash_handle()->sysinfo.remote_ipaddr;
			RLOG_INFO("local_ipaddr = %d.%d.%d.%d \r\n", ip[0], ip[1], ip[2], ip[3]);
			//读校准标志
			RLOG_HEX("cali_flag", get_cali_flag(0), NODE_ID_MAX);
		}else if(argc == 6){
			if (strcmp(argv[1], "set_local_ipaddr") == 0){  //设置本地IP
				 uint8_t ip[4] = {0, 0, 0, 0};
				 ip[0] = atoi(argv[2]);ip[1] = atoi(argv[3]);
				 ip[2] = atoi(argv[4]);ip[3] = atoi(argv[5]);
				 set_local_ipaddr(ip);
			}else if (strcmp(argv[1], "set_remote_ipaddr") == 0){  //设置远程IP
				 uint8_t ip[4] = {0, 0, 0, 0};
				 ip[0] = atoi(argv[2]);ip[1] = atoi(argv[3]);
				 ip[2] = atoi(argv[4]);ip[3] = atoi(argv[5]);
				 SET_SYSINFO_ITEM(sysinfo.remote_ipaddr, ip);
			}
		}else if(argc == 2){
			if (strcmp(argv[1], "save") == 0){  //保存系统参数
				 appflash_save();
			}else if (strcmp(argv[1], "factory") == 0){  //恢复出厂设置
				appflash_factory();
			}
		}
		return;
}
MSH_CMD_EXPORT(test_sysinfo, test_sysinfo test eg);
posted @ 2025-09-19 10:08  cupid8505  阅读(4)  评论(0)    收藏  举报