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);